在代码运行期间动态增加功能的方式,称为装饰器Decorator。常见的内置装饰器有:
@property@setter装饰器 以一个函数作为参数,并返回一个函数
def log(f): def write_log(*args, **kw): # 使用*是说可变参数,不限制参数的数量 with open('./module2/a.txt', 'w') as f1: # 这样写的好处是不用再单独写f1.close,他会自动关闭,不会造成资源的浪费 f1.write(f.__name__) print('写入日志成功,函数名字是:%s' % f.__name__) return f(*args, **kw) # 返回的是f这个方法,是把now传进来,然后封装成write_log,然后再把now返回出来,同时也对now进行了执行 return write_log # 传出来的也是一个方法 # write_log 有两个功能,一个是打印日志的功能,一个是now打印日志的功能 # 由于返回的是函数名write_log,而不是write_log(),所以write_log中的now并没有执行两遍,这个方式比较反人类,所以用下面的@来进行装饰
import datetime @log def now(): print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) now()学习 @property 和 @setter 原始代码:
class Student(): def __init__(self, score): self.__score = score def get_score(self): return self.__score def set_score(self, value): if not isinstance(value, int): raise ValueError('Score must be an integer!') if value < 0 or value> 100: raise ValueError('Score must between 0~100!') self.__score = value stu1 = Student(90) print(stu1.get_score()) stu1.set_score(85) print(stu1.get_score())加上装饰器,方法变成属性
class Student(): def __init__(self, score): self.__score = score @property def score(self): return self.__score @score.setter def score(self, value): # 此时看着两个函数一样,但上面那个无参,下面这个有参 # 但尽量还是避免重复命名的参数 if not isinstance(value, int): raise ValueError('Score must be an integer!') if value < 0 or value> 100: raise ValueError('Score must between 0~100!') self.__score = value stu2 = Student('98') print(stu2.score) print(type(stu2.score)) stu2 = Student(67) print(stu2.score) print(type(stu2.score)) # stu2.score = '59'运行之后,得到的结果是:
98 <class 'str'> 67 <class 'int'>这里要注意一下程序的流程:
stu2 = Student('98') # 实例化一个对象stu2,同时调用__init__方法,将stu2的score属性变成了‘98’ print(stu2.score) # 这里对stu2.score进行打印,Python内置的@property装饰器就是负责把一个方法变成属性调用的,所以会将绑定了self的score属性进行打印 print(type(stu2.score)) # 根据上面的结果,此时输出的值就是字符串类型 stu2 = Student(67) # 和上面的字符串类型的一样,只不过这里传的参数是int类型的67 print(stu2.score) print(type(stu2.score))若果代码换成:
stu2.score = 88 print(stu2.score) print(type(stu2.score)) stu2.score = '59'会先输出:
88 <class 'int'>然后报错,并且报错信息为我们自己定义的‘Score must be an integer!’’ 这是因为这几句代码是先调用了被@score.setter装饰过的score方法,这样可以对stu2的score属性进行修改,而当传入的值为字符串类型的时候,就会提示我们自定义过的错误。
