0

我正在尝试拥有一个类的默认实例。我希望有

class Foo():
    def __init__(self):
        ....

    _default = Foo()

    @staticmethod
    def get_default():
        return _default

然而_default = Foo()导致NameError: name 'Foo' is not defined

4

3 回答 3

5

Foo在类定义完成之前不存在。不过,您可以在类定义之后轻松引用它:

class Foo(object):
    def __init__(self):
    # ....

Foo.default_instance = Foo()

另请注意,我已经删除了多余的 getter 方法以支持普通的旧属性。

您还可以使用装饰器解决问题:

def defaultinstance(Class):
    Class.default_instance = Class()
    return Class

@defaultinstance
class Foo(object):
    # ...

或者,无偿地,使用元类:

def defaultmeta(name, bases, attrs):
    Class = type(name, bases, attrs)
    Class.default_instance = Class()
    return Class

# Python 2.x usage
class Foo(object):
    __metaclass__ = defaultmeta
    # ...

# Python 3.x usage
class Foo(metaclass=defaultmeta):
    # ...

您何时可能想要使用每种方法?

  • 一次性使用定义后的类属性分配
  • 如果您希望在许多不相关的类中具有相同的行为并“隐藏”它的实现,请使用装饰器(虽然在这里它并没有真正隐藏,甚至没有那么复杂)
  • 如果您希望行为是可继承的,请使用元类,在这种情况下它并不是真正无偿的。:-)
于 2013-11-04T22:52:06.490 回答
2

您不能引用尚不存在的类。在类定义主体中,尚未创建Foo类。

创建类后添加属性:

class Foo():
    def __init__(self):
        ....

    @staticmethod
    def get_default():
        return Foo._default


Foo._default = Foo()

请注意,您还需要更改get_default()静态方法;类主体不形成范围,因此您不能_default作为非本地 from 到达get_default()

然而,你现在经常重复自己。通过创建get_default()一个类方法来减少重复:

class Foo():
    def __init__(self):
        ....

    @classmethod
    def get_default(cls):
        return cls._default


Foo._default = Foo()

或在第一次调用时创建默认值:

class Foo():
    def __init__(self):
        ....

    @classmethod
    def get_default(cls):
        if not hasattr(cls, '_default'):
            cls._default = cls()
        return cls._default
于 2013-11-04T22:52:25.857 回答
0

你可以懒惰地初始化你的默认实例。

class Foo(object):

    _default = None

    @staticmethod
    def get_default():
        if not Foo._default:
            Foo._default = Foo()
        return Foo._default
于 2013-11-04T23:00:21.160 回答