本篇内容介绍了“python装饰器property和setter怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
1.引子:函数也是对象
木有括号的函数那就不是在调用。
def hi(name="yasoob"):return "hi " + nameprint(hi())# output: 'hi yasoob'# 我们甚至可以将一个函数赋值给一个变量,比如greet = hi# 我们这里没有在使用小括号,因为我们并不是在调用hi函数# 而是在将它放在greet变量里头。我们尝试运行下这个print(greet())# output: 'hi yasoob'# 如果我们删掉旧的hi函数,看看会发生什么!del hiprint(hi())#outputs: NameErrorprint(greet())#outputs: 'hi yasoob'
2.函数内的函数
(1)在python中,一个函数内能嵌套定义另一个函数,并且可以在该大函数内调用该小函数。
def hi(name="yasoob"):print("now you are inside the hi() function")def greet():return "now you are in the greet() function"def welcome():return "now you are in the welcome() function"print(greet())print(welcome())print("now you are back in the hi() function")hi()#output:now you are inside the hi() function# now you are in the greet() function# now you are in the welcome() function# now you are back in the hi() function# 上面展示了无论何时你调用hi(), greet()和welcome()将会同时被调用。# 然后greet()和welcome()函数在hi()函数之外是不能访问的,比如:greet()#outputs: NameError: name 'greet' is not defined
(2)开始神奇的是,大函数的返回值可以是一个函数:
def hi(name="yasoob"):def greet():return "now you are in the greet() function"def welcome():return "now you are in the welcome() function"if name == "yasoob":return greet #这里!!else:return welcomea = hi()print(a)#outputs: <function greet at 0x7f2143c01500>#上面清晰地展示了`a`现在指向到hi()函数中的greet()函数#现在试试这个print(a())#outputs: now you are in the greet() function
在 if/else 语句中我们返回 greet 和 welcome,而不是 greet() 和 welcome()。
为什么那样?这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它。
当我们写下 a = hi(),hi() 会被执行,而由于 name 参数默认是 yasoob,所以函数 greet 被返回了。
PS:如果我们打印出 hi()(),这会输出 now you are in the greet() function。
(3)最后要说的是函数作为参数传入一个函数:
def hi():return "hi yasoob!"def doSomethingBeforeHi(func):print("I am doing some boring work before executing hi()")print(func())doSomethingBeforeHi(hi)#outputs:I am doing some boring work before executing hi()# hi yasoob!
3.装饰器小栗子
终于来到了带@的装饰器,其实就是带了@帽子的函数作为参数,传入@后面的函数中。
def a_new_decorator(a_func):def wrapTheFunction():print("I am doing some boring work before executing a_func()")a_func()print("I am doing some boring work after executing a_func()")return wrapTheFunction@a_new_decoratordef a_function_requiring_decoration():"""Hey you! Decorate me!"""print("I am the function which needs some decoration to ""remove my foul smell")a_function_requiring_decoration()#outputs: 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()#the @a_new_decorator is just a short way of saying:a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
上面的代码等价于我们熟悉的:
def a_new_decorator(a_func):def wrapTheFunction():print("I am doing some boring work before executing a_func()")a_func()print("I am doing some boring work after executing a_func()")return wrapTheFunctiondef a_function_requiring_decoration():print("I am the function which needs some decoration to remove my foul smell")a_function_requiring_decoration()#outputs: "I am the function which needs some decoration to remove my foul smell"a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)#now a_function_requiring_decoration is wrapped by wrapTheFunction()a_function_requiring_decoration()#outputs: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()
不过一开始上面被装饰过的函数名字已经悄悄发生“改变”,如果print下可以看出(如下代码)。
解决方案:
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
print(a_function_requiring_decoration.__name__)# Output: wrapTheFunction
最终加上@wraps的代码如下:
from functools import wrapsdef a_new_decorator(a_func):@wraps(a_func)def wrapTheFunction():print("I am doing some boring work before executing a_func()")a_func()print("I am doing some boring work after executing a_func()")return wrapTheFunction@a_new_decoratordef a_function_requiring_decoration():"""Hey yo! Decorate me!"""print("I am the function which needs some decoration to ""remove my foul smell")print(a_function_requiring_decoration.__name__)# Output: a_function_requiring_decoration
5.property和setter用法
class Timer:def __init__(self, value = 0.0):self._time = valueself._unit = 's'# 使用装饰器的时候,需要注意:# 1. 装饰器名,函数名需要一直# 2. property需要先声明,再写setter,顺序不能倒过来@propertydef time(self):return str(self._time) + ' ' + self._unit@time.setterdef time(self, value):if(value < 0):raise ValueError('Time cannot be negetive.')self._time = valuet = Timer()t.time = 1.0print(t.time)
“python装饰器property和setter怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!