把函数视作对象
创建一个函数,并读取它的__doc__
属性,再检查它的类型
>>> def factorial(n):
... '''return n!'''
... return 1 if n < 2 else n * factorial(n-1)
>>> factorial.__doc__
'return n!'
>>> factorial(40)
815915283247897734345611269596115894272000000000
>>> type(factorial)
<class 'function'>
__doc__
属性用于生成对象的帮助文本。
通过别的名称使用函数,再把函数作为参数传递
>>> fact = factorial # 将函数赋值给一个变量 然后通过变量名调用
>>> fact
<function factorial at 0x0310D340>
>>> fact(5)
120
>>> map(factorial, range(11))
<map object at 0x03108298>
>>> list(map(fact, range(11)))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
map 函数返回一个可迭代对象, 里面的元素是把第一个参数(一个函数),应用到第二个函数(一个可迭代对象,这里是range(11)中各个元素上得到的结果。
高阶函数
高阶函数:接受函数为参数,或者把函数作为结果返回的函数。如:map、sorted也是:可选的key参数用于提供一个函数,它会应用到各个元素上排序。
根据反向拼写给一个单词列表 排序
>>> def reverse(word):
... return word[::-1]
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=reverse)
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
这样可以创建押韵词典,把各个单词反过来拼写。
匿名函数
lambda 关键字在Python表达式内创建匿名函数。
lambda 函数的定义提中不能赋值, 也不能使用 while 和 try 等语句。
使用lambda,反向给单词列表排序
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
可调用对象
可以通过 callable() 函数来进行判断
用户定义的函数
使用 def 语句或 lambda 表达式创建。
内置函数
使用 C 语言(CPython)实现的函数,如 len 或 time…strftime
内置方法
使用 C 语言实现的方法,如 dict.get
方法
在类的定义体中定义的函数。
类
调用类时会运行类的__new__
方法创建一个实例,然后运行 __init__
方法,初始化实例,最后把实例返回给调用方。
类的实例
如果类定义__call__
方法,那么它的实例可以作为函数调用。
生成器函数
使用 yield 关键字的函数或方法。调用生成器函数返回的时生成器对象。
判断对象能否调用,最安全的方法时使用内置的 callable() 函数
>>> abs, str, 13
(<built-in function abs>, <class 'str'>, 13)
>>> [callable(obj) for obj in (abs, str, 13)]
[True, True, False]
用户定义的可调用类型
如何 Python 对象都可以表现得像函数。只需实现方法__call__
。
调用 BingoCago 实例,从打乱的列表中取出一个元素。
import random
class BingoCage:
def __init__(self, items):
self._items = list(items)
random.shuffle(self._items)
def pick(self):
try:
return self._items.pop()
except IndexError:
# 如果列表为空,抛出异常,并设定错误消息
raise LookupError('pick from empty BingoCage')
def __call__(self):
# bingo.pick()的快捷方式时bingo()
return self.pick()
bingo = BingoCage(range(3))
print(bingo.pick())
print(bingo())
print(callable(bingo)) # 返回True表示可调用
0
1
True
shuffle() 方法将序列的所有元素随机排序。没有返回值,参数中可以是列表。
函数内省
Python 函数可以进行内省 -Introspection,查看函数内部细节,使用 __code__
属性。
dir(function) 查看函数具有的属性。
从定位参数到仅限关键字参数
tag 函数用于生成 HTML 标签;使用名为 cls 的关键字参数传入 “class” 属性
def tag(name, *content, cls=None, **attrs):
# 生成一个或多个HTML标签
if cls is not None:
attrs['class'] = cls
if attrs:
attr_str = ''.join(' %s="%s"' % (attr, value)
for attr, value
in sorted(attrs.items()))
else:
attr_str = ''
if content:
return '\n'.join('<%s%s>%s</%s>' %
(name, attr_str, c, name) for c in content)
else:
return '<%s%s />' % (name,attr_str)
>>> tag('br')
'<br />'
>>> tag('p', 'hello') ②
'<p>hello</p>'
>>> print(tag('p', 'hello', 'world'))
<p>hello</p>
<p>world</p>
>>> tag('p', 'hello', id=33) ③
'<p id="33">hello</p>'
>>> print(tag('p', 'hello', 'world', cls='sidebar'))
<p class="sidebar">hello</p>
<p class="sidebar">world</p>
>>> tag(content='testing', name="img")
'<img content="testing" />'
>>> my_tag = {'name':'img', 'title': 'Sunset Boulevard',
... 'src': 'sunset,jpg', 'cls': 'framed'}
>>> tag(**my_tag) ⑤
'<img class="framed" src="sunset,jpg" title="Sunset Boulevard" />'
② 第一个参数后面的任意个参数会被 *content 捕获,存入一个元组。
③ tag 函数签名中没有明确指定名称的关键字参数会被 **attrs 捕获,存入一个字典。
⑤ 加上 ** 字典中的所有元素作为单个参数传入,同名键会绑定到对应的具名参数上,余下被**attrs捕获
如果不想支持数量不定的定位参数,但是像支持仅限关键字参数,在签名中放一个*
>>> def f(a, *, b):
... return a, b
...
>>> f(1, b=2)
(1, 2)
注意,仅限关键字不一定要有默认值,如上例中所示,强制必须传入实参。
获取关于参数的信息
提取函数的签名
def clip(text, max_len=80):
"""
在max_len前面或后面的第一个空格处阶段文本
"""
end = None
if len(text) > max_len:
space_before = text.rfind(' ', 0, max_len)
if space_before >= 0:
end = space_before
else:
space_after = text.rfind(' ',max_len)
if space_after >= 0:
end = space_after
if end is None: # 没有找到空格
end = len(text)
return text[:end].rstrip()
>>> from inspect import signature
>>> sig = signature(clip)
>>> sig
<Signature (text, max_len=80)>
>>> str(sig)
'(text, max_len=80)'
>>> for name, param in sig.parameters.items():
... print(param.kind, ':', name, '=', param.default)
...
POSITIONAL_OR_KEYWORD : text = <class 'inspect._empty'> # 表示没有默认值
POSITIONAL_OR_KEYWORD : max_len = 80
inspect.signature 函数返回一个 inspect.Signature 对象,它有一个 parameters 属性,知识一个有序映射,把参数名 inspect.Parameter 对象对应起来。