Python 中的函数:从入门到精通_python函数的用法
函数是一种良好、有效且简洁的编写代码的方式,Python 拥有丰富的函数集,这些函数非常容易实现并且编写起来很有趣。功能到位,避免编写重复代码。想象一下计算 100 名学生的分数。您是否要重复类似的计算 100 次,从而编写 100 行代码?当然不是!您可以编写一个计算分数的函数,并使用 for 循环调用该函数 100 次来完成工作。这将需要 5-6 行代码!
在Python中,函数由关键字“def”定义,后跟函数名、括号和冒号。您想要从函数(代码行)中执行的操作称为函数体。与 if-else 和 for 循环一样,函数体需要缩进以指示函数的范围。该函数的语法如下 -
def 函数名():
''' 函数体 — 代码行 '''
'''返回值(可选)'''
Python 中有两种形式的函数。一种是内置函数,另一种是用户自定义函数。
无参数函数
无参数函数是不带任何参数的函数,即括号为空。看下面的代码可以更好地理解 -
def print_your_country():
print('Hi! I am from India')
print_your_country()
Output -
Hi! I am from India
前一个函数没有返回任何内容,但在调用时打印了一条语句。非参数函数也可能返回值(如果已定义)。让我们来看看 -
带 return 语句的非参数函数
def return_your_country():
return 'India'
country = return_your_country()
print('Hi! I am from {}'.format(country))
Output -
Hi! I am from India
上面的函数返回单词“India”,然后我们将其存储在变量 Country 中,然后打印出存储的值。您也可以直接从 print 语句调用该函数。像这样的东西 -
def return_your_country():
return 'India'
print('Hi! I am from {}'.format(return_your_country()))
Output -
Hi! I am from India
最常见的是使用参数函数。这些是括号中具有 n 个参数的函数。这些函数是通过传递以函数名称开头的参数来调用的。通过查看下面的代码和语法,会更好地理解它 -
参数功能
参数函数语法 -
def 函数名(参数1, 参数2):
''' 函数体 '''
''' 返回语句(可选) '''
#这里调用函数
函数名(参数 1,参数 2)
这里在函数定义中使用了两个参数,在函数调用中使用了两个变量来显示语法。可以使用 n 个参数,但建议保持函数简洁。
def get_two_numbers_added(num1, num2):
summation = num1+num2
print('Addition of two numbers is - ',summation)
get_two_numbers_added(10,20)
Output -
Addition of two numbers is - 30
让我们看看上面的函数使用 return 语句会是什么样子 -
带 return 语句的参数函数
def return_two_numbers_added(num1, num2):
summation = num1+num2
return summation
summation = return_two_numbers_added(10,20)
print('Addition of two numbers is - ',summation)
Output -
Addition of two numbers is - 30
使用关键字参数的参数函数
num1 和 num2 是参数的名称,在调用函数时使用了 num1 和 num2 变量名称。查看关键字参数的顺序,先写了 num2,然后写了 num1,但由于使用了关键字(即变量名与函数参数相同),所以 num2 参数的值将存储在 num2 参数和 num1 的值中将存储在 num1 参数中。因此,第一个参数 num1 为 20,第二个参数 num2 为 10。
def two_numbers_added(num1, num2):
summation = num1+num2
print('{} + {} = {}'.format(num1, num2, summation))
two_numbers_added(num2 = 10, num1 = 20)
Output -
20 + 10 = 30
现在,如果没有使用关键字参数并将其写为“two_numbers_add(10, 20)”,会发生什么?在本例中,num1 将存储 10,num2 将存储 20,因为它遵循值的位置。
def two_numbers_added(num1, num2):
summation = num1+num2
print('{} + {} = {}'.format(num1, num2, summation))
two_numbers_added(10, 20)
Output -
10 + 20 = 30
使用关键字和位置参数的参数函数
现在,可以同时使用位置参数和关键字参数。请记住,在函数调用中,关键字参数应始终位于位置参数之后,否则将收到错误。查看下面的代码,尝试更改关键字参数和位置参数的位置,看看会出现什么错误 -
def three_numbers_added(num1, num2, num3):
summation = num1+num2+num3
print('{} + {} + {} = {}'.format(num1, num2, num3, summation))
three_numbers_added(50, num3 = 10, num2 = 20)
Output -
50 + 20 + 10 = 80
使用默认参数的参数函数
还可以使用带有默认参数的函数,这意味着参数变量中已经存储了默认值。考虑下面的函数,num3 是默认参数,值为 10,但是当调用该函数时,声明了 num3 变量来存储 40,因此它将覆盖 num3 默认参数,得到 40 作为值。
def three_numbers_added(num1, num2, num3 = 10):
summation = num1+num2+num3
print('{} + {} + {} = {}'.format(num1, num2, num3, summation))
three_numbers_added(num1 = 50, num3 = 40, num2 = 30)
Output-
50 + 30 + 40 = 120
在下面的函数中,没有为 num3 提供任何值,因此它存储了默认值 10。请记住,默认参数应始终位于非默认参数之后,即最后在函数调用中。尝试更改参数的位置以查看出现的错误 -
def three_numbers_added(num1, num2, num3 = 10):
summation = num1+num2+num3
print('{} + {} + {} = {}'.format(num1, num2, num3, summation))
three_numbers_added(num1 = 50, num2 = 30)
Output -
50 + 30 + 10 = 90
使用可变数量参数的参数函数
有时,可能不确定需要传递给函数的值的数量。在这些情况下,使用 *args 代表多个位置参数, **kwargs 代表多个关键字参数。浏览下面的代码 -
def information(*args, **kwargs):
print('These are positional arguments - ',args)
print('These are keyworded arguments - ',kwargs)
information('Hello', 123, 4.75, name = 'Nishi Paul', city = 'Kolkata')
Output -
These are positional arguments - ('Hello', 123, 4.75)
These are keyworded arguments - {'name': 'Nishi Paul', 'city': 'Kolkata'}
Python 中的局部变量
ython 中的函数是缩进定义函数作用域的。在函数作用域中定义的变量称为局部变量,无法从函数内部访问这些局部变量(除们接下来将看到的一些特殊情况)。看下面的代码,num变量被传递到函数中,并且num的值在函数内部被改变。由于 num 是函数的局部变量,因此对其所做的更改不会反映在函数外部的变量 num 上。
def add_number_ten_times(num):
for i in range(10):
num += i
print('Inside the function, number in num variable is - ', num)
num = 2
print('Before calling the function, number in num variable is - ',num)
add_number_ten_times(num)
print('After calling the function, number in num variable is - ', num)
Output -
Before calling the function, number in num variable is - 2
Inside the function, number in num variable is - 47
After calling the function, number in num variable is - 2
Python 中的全局变量
全局变量是在函数外部定义的变量,可以在函数作用域内部使用。
operation = 'Self Addition'
def add_number_ten_times(num):
for i in range(10):
num += i
print(operation, ' is taking place in side function giving value - ', num)
num = 2
print('Before calling the function, number in num variable is - ',num)
add_number_ten_times(num)
print('After calling the function, number in num variable is - ', num)
Output -
Before calling the function, number in num variable is - 2
Self Addition is taking place in side function giving value - 47
After calling the function, number in num variable is - 2
在Python中,我们可以使用关键字global将局部变量变成全局变量。在下面的函数中,我们首先声明一个变量num wit value 2,然后调用该函数。该函数正在对 num 执行加法运算,并且该变量在函数内声明为全局变量。因此对此变量所做的任何更改都将反映到函数外部的变量 num 上并覆盖它。
def add_number_ten_times():
global num
for i in range(10):
num += i
print('Inside the function, number in num variable is - ', num)
num = 2
print('Before calling the function, number in num variable is - ',num)
add_number_ten_times()
print('After calling the function, number in num variable is - ', num)
Output -
Before calling the function, number in num variable is - 2
Inside the function, number in num variable is - 47
After calling the function, number in num variable is - 47
在使用函数时我们需要谨慎对待变量作用域,否则我们可能会丢失数据。因此,总而言之,函数体内部定义的任何内容对于该特定函数都是本地的(如果未使用 global 关键字定义变量),而函数范围之外定义的任何内容都可以被您定义的所有函数访问。当我们了解嵌套函数时,这一点就会很清楚。
嵌套函数——内部函数
嵌套函数是函数内的函数,可以有任意数量的嵌套函数,但这会增加代码的复杂性和可读性。所以我们通常会进入函数体的第二层。例如,在下面的代码中,我们将一个函数定义为outer_body,另一个函数定义为inner_body。现在,inner_body 函数只能从outer_body 函数访问,因为它是在outer_body 范围内定义的。
def outer_body(x):
def inner_body(y):
return x*y
return inner_body(5)
outer_body(10)
Output-
50
所有嵌套函数都可以使用函数上方范围内定义的任何内容。例如,在下面的代码中,可以从函数的所有层访问变量 a。现在,如果在outer_body函数内部定义变量b,那么它只能被outer_body和inner_body访问,但如果不是全局的,则不能被主体访问。亲自尝试变量声明的不同组合!
a = 100
print('From inside main body - ', a)
def outer_body(x):
print('From inside outer_body function -', a)
def inner_body(y):
print('From inside inner_body function -', a)
return x*y
return inner_body(5)
outer_body(10) #value returned by function
Output -
From inside main body - 100
From inside outer_body function - 100
From inside inner_body function - 100
50
嵌套函数——闭包函数和函数作为对象
python 中的函数也可以被视为对象。这意味着您可以返回一个函数(不仅仅是函数的值,而是整个函数)并将其存储在变量中。让我们通过下面的例子来理解这一点 -
external_body 是带有变量 x 的外部函数,inner_body 是带有变量 y 的内部函数,并且在 x 和 y 之间进行乘法运算。现在我们可以使用参数调用outer_body函数并将返回的函数存储在名为closure的变量中。因此 5 的值将存储在 x 中,现在我们有参数为 y 的 inner_body 函数,函数为 5*y,存储在闭包中。然后当你调用值为10的闭包变量(现在是一个函数)时,y的参数将接收10。通过下面的代码可以看到 -
def outer_body(x):
print('Value of x is - ', x)
def inner_body(y):
print('Value of y is - ', y)
return x*y
return inner_body
closure = outer_body(5)
print(closure(10))
Output -
Value of x is - 5
Value of y is - 10
50
函数作为参数
也可以将函数作为参数发送,就像我们将参数作为参数发送一样。在下面的代码中,我定义了 add、sub 和 mul 三个操作,以及另一个称为操作的通用函数,它将获取函数名称并执行相应的操作以返回结果。
def add(x,y):
return x+y
def sub(x,y):
return abs(x-y)
def mul(x,y):
return x*y
def operations(operate, x, y): #Here the operate parameter is receiving function objects
return operate(x,y)
list_of_operations = [add, sub, mul]
for op in list_of_operations:
print(operations(op, 10,50))
Output -
60
40
500
Lambda 函数:Python 中的匿名函数
Python 中的 Lambda 函数是用于在单行中执行函数操作的匿名函数。该函数由关键字 lambda 定义,语法如下 -
lambda(变量):(单个操作)
因此,使用 lambda 函数,您可以使用任意多个变量,但只能执行单个操作。与使用 def 关键字声明的函数不同,您不能使用单个 lambda 函数执行多个操作。此外,lambda 函数可以存储为对象。
def multiply_values(x,y):
return x*y
print('10x20 = ',multiply_values(10,20))
Output -
10x20 = 200
上面的函数可以使用 lambda 表达式来编写 -
multiply_value = lambda x,y: x*y
print('10x20 = ',multiply_value(10,20))
Output -
10x20 = 200
高阶函数
Lambda 函数:使用映射获取多个值
map() 函数是 python 中众多内置函数之一。 map() 函数是将函数应用于称为可迭代的数字列表。语法是——map(函数,可迭代)。 Map 函数生成另一个可迭代对象。
因此,您定义的函数作为第一个参数,可迭代对象是作为第二个参数的值列表。可迭代对象中的每个值都应用于定义的函数。通过下面的函数来理解这一点 -
def addition(num_list):
addition_list = []
for i in num_list:
addition_list.append(i+i)
return addition_list
num_list = [1,2,3,4,5]
print('1+2+3+4+5 = ', addition(num_list))
Output -
1+2+3+4+5 = [2, 4, 6, 8, 10]
上面的函数可以使用map()编写如下 -
num_list = [1,2,3,4,5]
addition_map = map(lambda x:x+x, num_list)
print('1+2+3+4+5 = ', list(addition_map))
Output -
1+2+3+4+5 = [2, 4, 6, 8, 10]
Lambda 函数:对多个值使用过滤器
filter() 函数是另一个内置函数,与 map() 一样,它以函数作为第一个参数,以迭代器作为第二个参数。对于filter(),该函数通常是一个条件函数,它将根据特定条件过滤掉数据。因此,可以从遵守函数条件并返回 True 的迭代中获取值。 Filter 函数还生成一个可迭代对象作为其输出。通过下面的代码来理解这个概念 -
def multiples_of_five(num):
five_multiples = []
for n in num:
if n%5 == 0:
five_multiples.append(n)
return five_multiples
num_list = list(range(2,20,1))
print('Multiples of 5 are - ',multiples_of_five(num_list))
Output -
Multiples of 5 are - [5, 10, 15]
将上面的函数写成过滤函数。因此,第一个参数中的 lambda 函数从名为 num_list 的可迭代列表中过滤掉乘以 5 的值。
num_list = list(range(2,20,1))
five_multiples = filter(lambda x:x%5==0, num_list)
print('Multiples of 5 are - ',list(five_multiples))
Output -
Multiples of 5 are - [5, 10, 15]
Lambda函数:对多个值使用reduce
与map()和filter()一样,我们还有另一个名为reduce()的函数,它接受一个可迭代对象并将其减少为单个值。因此,在使用map和filter的情况下,我们得到一个列表作为输出,但在使用reduce()的情况下,我们得到一个值作为输出。应用于可迭代对象的函数将其减少为单个值。 reduce() 是从名为 functools 的库导入的。浏览下面的代码 -
def all_addition(num_list):
result = 0
for i in num_list:
result = result + i
return result
num_list = list(range(2,10,1))
print('Addition of all numbers - ', all_addition(num_list))
Output -
Addition of all numbers - 44
上面的函数可以写成reduce函数的形式 -
from functools import reduce
num_list = list(range(2,10,1))
additions = reduce(lambda x,y:x+y, num_list)
print('Addition of all numbers - ', additions)
Output -
Addition of all numbers - 44
这样,map()、filter()、reduce()的写法都是一样的,第一个参数是函数,第二个参数是iterable。区别在于其使用概念。我们正在谈论可迭代,现在让我们来看看迭代器。
迭代器
任何值序列都可以视为可迭代。为了将值序列作为迭代器启动,我们在 python 中有一个内置函数,称为 iter()。当我们将序列放在 iter 的括号内时,该序列就变成了可迭代的。您可以将其视为为数字生成的指针。现在为了遍历数字序列,我们需要将此指针移动到所有值。为此,我们有另一个内置函数 next()。因此 iter() 和 next() 结合在一起来遍历序列。现在,通过使用 next(),您将一次获得一个值,因此我们必须调用 next() 来获取任意数量的值。一旦序列中的数字用完并且下一个数字指向无值,我们就会收到错误。 For 循环是迭代器的一种。
浏览下面的代码 -
numbers = [10,20,30,40,50]
iterable = iter(numbers) #instantiating iter() obejct and storing in variable named iterable
print(next(iterable)) #calling out values using next()
print(next(iterable))
print(next(iterable))
Output -
10
20
30
word = "Hello World!"
itering = iter(word)
print(next(itering))
print(next(itering))
print(next(itering))
print(next(itering))
print(next(itering))
Output -
H
e
l
l
o
numbers = (10,20,30,40,50)
iterable = iter(numbers)
print(next(iterable))
print(next(iterable))
Output -
10
20
numbers = {'a':10, 'b':20, 'c':30, 'd':40, 'e':50}
iterable = iter(numbers)
print(next(iterable)) #in case of dictionary, iteration will go via keys
print(next(iterable))
print(numbers[next(iterable)]) #accesing the value of the key
Output -
a
b
30
在此处获取有关 iter() 和 next() 的更多详细信息 —
https://docs.python.org/3/library/functions.html
生成器函数
生成器函数与普通函数类似,但效率更高并且节省内存。我们在生成器中使用yield关键字而不是return。生成器函数可以保留状态并将返回特定值而不是一次返回所有值。这非常有用,并且在无限值的情况下被广泛使用。让我们通过示例来更好地理解它。
在下面的函数中,我们想要生成五的倍数。假设我们在函数中传递 10 作为参数,这意味着生成器最多可以生成 10 个 5 的倍数。但我们不想一次看到所有这些。使用普通函数将立即生成所有值,即 5 到 10 项的倍数。但是,使用生成器,您可以根据需要调用项数。
请记住,一旦生成器对象生成一个值,它将保留下一个值的状态,但会丢失前一个值。这意味着如果你有 [2,3,4],那么调用生成器函数三次将得到 2、3 和 4,然后生成器函数将丢失之前的状态。让我们通过代码来更好地理解 -
def generate_five_multiples(terms):
for i in range(terms):
yield i*5
generator_object = generate_five_multiples(10) #we are calling the generator function here with 10 as argument and is storing the return value in generator object
print(next(generator_object))
print(next(generator_object))
print(next(generator_object))
Output -
0
5
10
在上面的函数中,我们调用了生成器 3 次,因此即使我们在函数中传递了 10 项,也只得到了 3 个数字。这就是它仅向您提供特定条款而不是返回所有条款的工作原理。但是,如果您想查看所有 10 个项,则必须将生成器对象放置在内置 list() 函数中,该函数将立即为您提供所有值。看到这个 -
def generate_five_multiples(terms):
for i in range(terms):
yield i*5
generator_object = generate_five_multiples(10)
print(list(generator_object))
Output -
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
现在,正如我之前所说,一旦生成器遍历了序列中的所有元素,它将耗尽并停止迭代,因为它无法返回。现在,如果您必须再次运行生成器函数,那么您必须创建一个新的生成器对象。见下文 -
iterator = iter(generator_object) #we are getting StopIteration error since the generator object we placed inside iter is already exhausted
print(next(iterator))
print(next(iterator))
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
Cell In[22], line 2
1 iterator = iter(generator_object) #we are getting StopIteration error since the generator object we placed inside iter is already exhausted
----> 2 print(next(iterator))
3 print(next(iterator))
StopIteration:
generator_object = generate_five_multiples(5) #re-initializing the generator again and this time with 5 as argument
iterator = iter(generator_object)
print(list(iterator))
Output -
[0, 5, 10, 15, 20]
generator_object = generate_five_multiples(5)
iterator = iter(generator_object)
print(next(iterator))
print(next(iterator))
print(next(iterator))
Output -
0
5
10
生成器和普通函数内存使用情况
为什么您认为生成器比普通函数更有效?那么请看下面的程序。另外,您将通过此代码了解生成器何时会像普通函数一样运行 -
import sys
def generate_numbers_in_normal_form(terms):
numbers = []
for i in range(terms):
numbers.append(i)
return numbers
def generate_numbers_in_generator(terms):
for i in range(terms):
yield i
numbers_in_list = generate_numbers_in_normal_form(100000)
print('Size consumed by normal function - ', sys.getsizeof(numbers_in_list), ' bytes')
numbers_in_generator = generate_numbers_in_generator(100000)
print('Size consumed by generator function - ', sys.getsizeof(numbers_in_generator), ' bytes')
numbers_in_generator_list = list(numbers_in_generator)
print('Size consumed by generator function after storing all values in iterable - ', sys.getsizeof(numbers_in_generator_list), ' bytes')
Output -
Size consumed by normal function - 800984 bytes
Size consumed by generator function - 104 bytes
Size consumed by generator function after storing all values in iterable - 800984 bytes
尝试在生成器函数中使用 print() 函数来查看您获得的值。
有关生成器的更多信息,请尝试此 —
https://www.geeksforgeeks.org/generators-in-python/
装饰器函数
当您已经有一个函数并且您希望在现有函数上添加更多功能而不对现有函数进行任何更改时,装饰器函数就像包装函数。使用@(按速率)运算符将装饰器应用于函数。让我们来看一个例子。看下面的数字加法函数。现在我想知道将 200000 个数字相加所需的时间,并且我不想更改该函数。
def number_addition(numbers):
total = 0
for i in numbers:
total += i
return total
num_list = range(200000)
number_addition(num_list)
Output -
19999900000
因此,我定义了一个名为 time_taken_to_run 的新函数,它将 number_addition 函数作为参数,然后定义一个内部函数,它接受该函数可能具有的任何参数。然后它会执行我们想要在现有函数之上施加的操作类型,然后相应地返回值。在每个步骤中使用 print() 语句可以更好地理解它 -
import time
def time_taken_to_run(function_name): #function_name parameter will take the function of number_addiction
def wrapper(*args, **kwargs): #this is taking the numbers as *args. **kwargs is empty since we are not having keyworded arguments
start_time = time.time() #starting the time of operation
result = function_name(*args, **kwargs) #calling the function of number_addition with numbers as parameters to execute the operation
end_time = time.time() #ending the time of operation
print('Time take for calculating value of {} is {:.6f}'.format(result, (end_time - start_time))) #difference in time between start and end
return result #returning the resultant function that we called
return wrapper #returning the inner function from the outer function
@time_taken_to_run #this is how decorators are defined on top of function
def number_addition(numbers): #our normal function definition
total = 0
for i in numbers:
total += i
return total
number_addition(range(200000)) #calling the function will call the time taken to run function
Output -
Time take for calculating value of 19999900000 is 0.010499
19999900000
有关装饰器的更详细视图,请尝试此 -
https://www.freecodecamp.org/news/python-decorators-explained-with-examples/
Python 中的递归函数
递归函数至关重要,但理解起来有点棘手。递归函数将主函数分解为更小的子程序,然后得到结果。从函数内部调用自身的函数称为递归。在递归中具有基本情况条件以停止递归操作非常重要,否则会出现内存错误,因为递归操作将继续调用自身。查看下面的代码来确定该数字是否是素数 -
num = 29
if num>1:
for i in range(2,int(num/2)+1):
if num % i == 0:
print('Not a prime number - ',num)
break
else:
print('Prime Number ',num)
else:
print('Not a prime number - ',num)
Output -
Not a prime number - 2
我们可以使用递归来进行相同的操作。在这种情况下,我们通过减少每次调用的步骤来调用带有数字的函数。
def prime_numbers(num, calls):
print(' At the start of recurssion - ', calls)
if calls == 1: #base case condition to stop recursion
return True
if num % calls == 0: #condition to imply that the number is not prime
return False
if prime_numbers(num, calls -1) == False:
return False
print(' Tracing back of the recurssive effects - ', calls)
return True #True will return when no perfect division will be found for the number. This signifies prime number
num = 13
calls = int(num/2) + 1
if prime_numbers(num, calls):
print('Prime Number ',num)
else:
print('Not a prime number - ',num)
Output -
At the start of recurssion - 7
At the start of recurssion - 6
At the start of recurssion - 5
At the start of recurssion - 4
At the start of recurssion - 3
At the start of recurssion - 2
At the start of recurssion - 1
Tracing back of the recurssive effects - 2
Tracing back of the recurssive effects - 3
Tracing back of the recurssive effects - 4
Tracing back of the recurssive effects - 5
Tracing back of the recurssive effects - 6
Tracing back of the recurssive effects - 7
Prime Number 13
因此,正如您在 print 语句中看到的那样,递归函数被划分为更小的函数,一旦达到基本情况,它就会追溯到之前的状态以返回结果,最后它存在于函数之外。
递归一开始很难通过编码来理解。观看此视频可以更好地理解,因为您将获得它的直观表示 -
https://www.youtube.com/watch?v=BNeOE1qMyRA 和另一个足智多谋的博客 -
https://realpython.com/python-thinking-recursively /
一些带有生成器和装饰器的递归程序 -
带生成器的递归函数
def fibonacci(n):
if n == 0:
yield 0
elif n == 1:
yield 0
yield 1
else:
a, b = 0, 1
yield a
yield b
for _ in range(2, n+1):
a, b = b, a+b
yield b
for i in fibonacci(8):
print(i)
Output -
0
1
1
2
3
5
8
13
21
带有装饰器的递归函数
def operation_outer(function):
def operation_inner(*args, **kwargs):
for i in function(*args, **kwargs):
if i % 2 == 0:
yield(i)
return operation_inner
@operation_outer
def even_numbers(number):
for n in range(number):
yield n
nums = 10
list(even_numbers(nums))
Output -
[0, 2, 4, 6, 8]
def operation_outer(function):
odd_values = []
def operation_inner(*args, **kwargs):
for i in function(*args, **kwargs):
if i % 2 != 0:
odd_values.append(i)
return odd_values
return operation_inner
@operation_outer
def odd_numbers(number):
number_list = []
for n in range(number):
number_list.append(n)
return number_list
nums = 10
print(odd_numbers(nums))
Output -
[1, 3, 5, 7, 9]