2013-11-04 36 views
0

我试图创建一个类的默认实例。我想有在类定义中创建类的实例

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

    _default = Foo() 

    @staticmethod 
    def get_default(): 
     return _default 

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

+0

请注意'__init'不是一种特殊的方法;它是'__init__'。 – abarnert

+2

同时,这听起来像[XY问题](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。许多想要这样做,但不知道如何的人,正试图用Python编写Java风格的代码,但实际上有更好的方法来解决他们真正的问题。所以,_why_你想要一个“默认实例”,你可以用这样的'staticmethod'来获得吗?为什么不,例如,只需要一个全局的'default_foo'对象? (是的,全局变量是不好的 - 但是单例变量是全局变量,它们只是隐藏了它们的全局性,而不是解决所有问题,但使事情变得更加复杂)。 – abarnert

+0

对于这个问题,即使你希望全局默认实例被类所拥有,为什么你需要一个getter方法呢?这几乎总是非pythonic设计的标志。 – abarnert

回答

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): 
    # ... 

当你可能会想使用哪种方法?

  • 使用一次性的
  • 的定义后class属性分配
  • 使用Decorator如果你想在很多不相关类的相同行为和“隐藏”的执行它(这不是真的隐藏,或者甚至是复杂的,尽管如此)
  • 如果你想要的行为是可继承使用元类,在这种情况下,它并不是真正的无偿。 :-)
+0

我想你想删除中间那里的_default = Foo()行。 – jwodder

+1

调用'Foo.get_default()'会为'_default'引发一个'NameError'。 –

+0

是的,我愚蠢地将OP的原始代码粘贴在那里。 – kindall

2

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

添加类已经被创建之后的属性:

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

    @staticmethod 
    def get_default(): 
     return Foo._default 


Foo._default = Foo() 

请注意,您还需要改变get_default()静态方法;班级主体不构成范围,因此您不能从get_default()_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 
0

您可以懒洋洋地初始化默认实例。

class Foo(object): 

    _default = None 

    @staticmethod 
    def get_default(): 
     if not Foo._default: 
      Foo._default = Foo() 
     return Foo._default 
+0

试图避免延迟初始化,因为它不是线程安全的 – mingxiao