这段代码来自于《Python Cook Book 3rd Edition》中的类章节第8.13节。该程序试图定义各种数据结构,但希望对允许分配给某些属性的值强制执行约束条件。 我正在使用Pycharm IDE在Python 2.7中执行该程序。
# Base class. Uses a descriptor to set a value
class Descriptor(object):
def __init__(self, name=None, **opts):
self.name = name
for key, value in opts.items():
setattr(self, key, value)
def __set__(self, instance, value):
instance.__dict__[self.name] = value
# Descriptor for enforcing types
class Typed(Descriptor):
expected_type = type(None)
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError('expected ' + str(self.expected_type))
super(Typed,self).__set__(instance, value)
class Integer(Typed):
expected_type = int
class String(Typed):
expected_type = str
class MaxSized(Descriptor):
def __init__(self, name=None, **opts):
if 'size' not in opts:
raise TypeError('missing size option')
super(MaxSized,self).__init__(name, **opts)
def __set__(self, instance, value):
if len(value) >= self.size:
raise ValueError('size must be < ' + str(self.size))
super(MaxSized,self).__set__(instance, value)
class SizedString(String, MaxSized):
pass
# Class decorator to apply constraints
def check_attributes(**kwargs):
def decorate(cls):
for key, value in kwargs.items():
if isinstance(value, Descriptor):
value.name = key
setattr(cls, key, value)
else:
setattr(cls, key, value(key))
return cls
return decorate
# Example
@check_attributes(name=String,shares=Integer,place=SizedString('tester',size=8))
class Stock(object):
def __init__(self, stkname, stkqty,stkhq):
self.name = stkname
self.shares = stkqty
self.place = stkhq
执行以下初始化代码时,
s = Stock('ACME', 50,'hky')
print s.name # print ACME
print s.shares # prints 50
print s.place # prints hky
条件:
当调试下面的代码 @check_attributes place=SizedString('tester',size=8) 时,下面的if条件为True,而对于name=String and shares=Integer,则else条件为True。
if isinstance(value, Descriptor):
value.name = key
setattr(cls, key, value)
else:
setattr(cls, key, value(key))
问题:
如果SizedString是Descriptor的一个实例(基于继承层次结构-String,Typed,MaxSized,Descriptor),那么String和Integer也应该满足If条件,对吗?因为最终它们也是(typed, Descriptor)的子类?
- 在setattr(cls,key,value(key))中,value(key)是什么意思,无法理解value(key)的含义?
抱歉内容有点长,但希望尽可能清晰明了。
SizedString('tester', size=8)
中传递虚拟的'tester'
值,而不是直接使用SizedString(size=8)
?或者,如果您出于某种原因想要强制使用仅将被@check_attributes
覆盖的临时名称,为什么允许name=None
? - abarnertissubclass
。 - Dan D.