python边写边总结(八)python的装饰器
发布日期:2021-06-29 06:03:25 浏览次数:2 分类:技术文章

本文共 3270 字,大约阅读时间需要 10 分钟。

之前在用flask的时候就碰到了装饰器,今天偶然又碰到decorator,决定总结一下decorator,主要学习资料来自

  • 变量解析规则
# code parta_string = "This is a global variable"def foo():     print a_string # 1foo()# output# This is a global variable

观察上述代码我们发现,在def的函数里面,即foo作用域成功调用了一个全局变量a_string,这是因为

创建变量一定会在当前作用域创建一个变量,但是访问或者修改变量时会在当前作用域查找变量,如果在本地作用域没有查找到,便会依次向上在闭合的作用域查找

  • 变量的生存周期

我们理解的作用域时变量所处的位置,而变量的生存周期即该作用域创建到结束这一过程,比如一个变量定义在一个函数里面,这个变量就会在调用函数执行时生成,在函数执行完的时候,该变量被销毁

  • python参数

python的参数与c++传递参数的方式有些区别,但是也有相同之处,普通的参数问题不必介绍,首先看看可变参数

所谓可变参数时传入的参数个数时可变的,可以是1、2、3...等任意多个,由于参数个数不确定,我们可以把参数以一个list或tuple传进来,看一下这几行代码

def calc(numbers):    sum = 0    for n in numbers:        sum = sum + n * n    return sum# numbers可以是一个list或者tuple,包含任意多个元素calc([1,2,3])# 调用的时候就把list或者tuple放进去

但是上述我们并不认为是可变参数,因为需要一个参数,你传了一个,只能算伪可变参数,我们看看真正的可变参数函数的设计,它的原理是将所有传入的参数合并为一个tuple

def calc(*numbers):    sum = 0    for n in numbers:        sum = sum + n * n    return sum# 在参数前加了一个*# 多个参数传入calc(1,2)# output 5calc()# output 0# 如果已经有一个list或者tuple如何做呢nums=[1,2,3]calc(*nums)>>>14

看了可变参数,我们来看看一个关键字参数问题

可变参数传入的时候组成的是tuple,而关键字参数传入的时候是自动组装成一个dict

def person(name, age, **kw):    print 'name:', name, 'age:', age, 'other:', kw

厉害之处在于这里的**kw,它可以让你传入以key=value形式的任意参数

person('Bob',35,city='Beijing')>>> name: Bob age: 35 other: {'city': 'Beijing'}

这里所谓组成dict,是说自己传入的key=value会组成一个dict

person('Adam',45,gender='M',job='Engineer')>>> name:Adam age:45 other{'gender','M','job':'Engineer'}

如果说你已经有一个dict,那么直接以**dict_name的形式传入就可以了

test_dict={'city':'Bejing','job':'Engineer'}person('Jack',24,**test_dict)
  • 嵌套函数
def outer():     x = 1     def inner():         print x # 1     inner() # 2 outer()>>>1
  • 把函数看成返回值
def outer():     def inner():         print "Inside inner"     return inner # 1 foo = outer() #2foo # doctest:+ELLIPSIS
foo()Inside inner

观察上面代码只是返回了一个函数值,直接执行outer(),只是返回inner,并不会执行inner()

但是如果用foo=outer()就收了inner就可以用foo()执行inner()

  • 闭包

python支持一个额叫做函数闭包的特性,嵌套定义在非全局作用域的函数能够记住它在被定义的时候它所处的封闭命名空间。这能够通过查看函数的func_closure属性得出揭露你,这个属性里面包含封闭作用域里面的值

def outer():     x = 1     def inner():         print x # 1     return innerfoo = outer()foo.func_closure # doctest: +ELLIPSIS(
,)# 这里嵌套定义的inner()函数能够记住它在被定义的时候它所处的封闭命名空间outer,能够通过查看函数的# func_closure属性得出结论,这个属性里面包含封闭作用域里面的值,即x

以上x是一个定值,不能改变,那么每次调用outer()的时候,x都不会变化,更难能可贵的时候,x可以作用outer的参数传入

def outer():     x = 1     def inner():         print x # 1     return innerfoo = outer()foo.func_closure # doctest: +ELLIPSIS(
,)
  • 装饰器

说了这么多,我们终于可以到装饰器了

def outer(some_func):     def inner():         print "before some_func"         ret = some_func() # 1         return ret + 1     return innerdef foo():     return 1decorated = outer(foo) # 2decorated()

观察一下,这里是把some_func作为参数传递到outer,并被嵌套定义的函数inner使用,当我们用decorated=outer(foo)接受了outer的返回值,就可以直接使用inner,然后inner是对foo的包装,所以,下面理解一下装饰器的含义

outer就是哪个装饰器,被装饰的函数是foo,它更新了foo的功能,这个更新的功能就是装饰

  • 使用@标识符将装饰器应用到函数
# 首先定义一个装饰器类型的函数def logger(func):     def inner(*args, **kwargs): #1         print "Arguments were: %s, %s" % (args, kwargs)         return func(*args, **kwargs) #2     return inner# 然后利用@直接装饰函数@logger def foo1(x, y=1):     return x * y@logger def foo2():     return 2# 使用foo1(5, 4)Arguments were: (5, 4), {}20foo1(1)Arguments were: (1,), {}1foo2()Arguments were: (), {}2

看到这里应该可以理解有些库的做法了,先定义一些装饰器函数,然后直接用@装饰自己定义的函数,这很棒,省掉自己的一些工作

现在可以回过头取看numba了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载地址:https://blog.csdn.net/zhouzhouasishuijiao/article/details/85018828 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python边用边总结(九)python的inspect
下一篇:python边写边总结(七)urllib学习

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月01日 21时16分59秒