2012-09-16 2 views
2

파이썬 초기화 작업 방법을 이해하려면 약간의 도움이 필요합니다. 필드/변수로 다른 클래스 (Foo) 클래스 (Bar) 있습니다. 이 변수를 Bar (__init__ 클래스가 아님)에서 직접 초기화하려고하면 Bar의 모든 인스턴스가 동일한 Foo를 가리 킵니다. 그러나 Bar2에서와 같이 __init__ 메서드가있는 경우 각 Bar2 인스턴스에는 고유 한 Foo 인스턴스가 있습니다. 여기서 무슨 일이 일어나고있는거야?__init__ 외부 필드 초기화

class Foo(): 
    number = 0 

class Bar(): 
    foo = Foo() 

class Bar2(): 
    foo = None 

    def __init__(self): 
     self.foo = Foo() 

first = Bar() 
second = Bar() 

print "Bar" 
print first 
print second 
print first.foo 
print second.foo 

first = Bar2() 
second = Bar2() 

print "\nBar2" 
print first 
print second 
print first.foo 
print second.foo 

예컨대 출력 의지 할 :

Bar 
<\__main__.Bar instance at 0x025B2AF8> 
<\__main__.Bar instance at 0x025B2B20> 
<\__main__.Foo instance at 0x004A3AA8> 
<\__main__.Foo instance at 0x004A3AA8> 

Bar2 
<\__main__.Bar2 instance at 0x025B2B48> 
<\__main__.Bar2 instance at 0x025B2AF8> 
<\__main__.Foo instance at 0x025B2B70> 
<\__main__.Foo instance at 0x025B2B98> 

같은 푸 인스턴스를 참조 할 바를 두 인스턴스 사용. 왜?

편집

:두 번 바을 first.foo인쇄에 오류가 수정되었습니다. 결과 동작은 여전히 ​​출력에서 ​​볼 수 있습니다.

+0

