programing

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

goodcopy 2023. 1. 20. 16:19
반응형

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

Python 클래스에서 메서드를 정의하면 다음과 같습니다.

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

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

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

Peters의 Python의 Zen을 인용하고 싶습니다."명백한 것이 암묵적인 것보다 낫다."

및 C'Java + C++'this.는 추론할 수 없는 변수 이름이 있는 경우를 제외하고 추론할 수 있습니다.그래서 필요할 때도 있고 안 필요할 때도 있어요.

Python은 규칙보다는 이런 것들을 명확하게 만들기로 결정했습니다.

또한 암시되거나 가정된 것이 없으므로 구현의 일부가 노출됩니다. self.__class__,self.__dict__기타 "내부" 구조물은 명백한 방법으로 사용할 수 있습니다.

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

예.

>>> class C:
...     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!
>>>

또한 (내가 아는 한) 파이썬 런타임 구현이 더 쉬워집니다.

나는 이 주제에 대해 Guido van Rossum의 블로그를 읽어야 한다고 제안한다 - 왜 노골적인 자아가 남아야 하는가.

메서드 정의가 장식될 때 자동으로 'self' 파라미터를 부여해야 하는지 여부를 알 수 없습니다.데코레이터는 함수를 정적 메서드('self'가 없는 경우) 또는 클래스 메서드('인스턴스 대신 클래스를 참조하는 재미있는 종류의 셀프'가 있는 경우)로 바꾸거나 전혀 다른 작업을 수행할 수 있습니다(트리비).순수한 Python에서 '@classmethod' 또는 '@staticmethod'를 구현하는 데코레이터를 작성한다.)그 방법이 암묵적인 '자기'의 논거로 정의될지 말지 장식가가 무엇을 하는지 알지 않고는 방법이 없다.

특수 캐싱 '@classmethod'나 '@staticmethod' 같은 해킹은 거부합니다.

Python은 당신에게 "self"를 사용하도록 강요하지 않습니다.원하는 이름을 붙일 수 있습니다.메서드 정의 헤더의 첫 번째 인수는 오브젝트에 대한 참조임을 기억해야 합니다.

다음과 같이 할 수 「」, 「다」를 합니다).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#과 같은 언어에서는 상상하기 어렵습니다.자기 참조를 명확하게 함으로써, 그 자기 참조에 의해서 어떠한 대상도 자유롭게 참조할 수 있습니다.또한, 런타임에 클래스를 가지고 노는 이러한 방법은 정적인 언어에서는 하기 어렵습니다.그것이 반드시 좋은 것과 나쁜 것만은 아닙니다.단지 노골적인 자아가 이 모든 광기들을 존재하게 할 뿐입니다.

이렇게 : ,, 음, 음, 음, 음, 음, 음, 음, 다, 다, moreover, moreover moreover.메서드의 동작을 커스터마이즈하고 싶다(프로파일링 또는 일부 미친 흑마법의 경우).은 우리로 수 있게 할 수: 만약 ?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 to " " 。InnocentClass및를하는 경우magic_selfMagic Method 。의 키워드를 것 같아요.this1 ★★★★★★★★★★★★★★★★★」this2C#로 하다이와 같은 마법은 프레임워크가 훨씬 더 장황한 작업을 수행할 수 있도록 합니다.

다시 말씀드리지만, 저는 이 물건의 윤리에 대해 언급하고 싶지 않습니다.나는 단지 명확한 자기 언급이 없으면 하기 힘든 것들을 보여주고 싶었어요.

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

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

"The Zen of Python" 이외의 진짜 이유는 Functions가 Python의 퍼스트 클래스 시민이기 때문이라고 생각합니다.

그 말은 본질적으로 그들을 물건으로 만드는 거죠.기본적인 문제는 당신의 함수도 오브젝트일 경우 오브젝트 지향 패러다임에서 메시지 자체가 오브젝트일 때 어떻게 오브젝트에 메시지를 보낼 것인가 하는 것입니다.

이 모순을 줄이기 위해서는 실행의 맥락을 메서드에 전달하거나 검출하는 방법밖에 없습니다.그러나 python은 중첩된 함수를 가질 수 있기 때문에 실행 컨텍스트가 내부 함수에 따라 변경되기 때문에 그렇게 할 수 없습니다.

즉, 가능한 유일한 해결책은 명시적으로 '자기'를 전달하는 것입니다(실행의 맥락).

그래서 나는 Zen이 훨씬 늦게 나타난 것이 실행상의 문제라고 생각한다.

Python의 self에서 설명한 바와 같이 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()는 3개의 파라미터를 정의하지만 2개의 파라미터(6과 8)를 방금 통과했습니다.마찬가지로 distance()는 1개의 인수가 필요하지만 0개의 인수가 전달되었습니다.

Python은 왜 이 인수번호 불일치에 대해 불평하지 않는가?

일반적으로 어떤 인수를 사용하여 메서드를 호출할 때, 대응하는 클래스 함수는 첫 번째 인수 앞에 메서드의 객체를 배치함으로써 호출됩니다.따라서 obj.meth(args)와 같은 것은 Class.meth(obj, args)가 됩니다.콜 프로세스는 자동적으로 행해지지만, 수신 프로세스는 행해지지 않습니다(명시되어 있지 않습니다.

이것이 클래스의 함수의 첫 번째 파라미터가 오브젝트 그 자체여야 하는 이유입니다. 이 파라미터를 자기라고 쓰는 것은 규칙일 뿐입니다.Python에서는 키워드도 아니고 특별한 의미도 없습니다.다른 이름(이러한 이름)도 사용할 수 있지만 사용하지 않는 것이 좋습니다.대부분의 개발자는 자기 이외의 이름을 사용하는 것을 꺼리고 코드의 가독성을 저하시킵니다(「가독성」).
...
그럼 첫 번째 예시는 self.x는 인스턴스 속성이고 x는 로컬 변수입니다.그들은 같지 않고 다른 네임스페이스에 놓여 있다.

Self Is To Stay

Python에서는 C++나 Java에서와 같이 self를 키워드로 만들자고 제안하고 있습니다. 이것은 방법의 형식 매개변수 목록에서 명시적 자아의 중복 사용을 제거할 것이다.이 아이디어는 유망해 보이지만 실현되지는 않을 것이다.적어도 가까운 미래에는 아니다.주된 이유는 하위 호환성입니다.여기 Python을 만든 사람이 직접 블로그를 통해 명시적 자아가 남아야 하는 이유를 설명합니다.

'self' 파라미터는 현재 호출 개체를 유지합니다.

class class_name:
    class_variable
    def method_name(self,arg):
        self.var=arg 
obj=class_name()
obj.method_name()

여기서 self 인수는 오브젝트 obj를 유지합니다.따라서 self.var는 obj.var를 나타냅니다.

또 다른 매우 간단한 답이 있다: 비단뱀의 선에 따르면, "명백한 것이 암묵적인 것보다 낫다".

언급URL : https://stackoverflow.com/questions/68282/why-do-you-need-explicitly-have-the-self-argument-in-a-python-method

반응형