2013-11-04 5 views
0

클래스의 기본 인스턴스를 가지려고합니다. 나는 그러나 _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)와 비슷합니다. 실제로이 문제를 해결할 더 좋은 방법이있을 때, 파이썬에서 자바 스타일의 코드를 작성하려고 시도하는 많은 사람들은 이것을하고 싶어하지만, 어떻게 알지 못합니다. 그래서, _why_ "staticmethod"를 가지고 "default instance"를 얻고 싶습니까? 왜 안 되죠?, 그냥 글로벌'default_foo' 객체가 있습니까? (그렇습니다, 전역은 좋지 않습니다. 그러나 싱글 톤은 전역 적으로 문제를 해결하는 방법으로 글로벌 성을 숨기고 상황은 더욱 복잡하게 만듭니다.) – abarnert

+0

그런 이유로 전역 기본 인스턴스가 클래스에 의해 소유되기를 원한다고해도 왜 getter 메소드를 원합니까? 그것은 거의 항상 비 - 파이썬 디자인의 신호입니다. – abarnert

답변

5

Foo로 연결

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

    _default = Foo() 

    @staticmethod 
    def get_default(): 
     return _default 

을 갖고 싶어. 당신은 쉽게하지만, 후 에 클래스 정의를 참조 할 수 있습니다 또한

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

때 각 방법을 사용하는 것이 좋습니다 수 있는가?

  • 사용 일회성
  • 에 대한 사후 정의 클래스 속성 할당
  • 를 사용하여 장식 동일한 관련이없는 많은 클래스의 행동을 "숨기기"그것의 구현을 (정말 숨겨진 아니에요하려는 경우 , 심지어는 복잡한 것까지도)
  • 동작을 상속 가능한으로 바꾸려면 메타 크라스를 사용하십시오.이 경우 실제로는 아무렇지도 않습니다. :-)
+0

중간에있는'_default = Foo()'줄을 삭제하고 싶다고 생각합니다. – jwodder

+1

'Foo.get_default()'를 호출하면'_default'에 대해'NameError'가 발생합니다. –

+0

그래, 어리석게도 OP의 원래 코드를 자르고 붙여 넣었다. – kindall

2

아직 존재하지 않는 클래스는 참조 할 수 없습니다. 클래스 정의 본문에서 Foo 클래스는 아직 생성되지 않았습니다 입니다.

하여 클래스를 생성 한 후 속성을 추가 : 당신은 또한 get_default() 정적 방법을 변경해야

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

    @staticmethod 
    def get_default(): 
     return Foo._default 


Foo._default = Foo() 

참고; 클래스 본문은 범위를 구성하지 않으므로 get_default()에서 _default에 로컬로 연결할 수 없습니다.

그러나 지금은 많은 것을 반복하고 있습니다.

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

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


Foo._default = Foo() 

또는 최초의 호출시에 기본을 만들 : 대신 classmethod를 get_default()하여 반복을 약간 감소

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

관련 문제