首页 > 解决方案 > 如何在从基类生成的类上创建@property?

问题描述

我想在一个类上动态生成属性,我希望在“基”类上生成它们。为了说明这个问题,我在这里使用伪代码来说明我如何不知道方法的名称。

class Base:
    def __init__(self):
        for n in range(1,3):
            setattr(self, f"func{n}", property(lambda self_=self: {f"func{n}": self_}))


class A(Base):
    pass

然后我运行:

>>> a = A()
>>> a.func1
<property object at 0x7f67c1342598>

但是,我期望得到以下结果:

>>> a = A()
>>> a.func1
{'func1': <A object at 0x7f9ccec77198>}

在我看来,property()通话没有按预期工作。我究竟做错了什么?

标签: python

解决方案


我不确定您为什么不将其用作装饰器,这是一个我们不直接调用属性的示例:

class Base:
    @property
    def func(self):
        return {"self": self}

class A(Base):
    pass

print(A().func)

{'self': <__main__.A object at 0x0000018CC01DDC10>}

回复已编辑的问题

当然这是可能的,但我们必须将属性绑定到类,而不是实例。我们也不能self_按照我们实际想要的每个实例的self.

class Base:
    def __init__(self):
        for n in range(1, 3):
            setattr(self.__class__, f"func{n}", property(lambda self_, n_=n: {f"func{n_}": self_}))

class A(Base):
    pass

print(A().func1)
print(A().func2)

{'func1': <__main__.A object at 0x00000139C12B5FD0>}
{'func2': <__main__.A object at 0x00000139C12B5FD0>}

一些断言来确保参数是正确的:

a1 = A()
a2 = A()

assert a1.func1["func1"] is a1
assert a1.func2["func2"] is a1

assert a2.func1["func1"] is a2
assert a2.func2["func2"] is a2

我们在每个实例中存储唯一对象的另一个示例

我担心前面的答案,因为它只是覆盖类方法。在这个例子中,我们仍然在创建每个实例时覆盖类方法,但我们还在每个实例中为每个 func 存储一个唯一的对象,我相信这更接近您正在寻找的内容。存储在类中的简单计数器用于可视化它。

class Base:
    count = 0

    def __init__(self):
        for n in range(1, 3):
            func_name = f"func{n}"
            var_name = f"_{func_name}_var"
            setattr(self, var_name, {func_name: self, "count": Base.count})
            setattr(self.__class__, func_name, property(lambda self_, name=var_name: getattr(self_, name)))

            Base.count += 1

class A(Base):
    pass

a1 = A()
a2 = A()

print(a1.func1)
print(a1.func2)
print(a2.func1)
print(a2.func2)

{'func1': <__main__.A object at 0x0000019298925FD0>, 'count': 0}
{'func2': <__main__.A object at 0x0000019298925FD0>, 'count': 1}
{'func1': <__main__.A object at 0x0000019298925F70>, 'count': 2}
{'func2': <__main__.A object at 0x0000019298925F70>, 'count': 3}

推荐阅读