2013-11-04 35 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