python 属性
类属性和实例属性
在类中定义的是类属性,在实例中定义的是实例属性。
如下定义的属性是类属性:
class Person:
name = None
Person.gender = 'man'
如下定义的属性是实例属性:
class Person:
def __init__(self, tall = None):
self.tall = tall
person = Person()
person.old = 12
@property装饰器
如果在设置类的某一个实例属性前需要验证,可以使用@property
装饰器:
class Person:
@property
def name(self):
retuen self._name
@name.setter
def setName(self, value):
if name is None:
raise ValueError("name should be None!")
self._name = value
@name.deleter
def deleteName(self):
del self._name
属性描述符
如果说有多个属性有相同的验证方式,可以定义一个类以提高代码利用率。这个类被称为描述符。描述符类需要实现__set__
方法、__delete__
方法、__get__
方法或__set_name__
方法,其中__set_name__
方法是可选的。
属性描述符的用法为:
class NameValidator:
'''
假设这是一个属性描述符
'''
...
class Person:
name = NameValidator() #使用属性描述符创建name属性
alice = Person()
alice.name = "alice"
在类的定义中创建类属性,将其实例化为属性描述符,即对于该类声明了一个实例属性。对于类的实例中如果对该属性进行复制、获取和删除操作时都会访问属性描述符。
__set__
方法
__set__
方法用来设置属性。__set__
方法含有两个参数:instance
和value
,instance
代表属性的持有者,value
代表要设置的值。
class NameValidator:
def __set__(self, instance, value):
instance.__dict__['name] = value
class Person:
name = NameValidator()
alice = Person()
alice.name = "alice" # 调用__set__方法
__set_name__
方法
__set_name__
用于苗书旗获取属性的名称。__set_name__
方法有两个参数:owner
, name
。owner
指的是属性持有类的类对象,name
指的是属性名称。__set_name__
方法在属性持有类的初始化过程中会调用。
class NameValidator:
def __set_name__(self, owner, name):
self.property_name = name
class Person:
name = NameValidator() # 在Person类的初始化过程中调用,owner为Person类对象,name为属性名字符串"name"
__get__
方法
__get__
方法用来获取属性值。__get__
有两个参数,第一个参数instance
代表实例对象,第二个参数代表实例对象的类对象。在访问类的实例对象的描述器定义的属性的会被调用。
class NameValidator:
def __get__(self, instance, owner):
instance.__dict__['name] = value
class Person:
name = NameValidator()
alice = Person()
alice.name = "alice" # 调用__set__方法
print(alice.name) # 调用__get__方法, instance 值为alice, owner值为Person
__delete__
方法
__delete__
方法在删除属性的时候会被调用。有一个参数代表实例对象。
class NameValidator:
def __delete__(self, instance):
idel nstance.__dict__['name']
class Person:
name = NameValidator()
del alice.name # __delete__方法会被调用,instance为alice
属性描述符分为两种:数据描述符和非数据描述符:
- 数据描述符: 实现了
__set__
方法和/或__delete__
方法;- 非数据描述符: 只实现了
__get__
方法。
不同的描述符访问属性的顺序不同。对于非数据描述符,python首先从实例的__dict__
中查找属性,没有的话才会调用__get__
方法;对于数据描述符,python则直接通过__get__
方法获取属性。