it-swarm-ko.tech

Python 메서드에 명시 적으로 "self"인수가 필요한 이유는 무엇입니까?

파이썬에서 클래스에 메소드를 정의 할 때 다음과 같이 보입니다 :

class MyClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

그러나 C #과 같은 다른 언어에서는 메소드 프로토 타입에서 인수로 선언하지 않고 "this"키워드를 사용하여 메소드가 바인딩 된 오브젝트에 대한 참조가 있습니다.

이것은 Python)에서 의도적 인 언어 디자인 결정입니까, 아니면 "self"를 인수로 전달해야하는 구현 세부 사항이 있습니까?

184
Readonly

저는 Peters의 Zen of Python을 인용하고 싶습니다. "명시적인 것이 묵시적인 것보다 낫다."

Java 및 C++, 'this. '는 추론 불가능한 변수 이름이있는 경우를 제외하고 추론 될 수 있습니다. 따라서 때로는 필요하지만 때로는 필요하지 않습니다.

파이썬은 규칙에 기초하기보다는 이와 같은 것을 명시 적으로 만들기로 결정합니다.

또한 암시되거나 가정 된 것이 없으므로 구현의 일부가 노출됩니다. self.__class__, self.__dict__ 및 기타 "내부"구조는 명백한 방식으로 사용 가능합니다.

88
S.Lott

방법과 기능의 차이를 최소화하는 것입니다. 메타 클래스에서 메소드를 쉽게 생성하거나 런타임시 기존 클래스에 메소드를 추가 할 수 있습니다.

예 :.

>>> class C(object):
...     def foo(self):
...         print "Hi!"
...
>>>
>>> def bar(self):
...     print "Bork bork bork!"
...
>>>
>>> c = C()
>>> C.bar = bar
>>> c.bar()
Bork bork bork!
>>> c.foo()
Hi!
>>>

또한 (내가 아는 한) python 런타임을 쉽게 구현할 수 있습니다.

58
Ryan

이 주제에 대해 Guido van Rossum의 블로그명시 적 자아를 유지해야하는 이유 를 읽어 보시기 바랍니다.

