概述
装饰器(Decorators)
装饰器是Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简洁,也更Pythonic。
- property类装饰器
- property()
- @property
- 闭包装饰器
- 指定参数个数
- 通用
假设我们要创建一个学生类,用set和get方法来修改实例属性
class Student():
def __init__(self, name, age):
self.__name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
if 0 < age < 100:
self.__age = age
else:
print("年龄不合理")
student1 = Student("Rico", 21)
print(student1.get_age())
student1.set_age(18)
print(student1.get_age())
现在我们利用装饰器来简化类的方法和函数功能,在使用实例对象时让代码跟简洁。
- @property
class Student():
def __init__(self, name, age):
self.__name = name
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
if 0 < age < 100:
self.__age = age
else:
print("年龄不合理")
student1 = Student("Rico", 21)
print(student1.age)
student1.age = 18
print(student1.age)
@property 可将方法调用转换为属性调用,被装饰的方法会直接进行内部托管,这样就使得实例属性在使用过程中方便了很多。
- property()
class Student():
def __init__(self, name, age):
self.__name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
if 0 < age < 100:
self.__age = age
else:
print("年龄不合理")
age = property(get_age, set_age)
student1 = Student("Rico", 21)
print(student1.age)
student1.age = 18
print(student1.age)
这里介绍一下property()的使用,
class property
(fget=None, fset=None)
如果c是Student的一个实例,c.x将调用getter ;c.x = value将调用setter。
- 闭包装饰器
首先,来创建一个闭包
def fuc_out(func):
def fuc_in(name, age):
func(name, age)
return fuc_in
def student(name, age):
if 0 < age < 100:
print("姓名:{};年龄:{}".format(name, age))
else:
print("年龄不合理")
student1 = fuc_out(student)
student1("Rico", 22)
使用闭包装饰器
def fuc_out(func):
def fuc_in(a, b):
func(a, b)
# 添加一个新功能
method()
return fuc_in
def method():
print("我是一个新功能")
@fuc_out
def student(name, age):
if 0 < age < 100:
print("姓名:{};年龄:{}".format(name, age))
else:
print("年龄不合理")
student("Rico", 22)
在此例中,@fuc_out相当于代替了student1=fuc_out(student)创建的过程。
这里简述一下闭包的作用,某些情况下我们不能对原本的代码方法进行修改,这时可以利用闭包来调用函数方法并添加为其新方法。另外,亦可以使用闭包来将函数方法进行组合,实现面向对象的编程目的。
- 通用装饰器
上述实例中,限定了student的参数,加入我现在需要给学生添加一个学号,那么就需要传递三个参数,这样就需要重新修改闭包的参数容量。
其实并不需要这样做,仅仅改动一个地方就可以了:
def fuc_out(func):
def fuc_in(*args, **kwargs):
func(*args, **kwargs)
#增添功能
method()
return fuc_in
def method():
print("我是一个新功能")
@fuc_out
def student(name, age):
if 0 < age < 100:
print("姓名:{};年龄:{}".format(name, age))
else:
print("年龄不合理")
@fuc_out
def student_add_id(name, age, id):
if 0 < age < 100:
print("姓名:{};年龄:{};学号:{}".format(name, age, id))
else:
print("年龄不合理")
student1 = student("Andy", 18)
student2 = student_add_id("Rico", 21, 123456789)
直接使用*args和**kwargs就解决了多个参数传递的问题。
*args 可以接受元组类型;**kwargs可以接受字典类型。