파이썬에서 클래스 메소드 내에서 "정적"클래스 변수에 어떻게 액세스 할 수 있습니까?


162

다음과 같은 파이썬 코드가있는 경우 :

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)

f = Foo()
f.bah()

불평

NameError: global name 'bar' is not defined

bar메소드 내에서 클래스 / 정적 변수에 어떻게 액세스 할 수 bah있습니까?


Python 및 정적에 대한 자세한 내용은 여기를 참조하십시오. stackoverflow.com/questions/68645/python-static-variable
bedwyr

답변:


166

또는 대신 bar사용하십시오 . 에 할당 하면 정적 변수가 생성되고에 할당 하면 인스턴스 변수가 생성됩니다.self.barFoo.barFoo.barself.bar


12
Foo.bar는 작동하지만 self.bar는 정적 변수가 아닌 인스턴스 변수를 만듭니다.
bedwyr

47
bedwyr, "print self.bar"는 인스턴스 변수를 생성하지 않습니다 (self.bar에 할당하더라도).
Constantin

@Constantin-나는 그것이 흥미로운 차이점이라는 것을 몰랐다. 수정 주셔서 감사합니다 :-)
bedwyr

2
그러나 ivar을 원하지 않는다면 Foo.classmember를 사용하는 것이 더 명확합니다.
mk12

2
: 정적 변수를 사용하는 경우, 여기에서 개는을 읽을 수있는 좋은 생각 stackoverflow.com/questions/68645/...을 . @Constantin은 많은 문제 중 하나를 제공합니다.
Trevor Boyd Smith

84

클래스 메소드를 정의하십시오.

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar

이제 bah()인스턴스 메소드 여야하는 경우 (즉, 자체에 액세스 할 수있는 경우) 클래스 변수에 직접 액세스 할 수 있습니다.

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar

3
self.__class__.bar 대신 Foo.bar만이 아닌 이유는 무엇입니까?
mk12

15
@ MK12 : 클래스 상속을 받으면 "클래스 변수"가 기본 클래스 또는 하위 클래스에있을 수 있습니다. 어느 것을 참조 하시겠습니까? 당신이하려는 일에 달려 있습니다. Foo.bar는 항상 지정된 클래스의 속성 (기본 클래스 또는 하위 클래스 일 수 있음)을 참조합니다. self.__class__.bar는 인스턴스가 어떤 클래스인지를 가리 킵니다.
Craig McQueen

7
이제 우리는 잘 정돈 된 두 가지 사용 사례를 구별 할 수있는 언어의 세부 사항을 알게되면서 불행한 시점에 도달했습니다. 그것은 실제로 당신이하고 싶은 일에 달려 있지만 많은 사람들이 그러한 미묘함에 참석하지 않을 것입니다.
holdenweb

2
BTW, 이것은 "클래스 변수"의 RARE 사용법입니다. 특정 클래스, Foo에서 정의하는 것이 훨씬 일반적입니다. 이것은 일부 고급 프로그래밍 상황에 유용한 정보입니다. 그러나 원래 질문이 답으로 원했던 것은 거의 확실하지 않습니다 (이 답변이 필요한 사람은 이미 Foo.bar를 수행하는 방법을 알고있을 것입니다). 내가 이것으로부터 무언가를 배웠기 때문에 +1.
ToolmakerSteve

3
클래스 변수와 메소드를 사용해야하는 시점에 대해 배우고 있습니다 (인스턴스 변수 및 메소드와 반대). 인스턴스 메소드에서 클래스 변수에 액세스하려면 self.__class__.bar를 사용해야합니까? bar가 인스턴스 변수가 아닌 클래스 변수이지만 self.bar가 작동한다는 것을 알았습니다.
Bill

13

모든 좋은 예와 마찬가지로 실제로 수행하려는 작업을 단순화했습니다. 이것은 좋지만 파이썬이 클래스 변수와 인스턴스 변수에 관해서 는 많은 유연성을 가지고 있음을 주목할 가치가 있습니다. 방법에 대해서도 마찬가지입니다. 좋은 가능성 목록을 보려면 Michael Fötsch의 새로운 스타일의 수업 소개 , 특히 2-6 절을 읽는 것이 좋습니다 .

시작할 때 기억해야 할 많은 작업 중 하나는 파이썬이 자바가 아니라는 것입니다. 진부한 것 이상. Java에서는 전체 클래스가 컴파일되어 네임 스페이스 확인이 간단 해집니다. 메소드 외부 (어디서나) 외부에 선언 된 모든 변수는 인스턴스 (또는 정적 인 경우) 변수이며 메소드 내에서 암시 적으로 액세스 할 수 있습니다.

파이썬에서 가장 중요한 규칙은 변수에 대해 순서대로 검색되는 세 개의 네임 스페이스가 있다는 것입니다.

  1. 기능 / 방법
  2. 현재 모듈
  3. 내장

{begin pedagogy}

이에 대한 제한된 예외가 있습니다. 나에게 발생하는 주요한 것은 클래스 정의가로드 될 때 클래스 정의가 자체 암시 적 네임 스페이스라는 것입니다. 그러나 이것은 모듈이로드되는 동안에 만 지속되며 메소드 내에서 완전히 우회됩니다. 그러므로:

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

그러나:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class B(object):
  File "<pyshell#11>", line 5, in B
    bar = get_foo()
  File "<pyshell#11>", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

결국, 기억해야 할 것은 액세스하려는 변수에 액세스 할 수는 있지만 암시 적으로는 불가능 하다는 것입니다. 목표가 간단하고 간단하다면 Foo.bar 또는 self.bar를 사용하는 것으로 충분합니다. 예제가 복잡해 지거나 상속 (정적 / 클래스 메서드를 상속 할 수 있음)과 같은 멋진 작업을 수행하거나 클래스 자체에서 클래스 이름을 참조하려는 아이디어가 잘못된 것 같습니다. 내가 소개 한 소개.


IIRC에는 기술적으로 검색된 함수 로컬, 모듈 / 글로벌 및 내장 3 개의 네임 스페이스가 있습니다. 중첩 된 범위는 여러 로컬 범위를 검색 할 수 있지만 예외적 인 경우 중 하나입니다. (...)
Jeff Shannon

이 기능의 포함하는 모듈로서 또한, 나는 이제, 검색이 아닌 것을, '주요 모듈을'말 조심 것 주요 모듈 ... 그리고 인스턴스 심판에서 속성을 찾고 다른 일이지만,이 대답은 설명하지 인스턴스 / 클래스 참조가 필요합니다.
Jeff Shannon


-2
class Foo(object):    
    bar = 1

    def bah(object_reference):
        object_reference.var = Foo.bar
        return object_reference.var


f = Foo() 
print 'var=', f.bah()

4
이 코드가 문제를 해결하는 방법과 이유에 대한 설명포함 하여 질문을 해결할 수는 있지만 게시물의 품질을 향상시키는 데 도움이되며 더 많은 투표를 할 수 있습니다. 지금 질문하는 사람 만이 아니라 앞으로 독자들에게 질문에 대답하고 있음을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을. 검토에서
이중 경고음
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.