函数作为对象使用

  • python中一切皆为对象,函数也是对象,有很多离谱操作
  • 赋值给变量
  • 作为另一个函数的实参
  • 作为函数的返回值
  • 嵌套定义值另一个函数中

lambda表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def add(num1, num2):
return num1 + num2


print(add(1, 2))

print((lambda num1, num2: num1 + num2)(1, 2))

le = lambda num1, num2: num1 + num2
print(le(1, 2))

result = map(lambda x: x * x, [1, 2, 3, 4])
print(list(result))


def do_sth():
return lambda num1, num2: num1 + num2


print(do_sth()(1, 2))
  • 相当于是一个匿名函数,同样是一个对象,也可以像函数那样用

偏函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from functools import partial


def f(a, b=5):
print('a =', a, 'b =', b)


f_new = partial(f, 2)

f_new()
f_new(6)
f_new(b=6)


# f_new(a = 3)


def eval_sum(*args):
s = 0
for n in args:
s += n
return s


eval_sum_new = partial(eval_sum, 20, 30)
print(eval_sum_new(1, 2, 3, 4, 5))

def f1(a, b=5, *args, **kwargs):
print('a =', a, 'b =', b, 'args =', args, 'kwargs =', kwargs)


f1_new = partial(f1, 1, 3, 6, m=8)
f1_new(2, 4, n=9)


def f2(a, b=5, *, c, **kwargs):
print('a =', a, 'b =', b, 'c =', c, 'kwargs =', kwargs)


f2_new = partial(f2, 1, m=8)
f2_new(3, c=9)
  • python可以为函数指定默认参数
  • 一个函数定义的时候没有指定默认值,但后续使用的时候想给其指定,可以使用偏函数来实现

闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def outer():
a = 10

def inner():
print(a)

return inner


def do_sth():
temp = 8
print(temp)


do_sth()
# print(temp)

outer_result = outer()
outer_result()
outer()()

print(outer_result.__closure__)
print(outer_result.__closure__[0].cell_contents)
  • 正常情况下,函数被调用后,函数内部声明的变量就会失效
  • 如果一个函数的内部函数引用了外部函数,且外部函数的返回值是内部函数,这个种情况叫闭包,被内部函数引用的变量可以在内部函数特殊属性__closure__中找到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def outer2():
a = 10

def inner2():
# a = 11

# a += 1

pass

return inner2


def outer3():
a = [3]

def inner3():
# a = [1]

a[0] = 8

print(a)

return inner3


outer3()()


def outer4():
a = 10

def inner4():
nonlocal a

# a = 11
a += 1

print(a)

return inner4


outer4_result = outer4()
outer4_result()

outer4_result()
  • 内部函数不能对外部函数的不可变类型的变量进行修改,只会进行覆盖,如果要进行修改需要使用nonlocal关键字来声明对外部函数变量进行使用
  • 闭包的内部函数持有了外部函数的资源,使其在脱离了外部函数之后还可以独立的运行,具体的使用场景后续再探索

globals()和locals()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def outer(a):
b = 8

def inner(c):
d = 3

print(locals()) # {'a': 5, 'b': 8, 'inner': <function outer.<locals>.inner at 0x107fd94c0>}


outer(5)

g = 2


class MyClass(object):
pass


print(globals()) # {'__name__': '__main__' ... 'outer': <function outer at 0x107fd9670>, 'g': 2, 'MyClass': <class '__main__.MyClass'>}
  • 都是返回各自作用域中所有的对象类型和value,注意函数也是对象所以也被返回了
  • globals中打印了object中的资源所以有很多数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def f():
x = 8
print(locals())

locals()['x'] = 9
locals()['y'] = 10

print(locals())


f()
g = 2
globals()['g'] = 6
globals()['gg'] = 66

print(globals())
  • locals返回的是值拷贝,所以通过locals无法修改资源,但是可以通过映射添加新资源
  • globals返回的是真实的命名空间(数据名和数值),通过globals做的任何修改都会生效

作用域

  • 上面说到的闭包的作用域比较特殊
  • 还有就是python2和3中列表推导的差异,3中列表推导相当于一个函数有独立的作用域,注意for-in语句一直没有独立作用域

代理