[英]Can I create class properties during __new__ or __init__?
I want to do something like this, but I haven't had much success so far. 我想做这样的事情,但是到目前为止我还没有取得太大的成功。 I would like to make each attr a property that computes _lazy_eval only when accessed:
我想使每个attr属性只有在访问时才计算_lazy_eval:
class Base(object):
def __init__(self):
for attr in self._myattrs:
setattr(self, attr, property(lambda self: self._lazy_eval(attr)))
def _lazy_eval(self, attr):
#Do complex stuff here
return attr
class Child(Base):
_myattrs = ['foo', 'bar']
me = Child()
print me.foo
print me.bar
#desired output:
#"foo"
#"bar"
** UPDATE ** **更新**
This doesn't work either: 这也不起作用:
class Base(object):
def __new__(cls):
for attr in cls._myattrs:
setattr(cls, attr, property(lambda self: self._lazy_eval(attr)))
return object.__new__(cls)
#Actual output (it sets both .foo and .bar equal to "bar"??)
#bar
#bar
** UPDATE 2 ** **更新2 **
Used the __metaclass__
solution, but stuck it in Base.__new__
instead. 使用
__metaclass__
解决方案,但将其停留在Base.__new__
。 It looks like it needed a better defined closure -- "prop()" -- to form the property correctly: 似乎需要更好地定义闭包-“ prop()”-才能正确形成属性:
class Base(object):
def __new__(cls):
def prop(x):
return property(lambda self: self._lazy_eval(x))
for attr in cls._myattrs:
setattr(cls, attr, prop(attr))
return object.__new__(cls)
#Actual output! It works!
#foo
#bar
Descriptors (such as instances of the property
type) are only meaningful when they're held in the class object, not the instance object. 描述符(例如
property
类型的实例)仅在存放在类对象中时才有意义,而在实例对象中时才有意义。 So, you need to change the class, not the instance, and (in Python 2.6 or better) a class decorator is very handy for that purpose: 因此,您需要更改类,而不是实例,并且(在Python 2.6或更高版本中)类装饰器非常方便:
class Base(object):
def _lazy_eval(self, attr):
#Do complex stuff here
return attr
def lazyclass(cls):
for attr in cls._myattrs:
setattr(cls, attr, property(lambda self: self._lazy_eval(attr)))
return cls
@lazyclass
class Child(Base):
_myattrs = ['foo', 'bar']
If you're stuck with Python 2.5 or earlier, the decorator syntax doesn't apply to classes, but it's easy to get the same effect, just with less nifty syntax -- change the last 3 rows to: 如果您使用Python 2.5或更早版本,则装饰器语法不适用于类,但是很容易获得相同的效果,只需减少一些精巧的语法即可-将最后3行更改为:
class Child(Base):
_myattrs = ['foo', 'bar']
Child = lazyclass(Child)
which has the same semantics as the class decorator syntax. 与类装饰器语法具有相同的语义。
Technically you want a metaclass: 从技术上讲,您需要一个元类:
class LazyMeta(type):
def __init__(cls, name, bases, attr):
super(LazyMeta, cls).__init__(name, bases, attr)
def prop( x ):
return property(lambda self: self._lazy_eval(x))
for x in attr['lazyattrs']:
setattr(cls, x, prop(x))
class Base(object):
__metaclass__ = LazyMeta
lazyattrs = []
def _lazy_eval(self, attr):
#Do complex stuff here
return attr
class Child(Base):
lazyattrs = ['foo', 'bar']
me = Child()
print me.foo
print me.bar
您可以通过__ class __ dict访问类属性
self.__class__.attr
You could consider using __getattr__()
instead: 您可以考虑使用
__getattr__()
代替:
class Base(object): def __getattr__(self, attr): if attr not in self._myattrs: raise AttributeError return self._lazy_eval(attr) def _lazy_eval(self, attr): #Do complex stuff here return attr class Child(Base): _myattrs = ['foo', 'bar'] me = Child() print me.foo print me.bar
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.