> 백엔드 개발 > 파이썬 튜토리얼 > Python에서 self 사용법 이해

Python에서 self 사용법 이해

高洛峰
풀어 주다: 2017-03-03 15:17:26
원래의
1627명이 탐색했습니다.

처음 Python에서 클래스 작성 방법을 배우기 시작했을 때 매우 번거로웠습니다. 정의할 때는 필요하지만 호출할 때는 필요하지 않은 이유는 무엇입니까? ? 이 기사를 읽은 후에는 모든 의심을 이해할 것입니다.

self는 클래스가 아닌 클래스의 인스턴스를 나타냅니다.

설명 예:

class Test:
  def prt(self):
    print(self)
    print(self.__class__)
 
t = Test()
t.prt()
로그인 후 복사

실행 결과는 다음과 같습니다

<__main__.Test object at 0x000000000284E080>
<class &#39;__main__.Test&#39;>
로그인 후 복사

위의 예에서 self는 클래스의 인스턴스를 나타내는 것이 분명합니다. 그리고 self.class는 클래스를 가리킵니다.

self를 self로 쓸 필요는 없습니다

많은 아이들이 다른 언어를 먼저 배우고 그다음에 Python을 배우기 때문에 항상 self가 이상하다고 느낍니다. 이렇게 쓰고 싶은데, 할 수 있나요?

물론 위의 코드를 다시 작성해 보겠습니다.

class Test:
  def prt(this):
    print(this)
    print(this.__class__)
 
t = Test()
t.prt()
로그인 후 복사

를 이렇게 변경한 후에도 실행 결과는 똑같습니다.

물론, 확립된 습관을 존중하고 자기 자신을 활용하는 것이 가장 좋습니다.

self를 쓸 수는 없나요?

Python 인터프리터 내부에서 t.prt()를 호출하면 실제로 Python은 Test.prt(t)로 해석하고, 즉, self를 클래스의 인스턴스로 대체합니다.

관심 있는 어린이는 위의 t.prt() 줄을 다시 작성할 수 있으며 실행 후 실제 결과는 정확히 동일합니다.

사실 self를 정의할 때 self를 생략할 수 없다고 부분적으로 설명했습니다. 꼭 해봐야 한다면 아래를 참고하세요:

class Test:
  def prt():
    print(self)
 
t = Test()
t.prt()
로그인 후 복사

런타임 알림 오류는 다음과 같습니다. prt가 정의될 ​​때 매개변수가 없지만 실행 시 강제로 매개변수를 전달합니다.

위에 설명된 대로 t.prt()는 Test.prt(t)와 동일하므로 프로그램은 매개변수 t를 하나 더 전달했음을 알려줍니다.

Traceback (most recent call last):
 File "h.py", line 6, in <module>
  t.prt()
TypeError: prt() takes 0 positional arguments but 1 was given
로그인 후 복사

물론 정의하고 호출할 때 클래스 인스턴스를 전달하지 않아도 괜찮습니다. 이것이 클래스 메소드입니다.

class Test:
  def prt():
    print(__class__)
Test.prt()
로그인 후 복사

실행 결과는 다음과 같습니다

<class &#39;__main__.Test&#39;>
로그인 후 복사

상속할 때 어느 것이 전달된 인스턴스는 self가 정의된 클래스의 인스턴스가 아니라 전달된 인스턴스입니다.

코드를 먼저 보세요

class Parent:
  def pprt(self):
    print(self)
 
class Child(Parent):
  def cprt(self):
    print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()
로그인 후 복사

실행 결과는 다음과 같습니다

<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>
로그인 후 복사

설명:

Child 클래스의 인스턴스를 참조하는 c.cprt()를 실행할 때 이해에 문제가 없어야 합니다.

그러나 c.pprt()를 실행하면 Child.pprt(c)와 동일하므로 self는 여전히 Child 클래스의 인스턴스를 참조합니다. pprt() 메서드는 self에 정의되어 있지 않습니다. 상속은 상속됨 트리를 살펴보면 prt() 메서드가 부모 클래스 Parent에 정의되어 있으므로 성공적으로 호출된다는 것을 알 수 있습니다.

descriptor 클래스에서 self는 descriptor 클래스의 인스턴스를 참조합니다.

은 이해하기 쉽지 않습니다.

