lambda表达式
lambda用来声明匿名函数,用于临时需要一个类似函数功能的场景,可以结合python的内置函数使用,比如map()。
map()函数参看: https://www.cnblogs.com/superxuezhazha/p/5714970.html
>>> function=lambda a,b,c: a*b*c # 起名lambda表达式为function
>>> print(function(2,3,4))
24
# 定义一个字典,里面有两个键f1,f2,对应两个lambda函数
>>> dict={'f1':(lambda x,y:x+y),'f2':(lambda x,y:x*y)}
>>> print(dict['f1'](2,3))
5
>>> print(dict['f2'](2,3))
6
关于lambda局部变量的错误:
>>> r=[]
>>> for x in range(10):
... r.append(lambda: x**2)
...
>>> r[1]()
81
>>> r[0]()
81
>>> r[2]()
81
>>> r[3]()
81
>>> x=2
>>> r[1]()
4
>>> r[2]()
4
>>> r[3]()
4
如果改为以下则正确:
>>> r=[]
>>> for x in range(10):
... r.append(lambda n=x: n**2)
...
>>> r[0]()
0
>>> r[1]()
1
>>> r[2]()
4
>>> r[3]()
9
>>> x=2
>>> r[0]()
0
>>> r[1]()
1
>>> r[3]()
9
关于以上全局和局部错误的另一个示例:
>>> f=lambda:i #返回i
>>> i=2
>>> f()
2
>>> i=5
>>> f()
5
>>> i=4
>>> f()
4
生成器
包含yield语句的函数叫做生成器函数。
生成器具有惰性求值的特点,可以用于大数据。
return一旦执行就立刻结束函数;yield则是返回一个值,然后挂起yield语句后面的代码,使用__next__()
可以恢复执行。
# 使用生成器生成斐波那契数列
>>> def f():
... a,b=1,1
... while True:
... yield a
... a,b=b,a+b #序列解包
...
>>> a=f()
>>> for i in range(10):
... print(a.__next__(),end=' ')
...
1 1 2 3 5 8 13 21 34 55
简单的分析(此处是草稿可跳过,我只是看看
markdown的图表怎么弄 -_-||)
a | b | yield |
---|---|---|
1 | 1 | 1 |
1 | 2 | 1 |
2 | 3 | 2 |
3 | 5 | 3 |
5 | 8 | 5 |
*args 和 **kwargs
这是魔法变量,实际上args和kwargs不是固定的,可以是任何命名,只要有和*就行。
*args 和 **kwargs 主要用于在函数定义的时候把不定数量的参数传递给一个函数。
*args
简单的例子:
def test_var_args(f_arg, *argv):
print("first normal arg:", f_arg)
for arg in argv:
print("another arg through *argv:", arg)
test_var_args('yasoob', 'python', 'eggs', 'test')
这会产生如下输出:
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test
**kwargs
**kwargs 将不定长度的键值对,作为参数传递给一个函数。
1 def greet_me(*args, **kwargs):
2 for v in args:
3 print("hello, {0}".format(v))
4 for key, value in kwargs.items():
5 print("{0} is {1}".format(key, value))
6
7
8 greet_me('andy', 'smith', name1="jane", name2='john', name3='claire')
输出:
hello, andy
hello, smith
name1 is jane
name2 is john
name3 is claire
使用 *args 和 **kwargs 来调用函数
def test_args_kwargs(arg1, arg2, arg3):
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
# 使用 *args
args = ("two", 3, 5)
test_args_kwargs(*args)
# 结果:
arg1: two
arg2: 3
arg3: 5
# 使用 **kwargs:
kwargs = {"arg3": 3, "arg2": "two", "arg1": 5}
test_args_kwargs(**kwargs)
# 结果:
arg1: 5
arg2: two
arg3: 3
使用时的顺序
标准的参数, 然后是*, 然后是**
some_func(fargs, *args, **kwargs)
修饰器(装饰器)
是函数嵌套的一个重要应用。
本质:修饰器是一个函数,只不过函数的参数是其它函数,也就是说接受其它函数作为传入参数,对传入的函数做一定的修改之后,返回一个新的函数。
从函数中返回函数
1 def hi(name="vic"):
2 def greet():
3 return "now you are in the greet() function. hello vic."
4
5 def welcome():
6 n = name
7 return "now you are in the welcome() function. hello " + n
8
9 if name == "vic":
10 return greet
11 else:
12 return welcome
13
14 a = hi()
15 print(a)
16 #outputs: <function greet at 0x7f2143c01500>
17
18 #上面清晰地展示了`a`现在指向到hi()函数中的greet()函数
19 #现在试试这个
20
21 print(a())
22 #outputs: now you are in the greet() function. hello, vic.
23
24 b = hi('lara')()
25 print(b)
26
27 # namely
28 # b = hi('lara')
29 # print(b())
30
31 #outputs: now you are in the welcome() function. hello lara
什么是装饰器
装饰器里面定义一个wrap函数对需要装饰的函数进行包装,装饰器返回wrap函数,注意是wrapTheFunction不带括号
1 def a_new_decorator(a_func):
2
3 def wrapTheFunction():
4 print("I am doing some boring work before executing a_func()")
5
6 a_func()
7
8 print("I am doing some boring work after executing a_func()")
9
10 return wrapTheFunction
11
12 def a_function_requiring_decoration():
13 print("I am the function which needs some decoration to remove my foul smell")
14
15 a_function_requiring_decoration()
16 #outputs: "I am the function which needs some decoration to remove my foul smell"
17
18 # 对a_function_requiring_decoration进行装饰
19 a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
20 #now a_function_requiring_decoration is wrapped by wrapTheFunction()
21
22 a_function_requiring_decoration()
23 #outputs:I am doing some boring work before executing a_func()
24 # I am the function which needs some decoration to remove my foul smell
25 # I am doing some boring work after executing a_func()
使用@符号修改上面的栗子:
1 def a_new_decorator(a_func):
2
3 def wrapTheFunction():
4 print("I am doing some boring work before executing a_func()")
5
6 a_func()
7
8 print("I am doing some boring work after executing a_func()")
9
10 return wrapTheFunction
11
12 @a_new_decorator # 相当于一种简写,在需要装饰的函数定义上面加上@装饰器即可。
13 def a_function_requiring_decoration():
14 print("I am the function which needs some decoration to remove my foul smell")
15
16 a_function_requiring_decoration()
17 #outputs:I am doing some boring work before executing a_func()
18 # I am the function which needs some decoration to remove my foul smell
19 # I am doing some boring work after executing a_func()
但是目前存在一个问题:
如果我们运行打印出a_function_requiring_decoration的函数名,会发现实际上答应出了wrapTheFunction
# print the name of the decorated funciton
print(a_function_requiring_decoration.__name__)
会打印出:
wrapTheFunction
而不是我们所想要的“a_function_requiring_decoration”。因为wrapTheFunction重写了我们函数的名字和注释文档(docstring)。
可以通过一个内置函数解决这个问题:
functools.wraps
1 #导入一个内置函数wrap
2 from functools import wraps
3
4 def a_new_decorator(a_func):
5
6 #使用wrap装饰传入进来作为的参数函数
7 @wraps(a_func)
8 def wrapTheFunction():
9 print("I am doing some boring work before executing a_func()")
10
11 a_func()
12
13 print("I am doing some boring work after executing a_func()")
14
15 return wrapTheFunction
16
17 @a_new_decorator
18 def a_function_requiring_decoration():
19 print("I am the function which needs some decoration to remove my foul smell")
20
21 a_function_requiring_decoration()
22 #outputs:I am doing some boring work before executing a_func()
23 # I am the function which needs some decoration to remove my foul smell
24 # I am doing some boring work after executing a_func()
25
26 # print the name of the decorated funciton
27 print(a_function_requiring_decoration.__name__)
输出为:
I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()
a_function_requiring_decoration
另外一个装饰器使用的示例:
定义函数调用之前和之后要执行的代码
1 def before(func):
2 def wrapper(*args, **kwargs):
3 print('Before function is called.')
4 return func(*args, **kwargs)
5 return wrapper
6
7 def after(func):
8 def wrapper(*args, **kwargs):
9 result = func(*args, **kwargs)
10 print('After function is called.')
11 return result
12 return wrapper
13
14 @before
15 @after
16 def test():
17 print(3)
运行结果:
Before function is called.
3
After function is called.
协程
协程(Coroutine)可以实现单线程并发代码。
即各个子任务协作运行的意思,可以解决异步问题。
这里写代码片
元类 - metaclass
http://python.jobbole.com/21351/
https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python