python函数进阶
2021-10-19 本文已影响0人
D_w
函数
- 主程序调用函数时,必须保证这个函数此前已经定义过,即被调函数的实现要在调用函数之前:
my_func('hello world')
def my_func(message):
print('Got a message: {}'.format(message))
# 输出
NameError: name 'my_func' is not defined
但在函数内部调用其他函数,函数间哪个声明在前、哪个在后就无所谓,因为 def 是可执行语句,函数在调用之前都不存在,我们只需保证调用时,所需的函数都已经声明定义:
def my_func(message):
my_sub_func(message) # 调用my_sub_func()在其声明之前不影响程序执行
def my_sub_func(message):
print('Got a message: {}'.format(message))
my_func('hello world')
# 输出
Got a message: hello world
- Python 不用考虑输入的数据类型,而是将其交给具体的代码去判断执行
- Python 函数的另一大特性,是 Python 支持函数的嵌套,嵌套的好处在于,第一,函数的嵌套能够保证内部函数的隐私,内部函数只能被外部函数所调用和访问;第二,合理的使用函数嵌套,能够提高程序的运行效率
def factorial(input):
# validation check
if not isinstance(input, int):
raise Exception('input must be an integer.')
if input < 0:
raise Exception('input must be greater or equal to 0' )
...
def inner_factorial(input):
if input <= 1:
return 1
return input * inner_factorial(input-1)
return inner_factorial(input)
print(factorial(5))
这里,我们使用递归的方式计算一个数的阶乘。这样的好处在于,在计算之前,需要检查输入是否合法,写成函数嵌套的形式,这样一来,输入是否合法就只用检查一次。而如果我们不使用函数嵌套,那么每调用一次递归便会检查一次,这是没有必要的,也会降低程序的运行效率。
- 我们都知道在函数内部想修改全局变量需要在函数内部对全局变量用global修饰,类似的对于嵌套函数来说,内部函数可以访问外部函数定义的变量,但是无法修改,若要修改,必须加上 nonlocal 这个关键字
- 闭包:闭包其实和刚刚讲的嵌套函数类似,不同的是,这里外部函数返回的是一个函数,而不是一个具体的值。返回的函数通常赋于一个变量,这个变量可以在后面被继续执行调用,合理地使用闭包,则可以简化程序的复杂度,提高可读性。。
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of # 返回值是exponent_of函数
square = nth_power(2) # 计算一个数的平方
cube = nth_power(3) # 计算一个数的立方
square
# 输出
<function __main__.nth_power.<locals>.exponent(base)>
cube
# 输出
<function __main__.nth_power.<locals>.exponent(base)>
print(square(2)) # 计算2的平方
print(cube(2)) # 计算2的立方
# 输出
4 # 2^2
8 # 2^3
匿名函数
- 第一,lambda 是一个表达式(expression),并不是一个语句(statement),因此,lambda 可以用在一些常规函数 def 不能用的地方,比如,lambda 可以用在列表内部,而常规函数却不能:
[(lambda x: x*x)(x) for x in range(10)]
# 输出
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- 第二,lambda 的主体是只有一行的简单表达式,并不能扩展成一个多行的代码块
匿名函数使用场景一般为:你需要一个函数,但它非常简短,只需要一行就能完成;同时它在程序中只被调用一次。
对列表所有元素求平方
squared = map(lambda x: x**2, [1, 2, 3, 4, 5]) # map(function, iterable) 作用为iterable每个元素依次执行function,
函数式编程
所谓函数式编程,是指代码中每一块都是不可变的(immutable),都由纯函数(pure function)的形式组成。这里的纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。
举个栗子:
# 非函数式编程,因为多次调用后列表l中的元素被改变了中的元素被改变了
def multiply_2(l):
for index in range(0, len(l)):
l[index] *= 2
return l
# 纯函数式编程
def multiply_2_pure(l):
new_list = [] # 重新创建列表并返回
for item in l:
new_list.append(item * 2)
return new_list
Python 主要提供了这么几个函数:map()、filter() 和 reduce(),通常结合匿名函数 lambda 一起使用,拥有函数式编程特性。
如map:
python3 -mtimeit -s'xs=range(1000000)' 'map(lambda x: x*2, xs)'
2000000 loops, best of 5: 171 nsec per loop
python3 -mtimeit -s'xs=range(1000000)' '[x * 2 for x in xs]'
5 loops, best of 5: 62.9 msec per loop
python3 -mtimeit -s'xs=range(1000000)' 'l = []' 'for i in xs: l.append(i * 2)'
5 loops, best of 5: 92.7 msec per loop
map是直接由C写,速度最快
- filter(function, iterable) 函数,它和 map 函数类似,function 同样表示一个函数对象。filter() 函数表示对 iterable 中的每个元素,都使用 function 判断,并返回 True 或者 False,最后将返回 True 的元素组成一个新的可遍历的集合,如:
# 返回一个列表中的所有偶数
l = [1, 2, 3, 4, 5]
new_list = filter(lambda x: x % 2 == 0, l)
------------------输出------------------
[2, 4]
- reduce(function, iterable) 函数,function 同样是一个函数对象,规定它有两个参数,表示对 iterable 中的每个元素以及上一次调用后的结果,运用 function 进行计算,所以最后返回的是一个单独的数值。
计算列表中元素的乘积
l = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, l) # 1*2*3*4*5 = 120