[英]Python descriptor returning itself not value when called from class
I want to make an attribute accessible from instance and class that cannot be reassigned. 我想从实例和类中访问无法重新分配的属性。 I have the "prevent from reassigned" part tackled thanks to a metaclass.
由于元类,我有“防止重新分配”的部分。 However, now the attribute cannot be read from the class.
但是,现在无法从类中读取该属性。 How to make it so.
如何做到这一点。
Having this: 有这个:
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)
When calling 打电话的时候
print Fixed.frozen
print Fixed().frozen
Gives 给
<property object at 0x106dbeba8>
I AM AWESOME
Why doesn't it give the same? 为什么不给它一样? How to make it give the same?
如何让它给出相同的?
A property
normally only works on an instance. property
通常仅适用于实例。 To make a property work on a class too, you'll need to create your own descriptor instead: 要使属性也适用于类,您需要创建自己的描述符:
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__)
The only difference between the above and a regular property
is in the __get__
method; 上面和常规
property
之间的唯一区别在于__get__
方法; a normal property
object does (in C) the equivalent of: 普通的
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)
eg on a class the descriptor returns self
, while my version sets obj
to objtype
in that case. 例如,在类上,描述符返回
self
,而我的版本在这种情况下将obj
设置为objtype
。
Also note that a descriptor __set__
method is only called when working with an instance; 另请注意, 只有在处理实例时才会调用描述符
__set__
方法; Fixed.frozen = 'something'
would not invoke the descriptor __set__
, only Fixed().frozen = 'something'
would. Fixed.frozen = 'something'
不会调用描述符__set__
,只有Fixed().frozen = 'something'
会。 Your metaclass __setattr__
intercepts the attribute assignment on the class instead. 您的元类
__setattr__
截取类的属性赋值。
You could also put a descriptor object on the metaclass , which would then be given the opportunity to have it's __set__
called for attribute assignment on the class itself. 您还可以在元类上放置一个描述符对象,然后可以在类本身上调用它的
__set__
来进行属性赋值。
By convention a Python descriptor returns itself when not called with an instance. 按照惯例,Python描述符在未使用实例调用时返回自身。 Properties are just a shortcut for a descriptor, to do this you need to implement your own descriptor.
属性只是描述符的快捷方式,为此,您需要实现自己的描述符。 The following should do what you want, without needing a metaclass:
以下应该做你想要的,而不需要元类:
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")
You would also probably want to override the delete method which is part of the descriptor interface. 您可能还想覆盖作为描述符接口一部分的delete方法。 There are some good articles explaining exactly how descriptors work.
有一些很好的文章解释了描述符的确切作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.