gpt4 book ai didi

python - 我可以在 __new__ 或 __init__ 期间创建类属性吗?

转载 作者:太空狗 更新时间:2023-10-30 01:04:00 25 4
gpt4 key购买 nike

我想做这样的事情,但到目前为止我还没有取得太大的成功。我想让每个 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"

**更新**

这也行不通:

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

** 更新 2 **

使用了 __metaclass__ 解决方案,但将其固定在 Base.__new__ 中。看起来它需要一个更好定义的闭包——“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

最佳答案

描述符(例如 property 类型的实例)只有在class 对象而不是instance 中时才有意义目的。因此,您需要更改类,而不是实例,并且(在 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']

如果您坚持使用 Python 2.5 或更早版本,装饰器语法不适用于类,但很容易获得相同的效果,只是使用不太漂亮的语法——将最后 3 行更改为:

class Child(Base):
_myattrs = ['foo', 'bar']
Child = lazyclass(Child)

它与类装饰器语法具有相同的语义。

关于python - 我可以在 __new__ 或 __init__ 期间创建类属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2496930/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com