之前已经介绍过类的一些基础知识,同时装饰器也在前面的博客中记录过了,大家有兴趣的话可以去翻一下呀。在这里哦!装饰器的功能就是可以让函数多一些功能,注意这里是装饰函数哦,所以这些额外的功能往往是可以重复被各种函数使用的,也正是因此使用装饰器的话就能避免代码的重写,也使得代码变得更加有条理更加简洁。装饰器的功能不再赘述啦。
在python的类中,由于类中包含有函数,因此类中也有经常需要使用到的装饰器,这些装饰器的功能可是很强大的哦,它们分别是classmethod(类方法,仅仅是个翻译哈。这里要注意不要和类中的函数混淆哦,因为类中的函数我们也叫类方法)、staticmethod(静态方法)、property(类属性装饰器)。这些装饰器都是默认存在于python中的,因此使用时不用再安装什么其它的东西啦,直接使用就行。
附上类使用专栏的其它文章的链接:
- python 类的使用(1) 之类使用的基本框架
- python 类的使用(2) 之类变量
- python 类的使用(3)之类中常用的三个装饰器@classmethod、@staticmethod、@property
- python 类的使用(4)之类常用的魔法方法
- python 类的使用(5)之类装饰器(类的装饰器和类作为装饰器)
- python 类的使用(6)之类的继承
- python 类的使用(7)之类的私有属性和方法 (类中以单下划线或双下划线开头的变量名或函数名)
classmethod
classmethod能够完成的功能有:
- 修改类中的变量,不论是类变量还是类实例传入的参数变量
- 产生类实例,即装饰有classmethod的函数能够产生类实例(可能会有点懵,看看例子就明白啦)
修改类变量的例子:
class Worker:
raise_percent = 1 # 默认没有涨工资,比例为1
def __init__(self, name, salary):
self.name = name
self.salary = salary
@classmethod # 加入此装饰器
def ch_raise_percent(cls, num): # 修改涨薪比例的函数
cls.raise_percent = num * cls.raise_percent # 传入一个数乘以之前的涨薪比例
'''
这里要多解释一下,传入的是cls,这里cls代表类本身。要传入类本身才能够修改类本身的内容(如类变量),
由于传的是类本身,使用class的话会与class定义语句有冲突,因此使用classmethod要传入类的信息时,
将类本身以cls形式传入。
后面传入的num是在调用这个函数(即ch_raise_percent)时传入的参数,这个参数和创建类实例需要的
参数是没有关系的,因为调用这个函数仅仅是修改了类本身的信息。
'''
Worker.ch_raise_percent(1.3)
# 这里在类外部调用classmethod装饰的函数,并传入一个num参数用于修改涨薪比例
print(Worker.raise_percent)
# 使用类本身查看其类变量是否变化
# 执行结果为1.3,表示这里我们确实把Worker类的raise_percent类变量给修改了。
有人可能会想使用其它方式不能直接修改类变量吗,比如在类函数中传入self,然后调用类变量(即self.raise_percent)来进行修改,但是实际上你在类函数中调用后修改产生的是局部变量,整个类是获取不到你修改得到的局部变量的。当然还有可能你会想使用global或者nonlocal(如global self.raise_percent或者self.raise_percent)等方法使函数产生的结果变成非局部变量,这个我也试了,好像是不行的。如果你还有其它方法的话,也欢迎提出来呀!
产生类实例的方法:
产生类实例的方法真的是非常好用啊,比如你的初始数据是一堆有规则的字符串,而这些字符串中包含着每个类实例所需的参数,那么你只需要添加一个classmethod装饰的函数,用这个函数帮你处理一下你的字符串,将这些字符串分成独立的项,再将这些项传递给类就可以产生类实例啦!
看看例子哈:
class Worker:
def __init__(self, name, age, height, salary):
self.name = name
self.age = age
self.height = height
self.salary = salary
@classmethod
def str_handler(cls, string):
name, age, height, salary = string.split('/')
# 将传入的字符串以/分割产生列表,一一对应
return cls(name, age, height, salary)
# 这里return返回的就是cls,也就是一个类实例,将Worker类类实例需要的
# 所有项都传入了cls,这就是一个完完整整的类实例啦
# 要注意return返回值可以被变量接收,接收后就成为类实例咯
A = 'Jack/20/1.75/1000'
B = 'Mary/18/1.65/2000'
# 两个需要处理的字符串
a = Worker.str_handler(A)
b = Worker.str_handler(B)
# 两次调用此类中的函数,产生两个类实例即a和b
print(a.name, a.age, a.height, a.salary)
print(b.name, b.age, b.height, b.salary)
# 查看类实例是否创建成功
运行结果:
staticmethod
staticmethod也叫静态方法,实际上staticmethod装饰的函数的功能可能和类本身没什么太大的关系,因为staticmethod装饰的函数不能传入类实例或者类变量或者刚刚提到的cls。因此这个函数处理的功能只是额外的,比如帮你记录一下日期之类的功能。这样的功能可能在某些时候会用上,所以就把这样的函数也顺带包装在类中。看一个例子就明白啦:
class Worker:
def __init__(self, name, age, height, salary):
self.name = name
self.age = age
self.height = height
self.salary = salary
@classmethod
def str_handler(cls, string):
name, age, height, salary = string.split('/')
return cls(name, age, height, salary)
@staticmethod # 静态方法装饰器
def read_file(worker_file):
f = open(worker_file,'r')
lines = f.readlines()
return lines
# 这里的功能就是读取工作人员的记录文件,将每一行内容作为一个item
# 记录到lines列表,最后将列表传出以供后续利用
# 有没有留意到,这个和类本身的功能是没有关系的,也就是实际上我们在类外部执行这个函数
# 或者单独执行这些代码也是一样的功能,只不过包装在类中更便于管理和使用而已
all_workers = Worker.read_file('2020_workers.txt')
# 使用上面的静态方法读取一个文件,这里假设有这个“2020_workers.txt”文件,其中每行都是
# Jack/20/1.75/1000 这样的内容
for item in all_workers:
worker = Worker.str_handlerhandler(item)
# 通过for循环可以将文件中所有行都转为类实例
# 后面对类实例的操作就不写啦
静态方法的内容较简单,就不多写啦。
property
相对来说property装饰器的使用可能较复杂一点,property的翻译就是属性,因此其跟属性有关啦。而装饰器又是用来装饰函数的,那其实加property装饰器的功能就是将函数的返回值作为类的属性啦。什么意思呢,也就是说我们调用这个被装饰的函数不需要加括号去运行,而是直接像变量或者属性一样获取这个值。
看下例子吧:
class Worker:
def __init__(self, name, salary):
self.name = name
self.salary = salary
@property
def name_and_salary(self):
return self.name+'的工资是'+str(self.salary)
# 需要有返回值,返回值作为获取到的属性嘛
A = Worker('Jack',1000)
A.name_and_salary
# 注意这里不用加括号哦,像变量或者属性一样去调用就好了
现在应该理解property的作用了吧,当然property不止这点作用,使用property装饰后,被装饰的函数就成为了新的装饰器,新的装饰器常用的有三个,如上例中就是getter(默认的,即赋予类使用者获取某属性的能力)、setter(赋予类使用者在类外部给某类属性重新赋值的能力)和deleter(赋予类使用者在类外部删除某属性的能力)。看下例子就理解啦:
class Worker:
def __init__(self, name, salary):
self.name = name
self.salary = salary
@property
# 先使用property装饰原函数,装饰之后就可以使用setter和deleter方法来进行装饰并有更多的功能了
# 这里默认已经有了getter的功能,也就是能够获取到这个属性的能力
def view_salary(self):
return self.salary
@view_salary.setter
# setter装饰器能够使我们在类外部重新设置view_salary这个属性
# 而没有setter的话就会报错 AttributeError: can't set attribute
def view_salary(self, new_salary):
self.salary = new_salary
return new_salary
@view_salary.deleter
# deleter装饰器的设置使我们可以在类外部使用del删除这个属性,但是这里我试了将self.salary
# 设置为其它值也是可以的哦,这个值设置非空的话还是会有属性继续存在的哦。也就是在类外部使用
# del的功能取决于你自己在这里设置的操作
# 我这里是设置为空值了
def view_salary(self):
self.salary = None
A = Worker('J',1000)
A.view_salary = 2000
# 这里在外部进行赋值,是使用的设置的setter方法哦,没有setter会报错的!!
print("使用setter后的view_salary 值是:"A.view_salary)
del A.view_salary # 尝试删除
print("使用del后J 的view_salary 的属性值是:"A.view_salary)
结果如下:
叮
我觉得应该多多看看我的例子就能够完全理解上面几个装饰器啦,我就不再多赘述啦!当然这些技术不管怎么样都要用到实际应用中才能够发挥到其最终的功效,因此在你觉得可以使用某些方式的情况下一定要去尝试一下哦!最后希望我的文章能帮到大家就是最好啦!
今天是平安夜,明天是圣诞节,祝大家节日快乐,生活愉快呀!可能到明年才有下一篇了,哈哈哈哈哈哈哈!
参考:https://www.py.cn/course/1106.html
参考:https://zhuanlan.zhihu.com/p/64487092
参考:http://c.biancheng.net/view/4561.html