2013-03-03 1 views
19

이 클래스에서 가져온 기본 값 인수가있는 클래스 내에 메서드를 작성하고 싶습니다. 일반적으로 일부 데이터를 필터링합니다. 내 수업 시간에는 일반적으로 데이터 벡터를 전달하는 메서드가 있습니다. 때로는 벡터가 없으며 시뮬레이트 된 데이터를 가져옵니다. 특정 벡터를 전달하지 않을 때마다 기본적으로 시뮬레이션 된 데이터를 가져오고 싶습니다. 내 방법 정의 내에서 내가 어디 a=self.vector 말 쉬운 건설되어야한다고 생각. 하지만 어떤 이유로 나는 NameError: name 'self' is not defined 오류가 있습니다. 단순화 된 구조입니다 : 내가 기대클래스 변수에 클래스 변수를 기본값으로 할당

class baseClass(object): # This class takes an initial data or simulation 
    def __init__(self): 
     self.x = 1 
     self.y = 2 

class extendedClass(baseClass): # This class does some filtering 
    def __init__(self): 
     baseClass.__init__(self) 
     self.z = 5 
    def doSomething(self, a=self.z): 
     self.z = 3 
     self.b = a 

if __name__ == '__main__': 
    a = extendedClass() 
    print a.__dict__ 
    a.doSomething() 
    print a.__dict__ 

출력은 다음과 같아야합니다

{'y': 2, 'x': 1, 'z': 5} 
{'y': 2, 'x': 1, 'z': 3, 'b': 5} 

내가 분명히 지금까지 작동하지 않습니다 def doSomething(self, a=z):로 기본 할당을 시도했다. 내가 이해하는 한, self.z은이 범위에서 볼 수 있으며 기본값으로 사용하는 것이 좋습니다. 왜 내가이 오류가 있고 그것을 어떻게하는지 모르겠다. 이것은 아마도 쉬운 질문이지만, 나는 그것을 알아 내거나 때때로 언젠가는 부족한 해결책을 찾으려고 노력합니다. 다른 언어에 대해서만 similar 질문을 찾았습니다.

답변

25

이해가 잘못되었습니다. self은 그 자체로 그 함수 정의에 대한 매개 변수이므로, 그 시점에서 범위 내에있을 수는 없습니다. 그것은 함수 내에서만 범위 내에 있습니다.

대답은 None에 인수를 기본적으로 다음 방법 안에이 있는지 확인하는 것입니다 : 정의가 실행될 때

def doSomething(self, a=None): 
    if a is None: 
     a = self.z 
    self.z = 3 
    self.b = a 
+0

, 당신은 단지'작성해야하는 경우 A : = self.z' 또는 'A = A 또는 self.z'. – danijar

+0

나는 당신이 'a not : a = self.z'를 의미한다고 생각한다. – BBischof

+0

이것은 표준 pythonic 패턴인가? 선택적인 메소드 속성의 폴백 (fall-back)으로 사용되는 기본값을 가진 클래스 속성을 갖는가? 아니면'z = None' 속성을 포함하도록'extendedClass' __init__ 생성자를 변경하는 것이 더 낫습니다. 그리고'None'을 메소드 내부의 어떤 디폴트로 설정하고 메소드 매개 변수로 가지지 않는다면? 하드 코딩 된 클래스 속성을 가지는 것은 실제로 상수 일 때 유용하다고 생각할 수 있습니다. 둘 이상의 메소드에서 필요합니다. 그렇지 않으면 메소드의 범위에 'z'를 제한하지 않는 것이 좋습니다. 클래스 나 객체가 없을 수도 있습니다. 속성? – Davos

6

다음은 간단한 예제 모듈에 대한 코드의 디스 어셈블리입니다. 코드 객체는 바이트 코드, 사용되는 상수 및 이름에 대한 읽기 전용 컨테이너이며 로컬 변수의 수, 필수 스택 크기 등에 대한 메타 데이터입니다. 모든 코드 객체는 상수로 컴파일됩니다. 이들은 컴파일 시간에 생성됩니다. 그러나 객체 class Afunction test은 실행시에 인스턴스화됩니다 (예 : 모듈을 가져올 때).

BUILD_CLASS 이름 'A', 기지 tuple (object,)하고, 클래스 네임 스페이스의 속성을 포함하는 dict 소요 클래스를 확인하십시오. 이는 type(name, bases, dict)을 호출하여 수동으로 유형을 인스턴스화하는 것과 같습니다. dict을 만들려면 코드 객체 A에서 함수가 만들어지고 호출됩니다. 마지막으로 클래스 객체는 STORE_NAME을 통해 모듈 네임 스페이스에 저장됩니다.

