Python에서 클래스의 멤버 변수에 액세스합니까?


85
class Example(object):
    def the_example(self):
        itsProblem = "problem"

theExample = Example()
print(theExample.itsProblem)

클래스의 변수에 어떻게 액세스합니까? 이 정의를 추가해 보았습니다.

def return_itsProblem(self):
    return itsProblem

그러나 그것은 또한 실패합니다.


1
제목 편집, 질문 사실에 대한 클래스 "정적"변수 : stackoverflow.com/questions/707380/...
치로 틸리郝海东冠状病六四事件法轮功

답변:


144

대답은 몇 마디로

귀하의 예에서는 itsProblem지역 변수입니다.

self인스턴스 변수를 설정하고 가져 오는 데 사용해야 합니다. __init__방법 에서 설정할 수 있습니다 . 그러면 코드는 다음과 같습니다.

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

그러나 진정한 클래스 변수를 원한다면 클래스 이름을 직접 사용하십시오.

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)

하지만 theExample.itsProblem자동으로 다음과 같도록 설정 되므로주의 해야합니다.Example.itsProblem 변수 되지만 전혀 동일한 변수가 아니며 독립적으로 변경할 수 있으므로주의해야합니다.

몇 가지 설명

Python에서는 변수를 동적으로 만들 수 있습니다. 따라서 다음을 수행 할 수 있습니다.

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 

인쇄물

진실

따라서 이것이 바로 이전 예제에서 수행하는 작업입니다.

실제로 Python에서는 self로 사용 this하지만 그 이상입니다. self첫 번째 인수는 항상 개체 참조이기 때문에 모든 개체 메서드에 대한 첫 번째 인수입니다. 전화하든 말든 자동으로 진행됩니다 self.

즉, 다음을 수행 할 수 있습니다.

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

또는:

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

똑같습니다. ANY 객체 메서드의 첫 번째 인수는 현재 객체이며 self규칙으로 만 호출합니다 .그리고 외부에서하는 것과 같은 방식으로이 개체에 변수를 추가합니다.

이제 클래스 변수에 대해.

당신이 할 때 :

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

먼저 클래스 변수를 설정 한 다음 객체 (인스턴스) 변수에 액세스 합니다 . 이 개체 변수를 설정하지 않았지만 작동합니다. 어떻게 가능합니까?

글쎄, 파이썬은 먼저 객체 변수를 얻으려고 시도하지만 찾을 수 없으면 클래스 변수를 제공합니다. 경고 : 클래스 변수는 인스턴스간에 공유되고 개체 변수는 공유되지 않습니다.

결론적으로 클래스 변수를 사용하여 객체 변수에 기본값을 설정하지 마십시오. 사용하다__init__그것을 위해 .

결국, 여러분은 파이썬 클래스가 인스턴스이고 따라서 객체 자체라는 것을 알게 될 것이며, 이는 위를 이해하는 데 새로운 통찰력을 제공합니다. 이 사실을 알게되면 나중에 다시 읽어보십시오.


"theExample.itsProblem은 Example.itsProblem과 동일하게 자동으로 설정되지만 전혀 동일한 변수가 아니며 독립적으로 변경할 수 있습니다."라고 말하지만 이는 옳지 않으며 사용자의 문구가 오해의 소지가 있습니다. 나는 그 문구를 수정 제안, 그래서 당신이 거기에 무슨 일이 일어나고 있는지 알고 신뢰 "는 것입니다 같은 변수 있지만 각 개체에 대해 독립적으로 rebinded 할 수 있습니다."
jsbueno

예, 그러나 바인딩은 완전히 알려지지 않은 Java 또는 C와 같은 다른 프로그래밍 언어에 대한 개념입니다. 그런 다음 바인딩이 무엇인지 설명하고, 후기 바인딩, 변경 가능한 객체에 대한 참조 문제를 설명하겠습니다. 너무 깁니다. 언젠가는 이해의 제단에서 정확성을 희생해야한다고 생각합니다.
e-satis

살펴볼 가치가있는 @classmethod 데코레이터도 있습니다. 여기에 흥미로운 토론 - stackoverflow.com/questions/12179271/...
JSH

