class 作为同一 class 的 class 成员的实例

Instance of class as class member of the same class

创建 class 成员(它是 class 的实例)的最 "pythonic" 方法是什么? IE。像这样:

class MyClass:

    # error! (and this is to be expected as MyClass is not yet fully defined)
    instance_as_member = MyClass()

    def __init__(self):
        print("MyClass instance created!")

可以通过在 class 定义后添加一个成员来解决这个问题:

class MyClass:
    ...
MyClass.instance_as_member = MyClass()

但这似乎有点不对;自然地,class 成员应该被定义为 in 即 class.

有更好的方法吗?

那不是 "A little wrong" - 这是做到这一点的简单明了的方法。 一行代码,人人可读,一目了然"what it is"。

还是不"feel"优雅。 所以,如果你不想仅仅为了外观而这样做,也许,如果有很多像这样的 classes,而不是重复代码,它可以用 class 装饰器来完成:

def instance_as_member(attr_name='instance_as_member', *init_args, **init_kwargs):
    def decorator(cls):
        instance = cls(*init_args, **init_kwargs)
        setattr(cls, attr_name, instance)
        return cls
    return decorator

@instance_as_member()
class MyClass:
    ...

装饰器对此没问题,因为它们在完全创建后将 cls 作为参数进行修改。使用 metaclasses,这会很棘手,因为 class 实例化的某些步骤,例如调用 __init_subclass__ 是在 任何显式 meta[=26 之后执行的=] 方法可以被覆盖,因此,尝试在 metaclass 初始化方法(__init____new__ 或 meta-meta-class' __call__)

您似乎需要 setUp 类型的功能。这是在 class 中执行此操作的 "slightly dirty" 方法:设置一个 class 变量标志来表示首次使用 class。检查实例化标志;如果这是第一次访问,则清除标志和运行设置方法。

class MyClass:

    first_touch = True

    def __init__(self, id=0):

        if MyClass.first_touch:
            MyClass.setUp(id)
        print("MyClass instance created!", id)

    @classmethod
    def setUp(self, id):
        MyClass.first_touch = False
        MyClass.instance_as_member = MyClass(-999)


print("Start")
local_obj = MyClass(1)
local_obj = MyClass(2)
local_obj = MyClass(3)

虽然 class 未在正文中定义,但 __init__

中定义的

但是在__init__里面实例化class有一个问题是递归的,所以需要跟踪instance_as_member是否已经实例化

类似以下的作品:

class Foo:
    member_added = False
    instance_as_member = None

    def __init__(self):
        if not Foo.member_added:
            Foo.member_added = True
            Foo.instance_as_member = Foo()

print(Foo.instance_as_member)
Foo()
print(Foo.instance_as_member)

这导致:

None
<__main__.Foo object at 0x7fcd9f68f3c8>

(至于这是否是个好主意是完全不同的问题!)