简体   繁体   中英

Instances of class A as class attributes of A in Python?

Are there Python versions that allow defining your class like this:

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

and then adding class attributes , such as BAR_1, BAR_2 , etc.:

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

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

which are actually "special cases of Foo ", such as:

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

so that, in my code, I can either make my own Foos or get common, predefined Foos by working directly with Foo.BAR_1 and Foo.BAR_2 ?

The code above obviously does not work, otherwise I would not post the question ( Foo is an unresolved reference when defining BAR_1 and BAR_2 ). I found a trick on SO how to sort-of achieve this -> defining a custom ClassProperty class:

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

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

which then allows me to define Foo as

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

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

    ...

and that works, but the issue is that Foo.__init__ is called everytime whenever Foo.BAR_1 or Foo.BAR_2 is retrieved, which can be useful in certain situations (precisely those where you always want separate instances), but in the special case where Foo is simply a messenger class which is coincidentally hard to load (like a result of a computation for example), this solution is unfeasible. I'd like for the constructor of Foo to be called exactly once for BAR_1 , exactly once for BAR_2 (ideally lazily, during the first retrieval, that would be fantastic), and after that it would only return the created instances. So, is there a way to do this?

I use Python 3.8.6 .

During the time I composed the question body, I figured out I can just define Foo like this:

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

Now, I can call Foo.BAR_X for retrieval of a defined Foo.__BAR_X which is actually an instance of Foo , which is always created only once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM