闭包

闭包可以帮助记住一些函数状态,这些事情类也可以做到


In [23]:
def produce(N):
    def action(X):
        return X*N
    return action

f1 = produce(2)
f2 = produce(4)
print(f1(10))
print(f2(10))


20
40

lambda表达式


In [24]:
x = lambda n:n*n

In [25]:
x(10)


Out[25]:
100

In [26]:
f = lambda a,b:a+b

In [27]:
f(1,2)


Out[27]:
3

In [20]:
lower = (lambda x,y:x if x<y else y)
lower('a','b')


Out[20]:
'a'

In [33]:
#关于作用域的一些问题
def makeAction():
    act=[]
    for i in range(5):
        act.append(lambda x:i**x)
    return act
act = makeAction()
print(act[0](2))
print(act[2](2))


16
16

In [35]:
#可以发现上面的结果都是16,这个很不符合常理,实际上,当运行act[]的函数的时候,
#这个时候才会去查询i而i已经循环到最后一个数字4了,所以后面执行的结果都是4
#为了避免这种情况
#关于作用域的一些问题,我们应该讲变量以参数形式传入
def makeAction():
    act=[]
    for i in range(5):
        act.append(lambda x,i=i:i**x)
    return act
act = makeAction()
print(act[0](2))
print(act[2](2))


0
4

In [3]:
## 函数高级用法,在列表中遍历使用函数
def func(arg):
    print(arg)

for (f,a) in [(func,'abc'),(func,'def')]:
    f(a)


abc
def

In [6]:
## 可以自定义函数属性,可以直接在外面添加函数的属性。
def func(arg):
    print(arg)

func.count = 0;
func.myAbr = "pro";
dir(func)


Out[6]:
['__annotations__',
 '__call__',
 '__class__',
 '__closure__',
 '__code__',
 '__defaults__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__get__',
 '__getattribute__',
 '__globals__',
 '__gt__',
 '__hash__',
 '__init__',
 '__kwdefaults__',
 '__le__',
 '__lt__',
 '__module__',
 '__name__',
 '__ne__',
 '__new__',
 '__qualname__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'count',
 'myAbr']

In [17]:
## 编写函数注解,注解只是附加信息,可以在__annotations__进行查看
def func(a:'spam',b:(1,10),c:float)->int:
    return a+b+c
func.__annotations__


Out[17]:
{'a': 'spam', 'b': (1, 10), 'c': float, 'return': int}

In [18]:
## 带默认值的注解
def func(a:'int'=10,b:float=10):
    print(a,b)
func.__annotations__


Out[18]:
{'a': 'int', 'b': float}

In [19]:
func()


10 10

In [23]:
## map对每一个元素使用响应的函数
def inc(x):return x+10
print(list(map(inc,[1,2,3,4])))


[11, 12, 13, 14]

In [24]:
#filter过滤器,针对某个函数去过滤一些数值
list(x for x in range(-5,5) if x>0)


Out[24]:
[1, 2, 3, 4]

In [25]:
list(filter((lambda x:x>0),range(-5,5)))


Out[25]:
[1, 2, 3, 4]

In [27]:
## 混合map和filter
list(map((lambda x:x*2),filter((lambda x:x%2==0),range(10))))


Out[27]:
[0, 4, 8, 12, 16]

生成器

生成器yield是返回一个值之后继续保持函数的运行状态,而return则是返回后结束函数的运行。


In [19]:
#三种方法对生成器的值进行迭代
def ProQuare(N):
    for i in range(N):
        yield i**2

In [20]:
x = ProQuare(10)

In [21]:
list(x)


Out[21]:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

In [22]:
x = ProQuare(10)
x.__next__()


Out[22]:
0

In [23]:
x = ProQuare(10)
next(x)


Out[23]:
0

In [28]:
## 迭代器和列表解析
(x for x in range(4))  #生成一个迭代器对象


Out[28]:
<generator object <genexpr> at 0x0000019E70AA2F10>

In [30]:
g = (x for x in range(4))  #迭代器
g.__next__()


Out[30]:
0

In [27]:
[x for x in range(4)] #生成列表


Out[27]:
[0, 1, 2, 3]

In [40]:
## 将内置对象封装成迭代器
g = iter([1,2,3,4])
g


Out[40]:
<list_iterator at 0x19e70a38b38>

In [41]:
print(g.__next__())
print(next(g))


1
2

计时


In [2]:
import time
start = time.clock()
for i in range(10000):
    i*i*i
print(time.clock()-start)


0.0025341354153791094

In [6]:
# 模块化测试
import time 

def timer(func,*pargs,**kargs):
    start = time.clock()
    func(*pargs,**kargs)
    elapsed = time.clock()-start
    return elapsed

In [7]:
def fun1():
    for i in range(10000):
        i*i*i
def fun2():
    [i*i*i for i in range(10000)]

for func in (fun1,fun2):
    print(timer(func))


0.001551538798956642
0.001782239276110431

In [15]:
## 函数中一些奇怪的现象
x = 10
def selec():
    print(x)
selec()


10

In [17]:
x = 10
def selec():
    print(x)
    x = 20
selec()  #会报错,原因是python在编译的时候,将x认作为本地变量,而不会去查找全局变量
         #所以本地变量在定义前被使用,所以报错


---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-17-eabd3e5b0429> in <module>()
      3     print(x)
      4     x = 20
----> 5 selec()  #会报错,原因是python在编译的时候,将x认作为本地变量,而不会去查找全局变量
      6          #所以本地变量在定义前被使用,所以报错

<ipython-input-17-eabd3e5b0429> in selec()
      1 x = 10
      2 def selec():
----> 3     print(x)
      4     x = 20
      5 selec()  #会报错,原因是python在编译的时候,将x认作为本地变量,而不会去查找全局变量

UnboundLocalError: local variable 'x' referenced before assignment

In [19]:
#每次调用结果不同,函数默认保留了静态变量
def func(x=[]):
    x.append(1)
    print(x)
func()
func()


[1]
[1, 1]

In [23]:
def func(x = None):
    if x == None:
        x = []
    x.append(1)
    print(x)
func()
func()
func([2])
func([4])


[1]
[1]
[2, 1]
[4, 1]

In [ ]: