一、提要
python的@property是python的一种装饰器,是用来修饰方法的。python @property 装饰器使一个方法可以像属性一样被使用。除此之外,还有几个使用场景,本文将叙述这些使用技巧。
二、关于属性的约定
首先看下属性的分类:
2.1 类绑定属性
一般类内属性是指定义成与类同一存储单元的属性,可以类访问。而当类实例化成对象后,类变量将做为拷贝加入对象,对象所访问的属性是一份拷贝。这份拷贝修改后易变。
python的@property是python的一种装饰器,是用来修饰方法的。python @property 装饰器使一个方法可以像属性一样被使用,而不需要在调用的时候带上() 接下来我们会了解什么时候需要使用它,并且在什么场景下需要用到它以及如何合理的使用它。
python类中@property装饰器,相配合的方法有:
setter() get() set() 相配合。
3.1 将一个属性转成方法
将一个属性转化为一个方法时,我们最好加上一个@property 装饰器来解决这个问题。在方法定义上面加一个@property 装饰器,可以在不改变原有调用方式的同时,来将一个属性改为一个方法。
class Goods():
def __init__(self,unit_price,weight):
self.unit_price = unit_price
self.weight = weight
@property
def price(self):
return self.unit_price * self.weight
lemons = Goods(7,4)
print(lemons.price)
结果:28
上文中,price是方法,现在将方法转化成属性调用。注意这个技巧,要知道原类定义中无price这个属性,这是一个临时产生的结果。类同于excel表格的“计算项”。
3.2 私有化某些属性
对于某些属性,不可直接访问。这里的“直接”就是“无条件”的意思;而条件的访问,就需要装饰器 @property,下例是双装饰器@property和@age.setter配合,对_age进行条件隔离的例子:
class Stranger(object):
def __init__(self, gender=None, age=None, job=None):
self.gender = gender
self._age = age # 这里的成员属性_age需要与成员方法age()区分开
self.jobb = job
# 读取age
@property # 实现一个age相关的getter方法
def age(self):
return self._age
# 设置age
@age.setter # 实现一个age相关的setter方法
def age(self, value):
if isinstance(value, int):
self._age = value
else:
raise ValueError("'int' type need")
if __name__ == "__main__":
# 创建一个“妹子”
meizi = Stranger()
meizi.age = 18 # 使用时注意是.age,不是._age
print("年龄:{age}".format(age=meizi.age))
注意事项:
属性名与方法名一定要区分开,不然会进入死循环(self._age,def age()) 实例化的对象使用属性时,不是调用属性(meizi._age),而是用的方法名(meizi.age) @property其实就是实现了getter功能; @xxx.setter实现的是setter功能;还有一个 @xxx.deleter实现删除功能 定义方法的时候 @property必须在 @xxx.setter之前,且二者修饰的方法名相同(age()) 如果只实现了 @property(而没有实现@xxx.setter),那么该属性为 只读属性
三、@staticmethod 和 @classmethod区别
一个比较简单粗暴的区分方式:
1、如果你的方法访问了类中的其他变量/方法,那么就使用@classmethod。
2、另一方面,如果方法没有接触到类中的任何其他变量,那么就使用@staticmethod。 3、但是其设计有更深的逻辑联系: classmethod主要用于替代构造函数。 staticmethod不使用对象的状态,甚至不使用类本身的结构。它可以是一个类外部的函数。它只放在类的内部,用于分组具有类似功能的函数(例如,像Java的数学类静态方法)
class Person:
age = 25
@classmethod
def printAge(cls):
print('The age is:', cls.age)
Person.printAge()