python基础——第6章 抽象

6.3 自定义函数

# 斐波那契数函数
def fibs(num): 
	result = [0, 1]  
	for i in range(num-2): 
		result.append(result[-2] + result[-1]) 
	return result 

6.3.1 给函数编写文档

文档字符串(docstring)
下面的代码演示了如何给函数添加文
档字符串:

def square(x): 
   'Calculates the square of the number x.'  
   return x * x 

可以像下面这样访问文档字符串:


>>> square.__doc__ 
'Calculates the square of the number x.' 

注意 __doc__是函数的一个属性。属性将在第7章详细介绍。属性名中的双下划线表示这是一个特殊的属性。特殊(“魔法”)属性将在第9章讨论。

6.4 参数魔法

注意 参数存储在局部作用域内。

6.4.3 关键字参数和默认值

关键字参数最大的优点在于,可以指定默认值。

6.4.4 收集参数

允许提供任意数量的参数

def print_paras(*argv):
	print(argvS)
  • 参数前面的星号将所有实参都放在一个元组中,它收集的是列表而不是元组中多余的值。
  • 星号收集余下的位置参数。如果没有可供收集的参数,params将是一个空元组。
  • 带星号的参数也可放在其他位置,在这种情况下:需要使用名称来指定都需参数。
  • 星号不会收集关键字参数。
>>> def in_the_middle(x, *y, z): 
...     print(x, y, z) 
... 
>>> in_the_middle(1, 2, 3, 4, 5, z=7) 
1 (2, 3, 4, 5) 7 
>>> in_the_middle(1, 2, 3, 4, 5, 7) 
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module> 
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z' 
  • 星号不会收集关键字参数。
>>> print_params_2('Hmm...', something=42) 
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module> 
TypeError: print_params_2() got an unexpected keyword argument 'something' 
  • 要收集关键字参数,可使用两个星号。
>>> def print_params_3(**params): 
...     print(params) 
... 
>>> print_params_3(x=1, y=2, z=3) 
{'z': 3, 'x': 1, 'y': 2} 

这样得到的是一个字典而不是元组。可结合使用这些技术。

6.4.5 分配参数

同样用(’* ‘和’ '),通过在调用函数时使用运算符实现。这种做法也可用于参数列表的一部分,条件是这部分位于参数列表末尾。通过使用运算符 **,可将字典中的值分配给关键字参数。
如果在定义和调用函数时都使用
,将只传递元组或字典。还不如不使用它们,还可省却些麻烦。

>>> def with_stars(**kwds): 
...   print(kwds['name'], 'is', kwds['age'], 'years old') 
... 
>>> def without_stars(kwds): 
...   print(kwds['name'], 'is', kwds['age'], 'years old') 
... 
>>> args = {'name': 'Mr. Gumby', 'age': 42} 
>>> with_stars(**args) 
Mr. Gumby is 42 years old 
>>> without_stars(args) 
Mr. Gumby is 42 years old 

对于函数with_stars,在定义和调用它时都使用了星号,而对于函数without_stars,我在定义和调用它时都没有使用,但这两种做法的效果相同。因此,只有在定义函数(允许可变数量的参数)或调用函数(拆分字典或序列)时使用,星号才能发挥作用。

6.5 作用域

命名空间或作用域

  • 全局作用域
  • 每个函数调用都将创建一个
作用域嵌套(闭包

python函数可以嵌套,即可将一个函数放在另一个函数内,嵌套通常用处不大,但有一个很突出的用途:使用一个函数来创建另一个函数。

def multiplier(factor): 
	def multiplyByFactor(number): 
		return number * factor 
	return multiplyByFactor 

在这里,一个函数位于另一个函数中,且外面的函数返回里面的函数。也就是返回一个函数,而不是调用它。重要的是,返回的函数能够访问其定义所在的作用域。换而言之,它携带着自己所在的环境(和相关的局部变量)!
每当外部函数被调用时,都将重新定义内部的函数,而变量factor的值也可能不同。由于Python的嵌套作用域,可在内部函数中访问这个来自外部局部作用域(multiplier)的变量,如下所示:

>>> double = multiplier(2) 
>>> double(5) 
10 
>>> triple = multiplier(3) 
>>> triple(3) 
9 
>>> multiplier(5)(4) 
20 

像multiplyByFactor这样存储其所在作用域的函数称为闭包
通常,不能给外部作用域内的变量赋值,但如果一定要这样做,可使用关键字nonlocal。这个关键字的用法与global很像,让你能够给外部作用域(非全局作用域)内的变量赋值。

6.6 递归

  • 基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。
  • 递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分。

map、filter、reduce

Python提供了一些有助于进行这种函数式编程的函数:map、filter和reduce。在较新的Python版本中,函数map和filter的用途并不大,应该使用列表推导来替代它们。你可使用map将序列的所有元素传递给函数。

>>> list(map(str, range(10))) # 与[str(i) for i in range(10)]等价 
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] 
你可使用filter根据布尔函数的返回值来对元素进行过滤。 
>>> def func(x): 
...     return x.isalnum() 
... 
>>> seq = ["foo", "x41", "?!", "***"] 
>>> list(filter(func, seq)) 
['foo', 'x41'] 

6.7 本章介绍的新函数

函 数 描 述
help(functionName) 获取名为functionName函数的信息
callable(x) 判断对象x是否可调用
map(func, seq[, seq, …]) 对序列中的所有元素执行函数
filter(func, seq) 返回一个列表,其中包含对其执行函数时结果为真的所有元素
reduce(func, seq[, initial]) 等价于 func(func(func(seq[0], seq[1]), seq[2]), …)
sum(seq) 返回 seq 中所有元素的和
apply(func[, args[, kwargs]]) 调用函数(还提供要传递给函数的参数)
globals() 返回一个包含全局变量的字典,类似于vars,globals()[‘parameter’]来访问名为parameter的全局变量
locals() 返回一个包含局部变量的字典

猜你喜欢

转载自blog.csdn.net/acktomas/article/details/84728213
今日推荐