1
이름 바인딩 : 레벨에 관계없이 거짓 진술을하는 것은 나쁜 생각이라고 생각합니다. 이 약간의 편집을 제안합니다. 그러나 theExample.itsProblem자동으로으로 설정 되므로주의해야합니다. 그러나 Example.itsProblem실제적인 관점에서 *는 전혀 동일한 변수가 아니며 독립적으로 변경할 수 있습니다. * : 실제로 동일한 객체로 시작하지만 Python의 이름 바인딩을
n611x007 2014

11

클래스 변수가 아닌 지역 변수를 선언하고 있습니다. 인스턴스 변수 (속성)를 설정하려면

class Example(object):
    def the_example(self):
        self.itsProblem = "problem"  # <-- remember the 'self.'

theExample = Example()
theExample.the_example()
print(theExample.itsProblem)

클래스 변수 (일명 정적 멤버) 를 설정하려면

class Example(object):
    def the_example(self):
        Example.itsProblem = "problem"
        # or, type(self).itsProblem = "problem"
        # depending what you want to do when the class is derived.

1
클래스 변수는 클래스 수준 에서 한 번 선언된다는 점을 제외하고 . 당신의 방식은 모든 인스턴스에 대해 재설정 할 것입니다. 이것은 실제로 당신이 원하는 것이 아닙니다. 또한 명시 적 자기 뒤에있는 근거 는 stackoverflow.com/questions/2709821/python-self-explained 를 참조하십시오 .

2

인스턴스 함수 (즉, self 전달됨)가있는 경우 self를 사용하여 다음을 사용하여 클래스에 대한 참조를 얻을 수 있습니다. self.__class__

예를 들어 아래 코드에서 tornado는 get 요청을 처리하는 인스턴스를 생성하지만, 우리는 get_handler클래스를 확보하고이를 사용하여 riak 클라이언트를 보유 할 수 있으므로 모든 요청에 ​​대해 하나를 생성 할 필요가 없습니다.

import tornado.web
import riak

class get_handler(tornado.web.requestHandler):
    riak_client = None

    def post(self):
        cls = self.__class__
        if cls.riak_client is None:
            cls.riak_client = riak.RiakClient(pb_port=8087, protocol='pbc')
        # Additional code to send response to the request ...
    

이것은 OPs 원래 제목의 질문을 보여주는 아주 좋은 예입니다. 실제로 OPs 예제는 제목과 일치하지 않으며 다른 답변은 예제를 참조합니다. 어쨌든 이것은 DRY 원칙을 위반하지 않기 때문에 클래스 수준 변수에 액세스하는 가장 좋은 방법입니다. 다른 예제와 마찬가지로. 클래스 이름을 반복하는 대신 self .__ class__를 사용하는 것이 좋습니다. 이는 코드의 미래를 증명하고 리팩토링을 더 쉽게 만들고 서브 클래 싱을 감히 사용한다면 이점도 가질 수 있습니다.
mit

독자는 위와 같은 처리기를 사용하면 단일 스레드가 아닌 응용 프로그램에서만 문제가 발생할 수 있음을 경고해야합니다. 클래스의 여러 인스턴스는 이론적으로 동일한 핸들러를 병렬로 사용할 수 있으며 핸들러가 내부 구조에 따라이를 수행하도록 설계되지 않은 경우 작동하지 않을 수 있습니다. 단일 스레드 애플리케이션에서 '병렬'이란 첫 번째 클래스 인스턴스가 핸들러 사용을 완료하지 않은 다음 두 번째 인스턴스가 핸들러 사용을 시작한다는 것을 의미합니다. 이러한 경우 인스턴스 변수를 대신 사용하는 것이 좋습니다.
mit

0

아래 예제와 같이 return 문을 구현하십시오! 당신은 잘해야합니다. 누군가에게 도움이되기를 바랍니다 ..

class Example(object):
    def the_example(self):
        itsProblem = "problem"
        return itsProblem 


theExample = Example()
print theExample.the_example()

1
코드 들여 쓰기를 수정해야합니다. 이이 질문에 대한 우수 답변은 또한 당신의 대답은 ... 그 답변에 기본적인 변화가 아닌 대체 솔루션입니다
HEADLESS_0NE
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.