1. 可变参数
介绍下 python 中常见的 *args 和 **kwargs 可变参数。
1.1 位置变量参数(*args)
一个函数接受任意数量的参数,称为使用可变参数,例如:
def f(x, *args):
...
f(1,2,3,4,5)
def f(x, *args):
1.2 关键字变量参数(**kwargs)
一个函数也可以接受任意数量的关键字参数。例如:
def f(x, y, **kwargs):
...
f(2, 3, flag=True, mode='fast', header='debug')
def f(x, y, **kwargs):
1.3 结合两者
函数还可以接受任意数量的变量关键字和非关键字参数。
def f(*args, **kwargs):
...
f(2, 3, flag=True, mode='fast', header='debug')
def f(*args, **kwargs):
...
1.4 扩展可变参数
元组扩展可变参数
numbers = (2,3,4)
f(1, *numbers)
字典扩展可变参数
options = {
'color' : 'red',
'delimiter' : ',',
'width' : 400
}
f(data, **options)
2. 回调函数与匿名函数
sort()的列表排序
s = [10,1,7,3]
s.sort()
s.sort(reverse=True)
sort()的字典排序
[{'name': 'AA', 'price': 32.2, 'shares': 100},
{'name': 'IBM', 'price': 91.1, 'shares': 50},
{'name': 'CAT', 'price': 83.44, 'shares': 150},
{'name': 'MSFT', 'price': 51.23, 'shares': 200},
{'name': 'GE', 'price': 40.37, 'shares': 95},
{'name': 'MSFT', 'price': 65.1, 'shares': 50},
{'name': 'IBM', 'price': 70.44, 'shares': 100}]
def stock_name(s):
return s['name']
portfolio.sort(key=stock_name)
[
{'name': 'AA', 'price': 32.2, 'shares': 100},
{'name': 'CAT', 'price': 83.44, 'shares': 150},
{'name': 'GE', 'price': 40.37, 'shares': 95},
{'name': 'IBM', 'price': 91.1, 'shares': 50},
{'name': 'IBM', 'price': 70.44, 'shares': 100},
{'name': 'MSFT', 'price': 51.23, 'shares': 200},
{'name': 'MSFT', 'price': 65.1, 'shares': 50}
]
匿名函数 Lambda
Lambda 允许直接在调用中定义一个特殊的处理函数。
- lambda 只允许使用一个表达式。
- 没有声明语句 if, while 等
- 通常与 sort 函数使用。
使用匿名函数代替以上回调函数,语法更加简短。
portfolio.sort(key=lambda s: s['name'])
3. Returning 函数
返回函数是在一个函数中返回另外一个函数。
例如:
def add(x, y):
def do_add():
print('Adding', x, y)
return x + y
return do_add
>>> a = add(3,4)
>>> a
<function do_add at 0x6a670>
>>> a()
Adding 3 4
7
3.1 局部变量
内部函数引用外部函数定义的局部变量。
def add(x, y):
def do_add():
print('Adding', x, y)
return x + y
return do_add
3.2 闭包
当一个内部函数作为结果返回时,该内部函数称为闭包(closure)。
def add(x, y):
def do_add():
print('Adding', x, y)
return x + y
return do_add
闭包也可以用作避免过多代码重复(使用函数生成代码)。
闭包的使用:
延迟评估
def add(x, y):
def do_add():
print(f'Adding {x} + {y} -> {x+y}')
return do_add
def after(seconds, func):
import time
time.sleep(seconds)
func()
after(30, add(2, 3))
4. 装饰器
装饰器的功能可以理解为,去除函数中重复的输出部分,常用于日志记录部分。
创建一个装饰器,使函数添加日志记录功能。
def logged(func):
def wrapper(*args, **kwargs):
print('Calling', func.__name__)
return func(*args, **kwargs)
return wrapper
def add(x, y):
return x + y
logged_add = logged(add)
>>> logged_add(3, 4)
Calling add
7
以上模仿了装饰器的调用过程,但实际应用中,使用特殊的装饰器语法调用即可。
装饰器语法:
def logged(func):
def wrapper(*args, **kwargs):
print('Calling', func.__name__)
return func(*args, **kwargs)
return wrapper
@logged
def add(x, y):
return x + y
>>> add(3, 4)
Calling add
7
5. 装饰方法
5.1 预定义的装饰器
预定义的装饰器用于在类定义中指定特殊类型的方法。
静态方法
@staticmethod 用于定义所谓的静态类方法(来自 C++/Java)。
静态方法是一个函数,它是类的一部分,但它不对实例进行操作。
class Foo(object):
@staticmethod
def bar(x):
print('x =', x)
>>> Foo.bar(2)
x=2
静态方法有时用于实现类的内部支持代码。例如,帮助管理已创建实例的代码(内存管理、系统资源、持久性、锁定等)。
类方法 @classmethod用于定义类方法。
类方法是接收类对象作为第一个参数的方法。
类方法最常被用作定义替代构造函数的工具。
class Foo:
def bar(self):
print(self)
@classmethod
def spam(cls):
print(cls)
>>> f = Foo()
>>> f.bar()
<__main__.Foo object at 0x971690>
>>> Foo.spam()
<class '__main__.Foo'>
>>>
|