python的@property是python的一种装饰器,是用来修饰方法的。python @property 装饰器使一个方法可以像属性一样被使用。除此之外,还有几个使用场景,本文将叙述这些使用技巧。
首先看下属性的分类:
一般类内属性是指定义成与类同一存储单元的属性,可以类访问。而当类实例化成对象后,类变量将做为拷贝加入对象,对象所访问的属性是一份拷贝。这份拷贝修改后易变。
验证代码
- class Stranger(object):
- name = 'class name' #类绑定属性
- def __init__(self, gender=None ):
- self.gender = gender #对象绑定属性
- self.name = 'new name' #对象中属性,与类属性的同名拷贝
-
- stan = Stranger('male')
- print(1,stan.gender)
- stan.gender = 'famel'
- print(2,stan.gender)
- print(3 stan.name)
- print( 4, Stranger.name)
结果:
1 male
2 famel
3 new name
4 class name
凡用self定义的属性,都是对象绑定属性,
- class Stranger(object):
- def __init__(self, gender=None ):
- self.gender = gender
-
- stan = Stranger('roma')
- print(stan.gender)
-
- stan.gender = 'Paras'
- print(stan.gender)
结果:
roma
Paras
注意:事实上实例化后的对象,也可以定义属性,外部也可以调用。
python的私有属性没有编译限定,知识以单下划线_开头,标记此属性是私有的,但是外部也可以自由访问(私有的程度不够多)。另一种是双下划线__开头的属性,可以转化成类属性访问
python的@property是python的一种装饰器,是用来修饰方法的。python @property 装饰器使一个方法可以像属性一样被使用,而不需要在调用的时候带上()
接下来我们会了解什么时候需要使用它,并且在什么场景下需要用到它以及如何合理的使用它。
python类中@property装饰器,相配合的方法有:
相配合。
将一个属性转化为一个方法时,我们最好加上一个@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表格的“计算项”。
对于某些属性,不可直接访问。这里的“直接”就是“无条件”的意思;而条件的访问,就需要装饰器 @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))
注意事项:
比如,我们输入了first_name、last_name可以得出fullname,下面代码可以实现全名的属性获取。而反过来,对全名进行修改后,如何将连带的first_name、last_name同步进行修改?。下文中的 @fullname.setter就是解决此类问题的。
- class Person():
- def __init__(self, first_name, last_name):
- self.first = first_name
- self.last = last_name
-
- @property
- def fullname(self):
- return self.first + ' ' + self.last
-
- @fullname.setter
- def fullname(self, name):
- first_name, last_name = name.split()
- self.first = first_name
- self.last = last_name
-
- def email(self):
- return '{}.{}@email.com'.format(self.first, self.last)
-
-
- person = Person('zhang', 'san')
- print(person.fullname)
- print(person.last)
- print(person.first)
-
- person.fullname = 'li si'
- print(person.fullname)
- print(person.last)
- print(person.first)
deleter
方法 和setter
方法类似,当我们需要删除一个属性时,我们会使用deleter
方法。
你可以像定义setter
方法一样来定义一个setter
方法,使用相同的方法名,并在方法上添加@{methodname}.deleter
装饰器 。
- class Person():
- def __init__(self, first_name, last_name):
- self.first = first_name
- self.last = last_name
-
- @property
- def fullname(self):
- return self.first + ' ' + self.last
-
- @fullname.setter
- def fullname(self, name):
- first_name, last_name = name.split()
- self.first = first_name
- self.last = last_name
-
- @fullname.deleter
- def fullname(self):
- self.first = None
- self.last = None
-
- def email(self):
- return '{}.{}@email.com'.format(self.first, self.last)
-
-
- person = Person('zhang', 'san')
- print(person.fullname)
- print(person.last)
- print(person.first)
-
- del person.fullname
-
- print(person.last)
- print(person.first)
使用该函数可以将方法直接变成属性,与@property类同。
使用property的代码示例:
- class Stranger(object):
- def __init__(self, gender=None, age=None, job=None):
- self.gender = gender
- self._age = age
- self.jobb = job
-
- # 设置_age
- def set_age(self, age):
- if isinstance(age, int):
- self._age = age
- else:
- raise ValueError("'int' type need")
-
- # 读取_age
- def get_age(self):
- return self._age
-
- # 使得实例化对象可以利用.age方式来访问
- age = property(get_age, set_age)
-
-
- if __name__ == "__main__":
- # 创建一个“妹子”
- meizi = Stranger()
-
- meizi.age = 18
- print("年龄:{age}".format(age=meizi.age))
# 输出:
#年龄:18