메소드 정의가 데코레이션 될 때 자동으로 'self'매개 변수를 제공할지 여부를 알 수 없습니다. 데코레이터는 함수를 정적 메소드 ( 'self'가없는) 또는 클래스 메소드 ( 인스턴스 대신 클래스를 참조하는 재미있는 종류의 자체가 있거나 완전히 다른 무언가를 할 수 있습니다 (순수한 파이썬에서 '@classmethod'또는 '@staticmethod'를 구현하는 데코레이터를 작성하는 것은 쉽지 않습니다). 메소드가 암시적인 'self'인수로 정의되는지 여부를 데코레이터가 무엇을하는지 알지 못하면 방법이 없습니다.

특수한 '@classmethod'및 '@staticmethod'와 같은 핵을 거부합니다.

52
bhadra

파이썬은 "self"를 사용하도록 강요하지 않습니다. 원하는 이름을 지정할 수 있습니다. 메소드 정의 헤더의 첫 번째 인수는 객체에 대한 참조임을 기억하면됩니다.

16
Victor Noagbodji

또한이 작업을 수행 할 수 있습니다. (즉, Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5)을 호출하면 12가 반환되지만 열광적 인 방식으로 수행됩니다.

class Outer(object):
    def __init__(self, outer_num):
        self.outer_num = outer_num

    def create_inner_class(outer_self, inner_arg):
        class Inner(object):
            inner_arg = inner_arg
            def weird_sum_with_closure_scope(inner_self, num)
                return num + outer_self.outer_num + inner_arg
        return Inner

물론 이것은 Java 및 C #과 같은 언어에서는 상상하기 어렵습니다. 자체 참조를 명시 적으로 지정하면 해당 자체 참조로 객체를 자유롭게 참조 할 수 있습니다. 런타임에 클래스를 가지고 노는 것이 더 정적 인 언어에서는하기가 더 어렵습니다. 반드시 좋은 것이 든 나쁜 것이 아니라, 명백한 자아만으로이 모든 게류가 존재할 수 있습니다.

또한, 이것을 상상해보십시오 : 우리는 메소드의 동작 (프로파일 링 또는 미친 흑 마법)을 사용자 정의하고 싶습니다. 이것은 우리가 생각하게 할 수있다 : 만약 우리가 행동을 무시하거나 통제 할 수있는 Method 클래스가 있다면 어떨까?

여기 있습니다 :

from functools import partial

class MagicMethod(object):
    """Does black magic when called"""
    def __get__(self, obj, obj_type):
        # This binds the <other> class instance to the <innocent_self> parameter
        # of the method MagicMethod.invoke
        return partial(self.invoke, obj)


    def invoke(magic_self, innocent_self, *args, **kwargs):
        # do black magic here
        ...
        print magic_self, innocent_self, args, kwargs

class InnocentClass(object):
    magic_method = MagicMethod()

이제 InnocentClass().magic_method()이 예상대로 작동합니다. 이 메서드는 innocent_self 매개 변수와 InnocentClass, magic_self와 MagicMethod 인스턴스에 바인딩됩니다. 허드? Java 및 C #)와 같은 언어로 2 개의 키워드 this1this2를 사용하는 것과 같습니다. 이와 같은 매직을 사용하면 프레임 워크가 훨씬 더 장황한 작업을 수행 할 수 있습니다.

다시 말하지만, 나는이 물건의 윤리에 대해 언급하고 싶지 않습니다. 나는 명백한 자기 참조 없이는하기 어려운 것들을 보여주고 싶었습니다.

6
vlad-ardelean

"파이썬의 선 (Zen of Python)"이외의 진짜 이유는 함수가 파이썬에서 일류 시민이기 때문이라고 생각합니다.

본질적으로 그것들을 객체로 만듭니다. 이제 근본적인 문제는 함수가 객체 인 경우 객체 지향 패러다임에서 메시지 자체가 객체 일 때 객체에 메시지를 보내는 방법은 무엇입니까?

이 역설을 줄이기 위해 닭고기 달걀 문제처럼 보이는 유일한 방법은 실행 컨텍스트를 메소드에 전달하거나 감지하는 것입니다. 그러나 python 중첩 함수를 가질 수 있기 때문에 실행 컨텍스트가 내부 함수에 대해 변경되므로 그렇게 할 수 없습니다.

이것은 가능한 유일한 해결책은 명시 적으로 'self'(실행 컨텍스트)를 전달하는 것입니다.

그래서 Zen이 훨씬 나중에 구현 문제라고 생각합니다.

2
pankajdoharey

PEP 227과 관련이 있다고 생각합니다.

클래스 범위의 이름은 액세스 할 수 없습니다. 가장 안쪽에있는 함수 범위에서 이름이 확인됩니다. 중첩 된 범위의 체인에서 클래스 정의가 발생하면 해결 프로세스는 클래스 정의를 건너 뜁니다. 이 규칙은 클래스 속성과 로컬 변수 액세스 간의 이상한 상호 작용을 방지합니다. 클래스 정의에서 이름 바인딩 조작이 발생하면 결과 클래스 오브젝트에 속성이 작성됩니다. 메소드 또는 메소드 내에 중첩 된 함수에서이 변수에 액세스하려면 자체 또는 클래스 이름을 통해 속성 참조를 사용해야합니다.

2
daole

Python의 자기 자신, Demystified 에서 설명 된 바와 같이

obj.meth (args)와 같은 것은 Class.meth (obj, args)가됩니다. 수신 프로세스는 명시 적이 지 않지만 호출 프로세스는 자동입니다. 이것이 클래스에서 함수의 첫 번째 매개 변수가 객체 자체 여야하는 이유입니다.

class Point(object):
    def __init__(self,x = 0,y = 0):
        self.x = x
        self.y = y

    def distance(self):
        """Find distance from Origin"""
        return (self.x**2 + self.y**2) ** 0.5

호출 :

>>> p1 = Point(6,8)
>>> p1.distance()
10.0

init ​​()는 세 개의 매개 변수를 정의하지만 방금 두 개 (6 및 8)를 전달했습니다. 마찬가지로 distance ()에는 하나의 인수가 필요하지만 0 개의 인수가 전달되었습니다.

Python 이 인수 번호가 일치하지 않습니다에 대해 불평하지 않는 이유는 무엇입니까?)

일반적으로 인수가있는 메소드를 호출 할 때 해당 클래스 함수는 메소드의 오브젝트를 첫 번째 인수 앞에 배치하여 호출됩니다. 따라서 obj.meth (args)와 같은 것은 Class.meth (obj, args)가됩니다. 수신 프로세스가 자동적이지 않은 동안 호출 프로세스는 자동입니다.

이것은 클래스에서 함수의 첫 번째 매개 변수가 객체 자체 여야하는 이유입니다. 이 매개 변수를 자체로 작성하는 것은 단지 규칙입니다]. 키워드가 아니며 파이썬에서 특별한 의미가 없습니다. 우리는 (이와 같은) 다른 이름을 사용할 수 있지만 강력히 추천하지는 않습니다. self가 아닌 다른 이름을 사용하면 대부분의 개발자가 눈살을 찌푸리고 코드의 가독성을 떨어 뜨립니다 ( "가독성").
...
첫 번째 예제 self.x는 인스턴스 속성이고 x는 로컬 변수입니다. 그것들은 동일하지 않으며 다른 네임 스페이스에 있습니다.

자아는 여기에있다

많은 사람들이 C++과 Java에서와 같이 파이썬에서 키워드를 만들도록 제안했습니다. 이렇게하면 메소드의 공식 매개 변수 목록에서 명시 적 자체를 중복 사용하지 않아도됩니다.이 아이디어는 유망한 것으로 보이지만 앞으로는 일어나지 않을 것입니다. 적어도 가까운 장래에는 그렇지 않습니다. 주된 이유는 이전 버전과의 호환성입니다. 다음은 Python) 작성자가 명시 적 자아를 유지해야하는 이유를 설명하는 블로그입니다.

0
mon