首页 > 解决方案 > 类 A 的实例作为 Python 中 A 的类属性?

问题描述

是否有允许像这样定义您的类的 Python 版本:

class Foo:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

然后添加class attributes,如BAR_1, BAR_2等:

class Foo:
    BAR_1 = ...
    BAR_2 = ...

    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

这实际上是“特殊情况Foo”,例如:

class Foo:
    BAR_1 = Foo(4, 9, 16)
    BAR_2 = Foo(2, 3, 5)

    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

这样,在我的代码中,我可以自己制作Foos或变得通用,Foos通过直接使用Foo.BAR_1and进行预定义Foo.BAR_2

上面的代码显然不起作用,否则我不会发布问题(Foo定义BAR_1and时是未解决的参考BAR_2)。我发现了一个关于如何实现这一点的技巧 - >定义一个自定义ClassProperty类:

class ClassProperty(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, owner):
        return self.f(owner)

然后允许我定义Foo

class Foo:
    @ClassProperty
    def BAR_1(cls):
        return Foo(4, 9, 16)

    @ClassProperty
    def BAR_2(cls):
        return Foo(2, 3, 5)

    ...

这有效,但问题是Foo.__init__每次Foo.BAR_1Foo.BAR_2检索时都会调用它,这在某些情况下可能很有用(确切地说是那些你总是想要单独实例的情况),但在特殊情况下,Foo它只是一个信使类,巧合的是很难要加载(例如计算结果),此解决方案是不可行的。我希望为 的构造函数Foo只调用一次,只为BAR_1一次BAR_2(理想情况下,在第一次检索期间,这将是非常棒的),之后它只会返回创建的实例。那么,有没有办法做到这一点?

我用Python 3.8.6.

标签: pythonclassattributes

解决方案


在我撰写问题正文的过程中,我发现我可以Foo这样定义:

class Foo:
    @ClassProperty
    def BAR_1(cls):
        if not hasattr(cls, '_Foo__BAR_1'):
            cls.__BAR_1 = Foo(4, 9, 16)
        return cls.__BAR_1

    @ClassProperty
    def BAR_2(cls):
        if not hasattr(cls, '_Foo__BAR_2'):
            cls.__BAR_2 = Foo(2, 3, 5)
        return cls.__BAR_2

现在,我可以要求Foo.BAR_X检索一个定义Foo.__BAR_X的,它实际上是一个实例Foo,它总是只创建一次。


推荐阅读