實現了__set__(), __get__()或__delete__()的對象,且描述符屬性只能定義在類級別。
@property可利用描述符實現。(@classmethod, @staticmethod等也可以用描述符實現)
利用描述符來進行類型檢查。
<b>Python中屬性引用解析的執行方式,優先級鏈搜索屬性。</b>數據描述符(實現了__set__(), __get__())優先級>實例變量>非數據描述符(只實現__get__())。在下例中實際給屬性賦值時, u_0.name='test'
等同于type(u_0).__dict__['name'].__set__(u_0, 'test')
,取值,訪問屬性u_.name
等同于type(u_0).__dict__['name'].__get__(u_0, type(u_0))
class Field(object):
_expected_type = type(None)
def __init__(self, name):
self.name = name
def __set__(self, instance, value):
if not isinstance(value, self._expected_type):
raise TypeError('excepted %s' % self._expected_type)
# setattr(instance, self.name, value)
instance.__dict__[self.name] = value
def __get__(self, instance, owner):
if not instance:
return self
# getattr(instance, self.name)
return instance.__dict__[self.name]
class StringField(Field):
_expected_type = str
class IntField(Field):
_expected_type = int
class User_0(object):
name = StringField('name')
age = IntField('age')
def __init__(self, name, age):
self.name = name
self.age = age
u_0 = User_0(name='JiangW', age=22)
u_0.name = 'test'
print(u_.age)
# TypeError: excepted <class 'int'>
# User_0(name='JiangW', age='22')
其他方式實現類型檢查。
利用函數和@property。property實際是一個描述符類,CheckType()方法返回的實際是一個<class 'property'>
的對象, 該對象也是實現了__set__(), __get__()。
def CheckType(name, expected_type):
_name = name
@property
def res(self):
return getattr(self, _name)
@res.setter
def res(self, value):
if not isinstance(value, expected_type):
raise TypeError('excepted type %s' % excepted_type)
setattr(self, _name, value)
return res