IT

왜 파이썬 메소드에 "self"인수가 명시 적으로 필요합니까?

lottoking 2020. 5. 16. 10:26
반응형

왜 파이썬 메소드에 "self"인수가 명시 적으로 필요합니까?


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

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

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

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


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

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

파이썬은 규칙에 기반하기보다는 이와 같은 것을 명시 적으로 선택합니다.

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


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

예 :

>>> 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!
>>>

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


나는 사람이 읽어야하는 것이 좋습니다 귀도 반 로섬 (Guido van Rossum)의 블로그 -이 주제에 대한 명시 적 자기 유지하는 이유는 .

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

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


파이썬은 "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, imagine this: We'd like to customize the behavior of methods (for profiling, or some crazy black magic). This can lead us to think: what if we had a class Method whose behavior we could override or control?

Well here it is:

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()

And now: InnocentClass().magic_method() will act like expected. The method will be bound with the innocent_self parameter to InnocentClass, and with the magic_self to the MagicMethod instance. Weird huh? It's like having 2 keywords this1 and this2 in languages like Java and C#. Magic like this allows frameworks to do stuff that would otherwise be much more verbose.

Again, I don't want to comment on the ethics of this stuff. I just wanted to show things that would be harder to do without an explicit self reference.


I think it has to do with PEP 227:

Names in class scope are not accessible. Names are resolved in the innermost enclosing function scope. If a class definition occurs in a chain of nested scopes, the resolution process skips class definitions. This rule prevents odd interactions between class attributes and local variable access. If a name binding operation occurs in a class definition, it creates an attribute on the resulting class object. To access this variable in a method, or in a function nested within a method, an attribute reference must be used, either via self or via the class name.


I think the real reason besides "The Zen of Python" is that Functions are first class citizens in Python.

Which essentially makes them an Object. Now The fundamental issue is if your functions are object as well then, in Object oriented paradigm how would you send messages to Objects when the messages themselves are objects ?

Looks like a chicken egg problem, to reduce this paradox, the only possible way is to either pass a context of execution to methods or detect it. But since python can have nested functions it would be impossible to do so as the context of execution would change for inner functions.

This means the only possible solution is to explicitly pass 'self' (The context of execution).

So i believe it is a implementation problem the Zen came much later.


As explained in self in Python, Demystified

anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit). This is the reason the first parameter of a function in class must be the object itself.

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

Invocations:

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

init() defines three parameters but we just passed two (6 and 8). Similarly distance() requires one but zero arguments were passed.

Why is Python not complaining about this argument number mismatch?

Generally, when we call a method with some arguments, the corresponding class function is called by placing the method's object before the first argument. So, anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit).

This is the reason the first parameter of a function in class must be the object itself. Writing this parameter as self is merely a convention. It is not a keyword and has no special meaning in Python. We could use other names (like this) but I strongly suggest you not to. Using names other than self is frowned upon by most developers and degrades the readability of the code ("Readability counts").
...
In, the first example self.x is an instance attribute whereas x is a local variable. They are not the same and lie in different namespaces.

Self Is Here To Stay

Many have proposed to make self a keyword in Python, like this in C++ and Java. This would eliminate the redundant use of explicit self from the formal parameter list in methods. While this idea seems promising, it's not going to happen. At least not in the near future. The main reason is backward compatibility. Here is a blog from the creator of Python himself explaining why the explicit self has to stay.


There is also another very simple answer: according to the zen of python, "explicit is better than implicit".

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

반응형