I am new to programming. I use Python 3.9.5 and VSCode on Windows 10. In video 14 titled "Exercise", chapter 3 titled "Control Flow" of Mosh Hamedani's "Complete Python Mastery" course, this assignment was provided:
Write a program that displays the even numbers between 1 to 10.
The output is supposed to be:
2
4
6
8
We have 4 even numbers
My program produced the intended output, but I was wondering how I can improve my code. I saw other people's answers to this question, but I'm focusing on how I can work on what I already have specifically.
number_of_numbers = 0
number = 0
while number < 8:
number += 2
number_of_numbers += 1
print(number)
print(f"We have {number_of_numbers} even numbers")
Some people suggested changes such as using range and for loops. However, when I implemented them, there came several issues.
for number in range(0, 10, 2): # The problem with this is that it prints 0 as well. How do I stop it from printing zero?
print(number)
number_of_numbers += 1
print(f"We have {number_of_numbers} even numbers") # This also says we have 9 even numbers instead of 4.
I was wondering if anyone could help improve my code and explain how to resolve those issues. Thank you very much in advance!
5 Answers 5
List Comprehensions :
- Using list-comprehension to get list of even numbers, so you can have storage of these elements and further you can have your desired operations on it !
>>> numbers = [_ for _ in range(1, 11)]
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> even_numbers = [num for num in numbers if num % 2 == 0]
>>> even_numbers
[2, 4, 6, 8, 10]
Create your own function :
- Using python three to create a function that return list of even number from a range of 1 to 10.
>>> from typing import List
>>> def even_nums(numbers: List[int]) -> int :
>>> n = len(numbers)
>>> res = []
>>> if n < 1 or n == 1 :
>>> return numbers
>>> for i in numbers :
>>> if i % 2 == 0 :
>>> res.append(i)
>>> # print(i)
>>> return res
>>> numbers: List[int] = [ i for i in range(1, 11)]
>>> print(even_nums(numbers))
- Customize above function.
>>> def even_nums(start_number: int, end_number: int) -> int :
>>> # Try adding edge cases.
>>> # this code is naive implementation
>>> start = start_number
>>> end = end_number + 1
>>> numbers = []
>>> res = []
>>> for i in range(start, end) :
>>> numbers.append(i)
>>> for i in numbers :
>>> if i%2 == 0 :
>>> res.append(i)
>>> return res
>>> print(even_nums(10, 20))
>>> [10, 12, 14, 16, 18, 20]
You don’t need to use lists or keep track of how many evens you’ve seen, you can do that with the range object alone. Like lists, range objects know their lengths.
def print_evens(start, stop):
start += start % 2 # start on even
range_object = range(start, stop, 2)
print(
*range_object, # spread evens out as arguments
f"we have {len(range_object)} even numbers",
sep="\n"
)
print_evens(1, 10)
On a side note, you can also subscript range objects as if they were lists, e.g. range(2, 10, 2)[1] == 4
. Internally, they use math to figure out which number to return when subscripted.
Lastly, if you did need to create a list of all the numbers from a range object, it’s fastest and most readable to just convert it to a list, e.g.:
number_list = list(range(2, 10, 2))
Python ranges allow you to specify the starting number and a step. The code you were experimenting with is heading in the right direction:
for number in range(0, 10, 2): print(number) number_of_numbers += 1 print(f"We have {number_of_numbers} even numbers")
The first argument to range
is the first number in the range. In this case, we want the list to start with 2
rather than 0
, so we should write range(2, 10, 2)
.
The trouble with counting using += 1
or ++
is that we have to make sure the counter is correctly initialised to 0 at the beginning.
If we assign the range to a variable, we can count its elements directly, using the built-in len()
function:
numbers = range(2,10,2)
len(numbers) # returns 4
We can use join()
to print many values at once, so we don't even need to write a loop:
print('\n'.join(str(n) for n in numbers))
print(f'We have {len(numbers)} even numbers.')
-
1\$\begingroup\$ You could also use
map
instead of a generator expression:'\n'.join(map(str, numbers))
\$\endgroup\$my_stack_exchange_account– my_stack_exchange_account2021年12月21日 21:17:33 +00:00Commented Dec 21, 2021 at 21:17 -
\$\begingroup\$ This overcomplicates things. Why use two
print()
calls, if it can be done with just one? \$\endgroup\$Richard Neumann– Richard Neumann2021年12月21日 23:26:34 +00:00Commented Dec 21, 2021 at 23:26 -
\$\begingroup\$ @richard, totally subjective, but I find the two separate calls easier to comprehend. And you can't use
\n
within an expression in an f-string (which was what I initially tried). \$\endgroup\$Toby Speight– Toby Speight2021年12月22日 07:42:47 +00:00Commented Dec 22, 2021 at 7:42
The task at hand can be solved with a rather simple one-liner:
print(*(numbers := list(filter(lambda x: not x % 2, range(1, 10)))), f'We have {len(numbers)} even numbers', sep='\n')
Explanation
filter(lambda x: not x % 2, range(1, 10))
This filters the numbers from 1 to 9 for even numbers. It returns a filter
object which is an iterator.
numbers := list(...)
This converts the filter object into a list, which is an iterable and assigns it to the name numbers
, which we will use later.
*(numbers := ...)
This unpacks our list of even integers as arguments for print()
.
f'We have {len(numbers)} even numbers'
This is the last line, as per the task, to print the amount of even numbers. We use the assigned name from above and use an f-string to format it accordingly.
sep='\n'
Since all output should be written on separate lines as per the task, we use the newline character to seperate our items to print.
Summary
There is no need to write complicated custom filter functions. Keep it simple and stupid.
It completely depends on what you need I am proving code assuming few situations.
Compact
print([x for x in range(0,10,2)])
output [0,2,4,6,8]
self explanatory
for number in range(0,10):
if number%2==0:
print(number)
output: 0 2 4 6 8
generic when code is made generic it can used on numerous cases rather than sticking on to one particular case or by just manually editing values.
def evenNUMgenerator(start,end):
for number in range(start,end):
if number%2==0:
print(number)
start=0
end=10
#in case
#start=int(input())
#end=int(input())
evenNUMgenerator(start,end)
output: 0 2 4 6 8
Your code is already good enough and there is no correct way to code until its efficient enough and follows coding standards.
-
\$\begingroup\$ This isn't much of a review - it seems more like a selection of alternative versions (but including
0
as a value between 1 and 10?) without any explanation of how they are better. \$\endgroup\$Toby Speight– Toby Speight2021年12月21日 20:09:38 +00:00Commented Dec 21, 2021 at 20:09 -
\$\begingroup\$ I am completely new to code review I am from stack overflow. Just learning and answered it in stack overflow perspective hope u understand and encourage me. \$\endgroup\$gilf0yle– gilf0yle2021年12月21日 20:19:53 +00:00Commented Dec 21, 2021 at 20:19
range(2,10,2)
gives you a range starting from 2 instead. And no need to count as you go - if you havenumbers = range(2,10,2)
, thenlen(numbers)
returns the 4 that you expect. \$\endgroup\$