코드 개체 A에서 의 인수로 self.z이 스택에로드됩니다. 바이트 코드가 LOAD_NAME 인 경우 현재 지역 (즉, 클래스 네임 스페이스가 정의 됨), 모듈 전역 및 기본 제공 항목에서 self을 검색합니다. self이 global 또는 builtins 범위에 정의되어 있지 않으면 분명히 실패합니다. 그것은 분명히 지역 범위에서 정의되지 않습니다.

그러나 성공한 경우 (self.z,)이라는 특성을 사용하여 __defaults__ 특성으로 만든 다음 로컬 이름 test에 저장합니다.

>>> code = compile(''' 
... class A(object): 
... def test(self, a=self.z): pass 
... ''', '<input>', 'exec') 

>>> dis.dis(code) 
    2   0 LOAD_CONST    0 ('A') 
       3 LOAD_NAME    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    1 (<code object A ...>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_NAME    1 (A) 
      22 LOAD_CONST    2 (None) 
      25 RETURN_VALUE 

>>> dis.dis(code.co_consts[1]) # code object A 
    2   0 LOAD_NAME    0 (__name__) 
       3 STORE_NAME    1 (__module__) 

    3   6 LOAD_NAME    2 (self) 
       9 LOAD_ATTR    3 (z) 
      12 LOAD_CONST    0 (<code object test ...>) 
      15 MAKE_FUNCTION   1 
      18 STORE_NAME    4 (test) 
      21 LOAD_LOCALS   
      22 RETURN_VALUE  

@uselpa : 귀하의 페이스트 빈 예 (2.X 용으로 다시 작성) : 당신이 볼 수 있듯이

>>> code = compile(''' 
... default = 1 
... class Cl(object): 
...  def __init__(self, a=default): 
...   print a 
... Cl() 
... default = 2 
... Cl() 
... ''', '<input>', 'exec') 
>>> dis.dis(code) 
    2   0 LOAD_CONST    0 (1) 
       3 STORE_NAME    0 (default) 

    3   6 LOAD_CONST    1 ('Cl') 
       9 LOAD_NAME    1 (object) 
      12 BUILD_TUPLE    1 
      15 LOAD_CONST    2 (<code object Cl ...>) 
      18 MAKE_FUNCTION   0 
      21 CALL_FUNCTION   0 
      24 BUILD_CLASS   
      25 STORE_NAME    2 (Cl) 

    6   28 LOAD_NAME    2 (Cl) 
      31 CALL_FUNCTION   0 
      34 POP_TOP    

    7   35 LOAD_CONST    3 (2) 
      38 STORE_NAME    0 (default) 

    8   41 LOAD_NAME    2 (Cl) 
      44 CALL_FUNCTION   0 
      47 POP_TOP    
      48 LOAD_CONST    4 (None) 
      51 RETURN_VALUE   

는, 클래스 객체 Cl (그리고 함수 객체 __init__가)에만 인스턴스화 로컬 이름 'Cl'에 한 번 저장됩니다. 런타임에 모듈이 순차적으로 실행되므로 default이라는 이름을 다시 바인딩하면 기본값 인 __init__에 아무런 영향을 미치지 않습니다. 새로운 __defaults__ 튜플로 함수를 작성하는이 __init__.__code__에서 이미 컴파일 된 코드 개체를 재사용

>>> default = 1 
>>> class Cl(object): 
...  def __init__(self, a=default): 
...   print a 
... 

>>> from types import FunctionType 
>>> default = 2 
>>> Cl.__init__ = FunctionType(
... Cl.__init__.__code__, globals(), '__init__', (default,), None) 
>>> c = Cl() 
2 

: 당신은 동적 이전에 컴파일 된 코드와 새로운 기본값을 사용하여 새 기능을 인스턴스화 할 수

인수가 falsy 값을 취할 수없는 경우
>>> Cl.__init__.__defaults__ 
(2,) 
+1

나는 막혔다. 인스턴스 생성시에 클래스와 메소드가 생성된다면 http://pastebin.com/UJfMpnqW에 나와있는 예제와 분명히 다른 이유는 무엇입니까? – uselpa

+0

@uselpa : "컴파일 시간"과 "실행 시간"의 차이를 명확하게 설명하기 위해 예제를 추가했습니다. 모듈은 구문 오류없이 정상적으로 컴파일 될 수 있지만 가져 오기 (실행)시 런타임 오류가 발생합니다. – eryksun

+0

나는 그것을 얻고 있다고 생각한다. 양해 해 주셔서 대단히 감사합니다! – uselpa

관련 문제