Python 2.x에서'class Foo() :'라고 쓰지 마십시오. 그러면 이전 스타일의 클래스가 생성됩니다. 당신은 거의 그것을 원하지 않을 것입니다. 대신, [새 스타일 클래스] (http://docs.python.org/reference/datamodel.html#newstyle)가 필요합니다. 이를 위해'class Foo (object) :'라고 쓰십시오. – pillmuncher

+0

그 점에 대해 나는 몰랐다. 실제로 파이썬과의 첫 만남 이전에 변경이 있었기 때문에 나는 알고 있었어야합니다. –

답변

2

파이썬은 동적 언어입니다. Java와 같은 정적 언어에서 컴파일러는 코드를 읽고, 클래스 정의를 찾고, 적절한 지 알아 내고 그에 따라 일부 코드를 생성합니다. 파이썬에서, 클래스 정의 (또는 함수 정의)는 변수에 대한 할당처럼 다른 것과 같은 명령문 일뿐입니다. 구문은 약간 다릅니다.

클래스를 정의 할 때 인터프리터는 클래스 정의를 실행합니다. 즉, 클래스 라인 뒤의 모든 코드를 실행합니다. 함수 정의를 찾으면 함수를 정의하고 함수 이름에 바인드합니다. 클래스 및 함수 정의는 다른 할당 문과 동일하므로 많은 곳에서 사용할 수 있습니다. 예를 들어 다음과 같이 :

def foo(): 
    class A: pass 
    a = A() 
    a.msg = "Hello" 
    return a 

파이썬은 오리 (가 오리처럼 꽥꽥 하나처럼 보이는 경우, 그것은 하나)의 함수 foo의 사용자도 클래스가 무엇인지 알 필요가 없습니다 입력되어 있기 때문에 그들은 단순히 foo가 멤버 msg를 가진 객체를 반환한다는 것을 알 필요가있다.이처럼 사용합니다 : 바의 정의가 실행될 때 예에 따라서

a = foo() 
print a.msg 

는, 클래스 문은 푸 객체의 생성을 포함하여 실행됩니다. Bar2의 정의가 실행되면 클래스 문은 이라는 함수 정의 사이에서 실행됩니다. 파이썬은 객체가 생성 될 때 호출 할 함수의 이름으로 이것을 사용합니다 (다른 함수를 호출 한 후 __new__, 그 점 이외에는).

다시 클래스 정의 (코드가 Foo 객체를 만드는 클래스 내부의 코드)는 클래스가 도입 될 때 한 번만 실행됩니다. __init__은 새로운 객체가 만들어 질 때마다 반복적으로 호출되므로 Bar2에서는 Foo의 생성이 계속 반복됩니다.

내가 말할 수있는 한 "foo = None"것은 불필요합니다. 실제로 필요하지 않습니다. 파이썬에서는 클래스 외부와 심지어 안으로 __init__의 어떤 곳에서도 인스턴스 변수를 추가 할 수 있습니다.

+0

__foo = None__이 필요하지 않은 것은 맞습니다. 내가 처음부터 그곳에 놓았 기 때문에 나는 그 예에서 그것을 남겨 둘 것이다. 나는 왜 내가이 행동을 보는지 왜 설명하는지 알지 못합니다. –

+0

설명을 추가했습니다. –

+0

지금 이해하기 쉽습니다. 고마워요. –

2

Bar.foo은 클래스 변수입니다. 클래스가 생성 될 때 한 번 초기화됩니다.

은 (코드 루게릭 병 두 번 first.foo를 인쇄한다는 점에 유의 당연 출력은 동일합니다.)

+0

예제에서 오류가 수정되었지만 여전히 동일한 동작입니다. –

+0

@ HåkonK.Olafsen : 그렇습니다. 클래스 변수이기 때문입니다. 클래스에 저장되며 개별 인스턴스에는 저장되지 않습니다. 오류에 대한 설명은 부수적 인 내용 이었으므로 그 내용을 괄호 안에 넣었습니다. –

+0

이해하기가 더 쉬웠습니다. 감사. –

0
first = Bar() 
second = Bar() 

print "Bar" 
print first 
print second 
print first.foo 
print first.foo 

을 여기에서 두 번 first.foo 인쇄, 같은 foo는 개체가 인쇄되어 그 이유는.

first = Bar2() 
second = Bar2() 

print "\nBar2" 
print first 
print second 
print first.foo 
print second.foo 

여기서 foo는 Bar2 클래스의 정적 변수이므로 두 개체가 동일한 foo 개체를 가리키며 두 번째 구문으로 구성됩니다. BAR2에서

class Bar2(): 
foo = None 

def __init__(self): 
    self.foo = Foo() 

class Bar(): 
def __init__(self): 
    self.foo = Foo() 

, BAR2의 모든 객체는 BAR2의 마지막 구성 개체의 건설에 건설 같은 객체를 가리키는 foo는 개체를해야합니다.

Bar에서는 다르게 명시되지 않는 한 모든 foo 객체가 Bar의 모든 객체에 대해 고유합니다.

+0

필자의 예제는 first.foo를 인쇄 할 때 약간의 실수를했지만 실제 코드는 그렇지 않았다. 그래서이 동작을 발견했다. 나는 당신이 당신의 대답에서 __Bar__와 __Bar2__을 바꿀 수 있다고 생각합니다. 업데이트 된 예제 (정확한 인쇄)를 실행하면 출력은 여전히 ​​동일합니다. Foo의 정적 버전을 만드는 __Bar__입니까? –

0

클래스도 개체이며 고유 한 변수 집합을 가지고 있습니다. 뿐만 아니라 파이썬이 객체에서 변수를 찾을 수 없을 때, 클래스 내에서 변수를 찾아서 사용할 수 있는지를 확인합니다. 클래스는 해당 클래스의 모든 객체간에 공유되므로 해당 클래스 내의 변수도 마찬가지입니다.