文章目录
1 函数是 Python 的对象
1 Python
中一切皆为对象,函数也不例外。可以将函数分配给变量或存储在数据结构中。
2 作为头等对象,函数还可以被传递给其他函数或作为其他函数的返回值。
3 头等函数的特性可以用来抽象并传递程序中的行为。
4 函数可以嵌套,并且可以捕获并携带父函数的一些状态。具有这种行为的函数称为闭包
。
5 对象可以被设置为可调用的,因此很多情况下可以将其作为函数对待。
1.1 函数是对象
def yell(text):
return text.upper() + '...'
bark = yell
print(bark) # <function yell at 0x0000027E7DDAD1E0>
print(yell) # <function yell at 0x0000027E7DDAD1E0>
demo1_1 = bark("Hello world | function test demo 1")
print(demo1_1) # HELLO WORLD | FUNCTION TEST DEMO 1...
del yell
# yell("Hello") # NameError: name 'yell' is not defined
hi = bark("Hello")
print(hi) # HELLO...
print(bark.__name__) # yell
1.2 函数可传递给其他函数
def greet(func):
greeting = func('Hi, I am a Python program')
print(greeting)
print(greet(bark)) # HI, I AM A PYTHON PROGRAM...
Python 中具有代表性的高阶函数是内置的 map
函数。map
接受一个函数对象和一个可迭代对象,然后在可迭代对象中的每个元素上调用该函数来生成结果。
下面通过将 bark
函数映射到多个问候语中来格式化字符串:
print(list(map(bark, ['hello', 'hey', 'hi']))) # ['HELLO...', 'HEY...', 'HI...']
1.3 嵌套函数
def speak(text):
def whisper(t):
return t.upper() + '!!!'
return whisper(text)
print(speak('Hello, World')) # HELLO, WORLD!!!
1.4 闭包示例
def get_speak_func(text, volume):
# 内部函数 whisper 和 _yell,注意其中并没有 text 参数
def whisper():
return text.lower() + '...'
def _yell():
return text.upper() + '!'
if volume > 0.5:
return _yell
else:
return whisper
hello = get_speak_func('Hello, World', 0.7)()
print(hello) # Output: 'HELLO, WORLD!'
2 lambda 是单表达式函数
简单示例
>>> add = lambda x, y: x + y
>>> add(5, 3)
8
2.1 函数表达式
expert = (lambda x, y: x + y)(5, 3)
print(expert) # 8
2.2 lambda 使用场景:排序
tuples = [(1, 'd'), (2, 'b'), (4, 'a'), (3, 'c')]
tuples = sorted(tuples, key=lambda x: x[1], reverse=False)
print(tuples) # [(4, 'a'), (2, 'b'), (3, 'c'), (1, 'd')]
将 lambda 和 map()
或 filter()
结合起来构建复杂的表达式也很难让人理解,
此时用列表解析式或生成器表达式通常会清晰不少:
# 有害:
>>> list(filter(lambda x: x % 2 == 0, range(16)))
[0, 2, 4, 6, 8, 10, 12, 14]
# 清晰:
>>> [x for x in range(16) if x % 2 == 0]
[0, 2, 4, 6, 8, 10, 12, 14]
3 装饰器的力量
装饰器的一大用途是将通用的功能应用到现有的类或函数的行为上,这些功能包括:
1 日志(logging
)
2 访问控制和授权
3 衡量函数,如执行时间
4 限制请求速率(rate-limiting
)
5 缓存,等等
def trace(func):
def wrapper(*args, **kwargs):
print(f'TRACE: calling {func.__name__}() '
f'with {args}, {kwargs}')
original_result = func(*args, **kwargs)
print(f'TRACE: {func.__name__}() '
f'returned {original_result!r}')
return original_result
return wrapper
@trace
def say(name, line):
return f'{name}: {line}'
text = say('Jane', 'Hello, World')
print(text)
# TRACE: calling say() with ('Jane', 'Hello, World'), {}
# TRACE: say() returned 'Jane: Hello, World'
# Jane: Hello, World
Python 装饰器写日志
示例如下
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kw):
if func.__name__ == "debug":
msg = "debug {}".format(args[0])
elif func.__name__ == "info":
msg = "info {}".format(args[0])
else:
msg = "unknown {}".format(args[0])
return func(msg, **kw)
return wrapper
@log
def debug(msg):
print(msg)
@log
def info(msg):
print(msg)
if __name__ == "__main__":
debug("bug!")
info("msg.")
# 输出结果如下:
# debug bug!
# info msg.
4 有趣的 *args
和 **kwargs
*args
和 **kwargs
用于在 Python 中编写变长参数的函数。
*args
收集额外的位置参数组成元组。**kwargs
收集额外的关键字参数组成字典。
def foo(required, *args, **kwargs):
print(required)
if args:
print(args)
if kwargs:
print(kwargs)
# print(foo()) # TypeError: foo() missing 1 required positional argument: 'required'
foo('hello') # hello
foo('hello', 1, 2, 3)
# hello
# (1, 2, 3)
foo('hello', 1, 2, 3, key1='value', key2=999)
# hello
# (1, 2, 3)
# {'key1': 'value', 'key2': 999}
5 函数参数解包
*
和 **
操作符有一个非常棒但有点神秘的功能,那就是用来从序列和字典中 “解包” 函数参数。
高效使用参数解包有助于为模块和函数编写更灵活的接口。
def print_vector(x, y, z):
print('<%s, %s, %s>' % (x, y, z))
express = (x * x for x in range(3))
print_vector(*express) # <0, 1, 4>
dict_vec = {'y': 0, 'z': 1, 'x': 1}
print_vector(**dict_vec) # <1, 0, 1>
print_vector(*dict_vec) # <y, z, x>
6 返回空值
Python 在所有函数的末尾添加了隐式的 return None
语句。因此,如果函数没有指定返回值,默认情况下会返回 None。
返回空值是 Python 的核心功能,但是使用显式
的 return None
语句能更清楚地表达代码的意图。
def foo1(value):
"""建议显示说明返回值 None,方便以后维护"""
if value:
return value
else:
return None
def foo2(value):
"""纯return 语句,相当于`return None`"""
if value:
return value
else:
return
def foo3(value):
"""无return 语句,也相当于`return None`"""
if value:
return value