如何在Python中定义一个指向同一类对象的类变量

3

以下是Java代码。我需要知道Python中等价的代码:

class A {
    public static A obj = new A();
}

相关:http://stackoverflow.com/questions/16935346/can-a-class-variable-be-an-instance-of-the-class - Ashwini Chaudhary
@PravatPanda -- 可能是因为 OP 正试图在 Python 中复制那个 Java 结构。大概,最了解这个问题的人也知道 Java... - mgilson
@mgilson 抱歉,我一开始没有理解问题。 - Pravat Panda
4个回答

6

在Python类定义中,你不能这样做,因为直到class:块结束前,该类才被定义。你必须在之后设置它:

class A(object): 
    pass    
A.obj = A()

9
请注意,通常情况下在 Python 中不会这样做。使用 Java 的原因是你导入类而非文件,所以将一个类的“默认”实例作为该类的静态成员变量保留在该类本身是有意义的。在 Python 中,你导入模块,实例可以存在于类之外,因此将一个类的默认实例作为模块级变量保留在定义该类的模块中是有意义的。 - Daniel Roseman

4
你可以使用元类完成这个任务:
class SelfReferencingObjectMetaclass(type):

    def __new__(cls, name, bases, attrs):

        attrs['obj'] = property(lambda self: self.__class__.obj)
        return super(SelfReferencingObjectMetaclass, cls).__new__(cls, name, bases, attrs)

    @property
    def obj(cls):

        try:
            return cls._obj
        except AttributeError:
            cls._obj = cls()
            return cls._obj

class A(object):

    __metaclass__ = SelfReferencingObjectMetaclass

正如 @Daniel Roseman 在评论中指出的那样,解决你所面临的问题可能有一种更加简单、更具Pythonic的方法。 在考虑了这个评论之后,如果不是在对象结构上完全相同,你可以通过拥有类似于以下模块的方式来实现相同的功能:

a.py

class A(object):

    @property
    def obj(self):

        return a_inst


a_inst = A()

这确实在使用它的代码中创建了有点丑陋的结构from a import A,但这是一种更简单的实现方式。


2
我其实也考虑过发布这个问题——主要是因为我刚开始学习元类,然后就想:“嘿,我可以用元类来解决这个问题!” - mgilson
元类是某些事情的绝佳工具。但是过度使用它们有点诱人危险。在这种情况下,我比起 cls.obj = cls() 或者我答案中的 property 东西更喜欢它们,因为我真的讨厌 from a import A 结构的冗余。虽然更常见的情况是,通过调整实现并将类推到层次结构的上一级或两级,您可以避免这两个问题。 - Silas Ray
我认为@DanielRoseman的意思是你的第二段代码应该是在模块a中定义class A(object): pass,并且obj应该是a.obj,否则我看不出与我的代码相比有任何优势。 - jamylak
实际上并没有一个,只是有一种替代方案,在非玩具示例中可能更有用。此外,它可以被认为更加“安全”和静态,这在这种情况下可以被视为优点,因为a_inst可以被视为类的实现细节,而A.obj是不可分配的。当然,它的缺点是无法从类中访问,但您可以使用描述符或元类来解决这个问题。 - Silas Ray

1

在创建类的任何实例之前,您需要这个类成员吗?如果不需要,您可以尝试在创建第一个实例时进行赋值:

class A (object):
    obj = None

    def __init__(self):
        if A.obj is None:
            a.obj = A()
            # or:
            a.obj = self

或者在__new__中更早地完成它。 - Silas Ray

0

我认为你想这样做是因为你正在尝试实现单例模式或类似的模式。

你可以从 activestate 阅读以下配方:http://code.activestate.com/recipes/52558/

它解释了它的工作原理,并展示了一些代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接