python装饰器property和setter用法

作者:wx62cea850b9e28??????? 时间:2023-02-14 09:01:05 

1.引子:函数也是对象

木有括号的函数那就不是在调用。

def hi(name="yasoob"):
return "hi " + name
print(hi())
# output: 'hi yasoob'
# 我们甚至可以将一个函数赋值给一个变量,比如
greet = hi
# 我们这里没有在使用小括号,因为我们并不是在调用hi函数
# 而是在将它放在greet变量里头。我们尝试运行下这个
print(greet())
# output: 'hi yasoob'
# 如果我们删掉旧的hi函数,看看会发生什么!
del hi
print(hi())
#outputs: NameError
print(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 welcome
a = 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_decorator
def 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 wrapTheFunction

def 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()

不过一开始上面被装饰过的函数名字已经悄悄发生&ldquo;改变&rdquo;,如果print下可以看出(如下代码)。
解决方案:
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

print(a_function_requiring_decoration.__name__)
# Output: wrapTheFunction

最终加上@wraps的代码如下:

from functools import wraps
def 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_decorator
def 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 = value
self._unit = 's'
# 使用装饰器的时候,需要注意:
# 1. 装饰器名,函数名需要一直
# 2. property需要先声明,再写setter,顺序不能倒过来
@property
def time(self):
return str(self._time) + ' ' + self._unit
@time.setter
def time(self, value):
if(value < 0):
raise ValueError('Time cannot be negetive.')
self._time = value
t = Timer()
t.time = 1.0
print(t.time)

来源:https://blog.51cto.com/u_15717393/5470902

标签:python,装饰器,property,setter,用法
0
投稿

猜你喜欢

  • PHP异步调用socket实现代码

    2023-06-26 09:23:09
  • DBCC CHECKIDENT 重置数据库标识列从某一数值开始

    2024-01-15 11:16:27
  • python使用opencv驱动摄像头的方法

    2023-08-26 17:00:49
  • python图像平滑处理原理

    2023-07-07 00:21:11
  • JS添加删除一组文本框并对输入信息加以验证判断其正确性

    2024-05-03 15:30:54
  • asp中access升级到sql server后要做的工作

    2007-08-11 13:35:00
  • 几个图片按比例缩放的代码

    2008-02-13 08:51:00
  • python利用OpenCV2实现人脸检测

    2021-05-14 11:03:45
  • Python基于smtplib模块发送邮件代码实例

    2022-09-18 11:07:49
  • 从git仓库中删除.idea文件夹的小妙招

    2022-10-29 04:12:00
  • Python如何求取逆序数

    2022-07-16 07:16:57
  • JS变量及其作用域

    2024-04-10 10:40:19
  • asp学习入门基本语法知识

    2007-11-07 14:02:00
  • vue源码之批量异步更新策略的深入解析

    2024-05-09 15:21:30
  • php删除一个路径下的所有文件夹和文件的方法

    2024-06-05 09:51:11
  • 通过 Python 和 OpenCV 实现目标数量监控

    2021-08-18 19:18:24
  • GoLang nil与interface的空指针深入分析

    2024-02-18 01:58:50
  • keras CNN卷积核可视化,热度图教程

    2021-03-15 05:06:15
  • 对python中assert、isinstance的用法详解

    2022-04-29 14:10:54
  • SQL Server 置疑、可疑、正在恢复等情况分析

    2012-01-05 18:51:59
  • asp之家 网络编程 m.aspxhome.com