我想从实例和类中访问无法重新分配的属性。由于元类,我有“防止重新分配”的部分。但是,现在无法从类中读取该属性。如何做到这一点。
有这个:
class Meta(type):
def __setattr__(cls, attr, val):
if attr =="frozen":
print "You can't unfreeze the frozen"
else:
cls.name = val
class Fixed(object):
__metaclass__ = Meta
frzn = 'I AM AWESOME'
def holdset(_,val):
_.frzn = _.frzn
print "frozen is frozen not setting to ", val
def get(_):
return _.frzn
frozen = property(fset=holdset,fget=get)
致电
print Fixed.frozen
print Fixed().frozen
给出
<property object at 0x106dbeba8>
I AM AWESOME
为什么不给它一样?如何让它给出相同的效果?
答案 0 :(得分:1)
property
通常只适用于某个实例。要使属性也适用于类,您需要创建自己的描述符:
class ClassAndInstanceProperty(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
if doc is None and fget is not None:
doc = fget.__doc__
self.__doc__ = doc
def __get__(self, obj, objtype=None):
if obj is None:
obj = objtype
if self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError("can't set attribute")
self.fset(obj, value)
def __delete__(self, obj):
if self.fdel is None:
raise AttributeError("can't delete attribute")
self.fdel(obj)
def getter(self, fget):
return type(self)(fget, self.fset, self.fdel, self.__doc__)
def setter(self, fset):
return type(self)(self.fget, fset, self.fdel, self.__doc__)
def deleter(self, fdel):
return type(self)(self.fget, self.fset, fdel, self.__doc__)
上述与常规property
之间的唯一区别在于__get__
方法;一个普通的property
对象(在C中)相当于:
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
e.g。在类上,描述符返回self
,而我的版本在这种情况下将obj
设置为objtype
。
另请注意,在处理实例时,描述符__set__
方法仅 。 Fixed.frozen = 'something'
不会调用描述符__set__
,只会调用Fixed().frozen = 'something'
。您的元类__setattr__
会截取类的属性赋值。
您还可以在元类上放置一个描述符对象,然后有机会让它__set__
在类本身上调用属性赋值。
答案 1 :(得分:1)
按照惯例,Python描述符在未使用实例调用时返回自身。属性只是描述符的快捷方式,为此,您需要实现自己的描述符。以下应该做你想要的,而不需要元类:
class Frozen(object):
def __init__(self, fixed_value):
self.fixed_value = fixed_value
def __get__(self, instance, owner=None):
return self.fixed_value
def __set__(self, instance, value):
print "You can't unfreeze the frozen"
class Fixed(object):
frzn = Frozen("I AM AWESOME")
您可能还想覆盖作为描述符界面一部分的 delete 方法。有一些很好的文章解释了描述符的确切运作方式。