class Desc:
  def __get__(self, ins, cls):
    print(&#39;self in Desc: %s &#39; % self )
    print(self, ins, cls)
class Test:
  x = Desc()
  def prt(self):
    print(&#39;self in Test: %s&#39; % self)
t = Test()
t.prt()
t.x
로그인 후 복사

실행 결과는 다음과 같습니다.

self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8> <class &#39;__main__.Test&#39;>
로그인 후 복사

대부분의 아동용 신발에 의문점이 생기기 시작하는데, 왜 Desc 클래스에서 self를 정의해야 합니까? 이를 호출하는 인스턴스가 아니어야 합니까? 어떻게 Desc 클래스의 인스턴스가 되었나요?

참고: 여기서 명확하게 보려면 눈을 뜨고 있어야 합니다. 여기서 호출되는 것은 t.x입니다. 즉, Test 클래스의 인스턴스 t의 속성 x가 정의되어 있지 않습니다. 인스턴스 t에서는 Class 속성 x가 발견되며 이 속성은 Desc 클래스의 인스턴스인 설명자 속성이므로 여기서는 Test 메소드가 사용되지 않습니다.

그런 다음 클래스를 통해 x 속성을 직접 호출하면 동일한 결과를 얻을 수 있습니다.

t.x를 Test.x로 변경한 결과는 다음과 같습니다.

self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class &#39;__main__.Test&#39;>
로그인 후 복사

여담: 많은 경우 설명자 클래스는 여전히 설명자를 호출하는 인스턴스가 누구인지 알아야 하므로 세 번째 매개변수가 있습니다. 두 매개변수는 다음과 같습니다. 이를 호출하는 클래스 인스턴스를 나타내는 데 사용되므로 t. Test.x를 사용하여 호출하면 인스턴스가 없기 때문에 None이 반환됩니다.

OO의 본질에서 Python의 자기 이해
예를 들어 이름과 나이가 포함된 사용자 데이터를 조작한다고 가정해 보겠습니다. 프로세스 지향을 사용하는 경우 구현은 다음과 같습니다.

def user_init(user,name,age): 
  user[&#39;name&#39;] = name 
  user[&#39;age&#39;] = age 
 
def set_user_name(user, x): 
  user[&#39;name&#39;] = x 
 
def set_user_age(user, x): 
  user[&#39;age&#39;] = x 
 
def get_user_name(user): 
  return user[&#39;name&#39;] 
 
def get_user_age(user): 
  return user[&#39;age&#39;] 
 
myself = {} 
user_init(myself,&#39;kzc&#39;,17) 
print get_user_age(myself) 
set_user_age(myself,20) 
print get_user_age(myself)
로그인 후 복사

보시다시피 사용자에 대한 다양한 작업을 수행하려면 사용자 매개변수를 전달해야 합니다.
객체 지향을 사용하면 매번 사용자 매개변수를 주고받을 필요가 없습니다. 관련 데이터와 작업이 한 곳에 바인딩되어 있어 이 클래스의 여러 위치에서 쉽게 데이터를 얻을 수 있습니다.
클래스의 다양한 위치에서 데이터에 접근할 수 있는 이유는 self에 바인딩되어 있기 때문입니다. 물론 해당 메서드의 첫 번째 매개 변수는 self라고 할 필요는 없지만 다른 이름으로 호출할 수 있습니다. 그냥 컨벤션.
다음은 객체지향 구현으로 훨씬 더 구조화되고 명확하며 가독성이 높다는 것을 알 수 있습니다.

class User(object): 
  def __init__(self,name,age): 
    self.name = name 
    self.age = age 
 
  def SetName(self,name): 
    self.name = name 
 
  def SetAge(self,age): 
    self.age = age 
 
  def GetName(self): 
    return self.name 
 
  def GetAge(self): 
    return self.age 
 
u = User(&#39;kzc&#39;,17) 
print u.GetName() 
print u.GetAge()
로그인 후 복사

위의 예에서 볼 수 있듯이 객체지향은 실제로 꽤 유용하지만 대부분의 사람들은 이를 잘 추상화하지 않고 잘 캡슐화합니다. 그리고 실수를 적용합니다.

요약

  • Self를 정의할 때 정의해야 하는데 호출 시 자동으로 전달됩니다.

  • 셀프 이름은 정해져 있지 않으나, 약관에 따라 셀프를 사용하는 것이 가장 좋습니다

  • self는 호출될 때 항상 클래스의 인스턴스를 참조합니다.

Python의 self 사용법 이해와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