programing

Python의 클래스 메서드 차이: bound, unbound 및 static

copysource 2022. 9. 25. 14:59
반응형

Python의 클래스 메서드 차이: bound, unbound 및 static

다음 수업 방법의 차이점은 무엇입니까?

하나는 정적이고 다른 하나는 그렇지 않은가?

class Test(object):
  def method_one(self):
    print "Called method_one"

  def method_two():
    print "Called method_two"

a_test = Test()
a_test.method_one()
a_test.method_two()

Python에서는 bound 메서드와 unbound 메서드가 구분됩니다.

멤버 함수에 콜(「」등)입니다.method_one 함수 "바인드 함수"

a_test.method_one()

로 변환됩니다.

Test.method_one(a_test)

MethodMethod.로 호출합니다.의 「」, 「」에의 이 행해집니다.method_twoTypeError

>>> a_test = Test() 
>>> a_test.method_two()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: method_two() takes no arguments (1 given) 

데코레이터를 사용하여 메서드의 동작을 변경할 수 있습니다.

class Test(object):
    def method_one(self):
        print "Called method_one"

    @staticmethod
    def method_two():
        print "Called method two"

기본 메타클래스를 .type(클래스의 클래스, cf. this question)에 대해 바인딩된 메서드를 작성하지 않음method_two.

이제 인스턴스 또는 클래스 모두에서 직접 스태틱메서드를 호출할 수 있습니다.

>>> a_test = Test()
>>> a_test.method_one()
Called method_one
>>> a_test.method_two()
Called method_two
>>> Test.method_two()
Called method_two

Python의 메서드는 디스크립터 시스템의 기본을 이해하면 매우 간단합니다.다음 클래스를 상상해 보십시오.

class C(object):
    def foo(self):
        pass

이제 셸 내의 클래스를 살펴보겠습니다.

>>> C.foo
<unbound method C.foo>
>>> C.__dict__['foo']
<function foo at 0x17d05b0>

하면 알 수 있듯이foo클래스 속성에는 바인딩되지 않은 메서드가 반환되지만 클래스 저장소(dict) 안에는 함수가 있습니다.왜요?그 이유는 당신의 클래스가 다음을 구현하기 때문입니다.__getattribute__디스크립터를 해결합니다.복잡하게 들리지만 그렇지 않다. C.foo는, 그 이 동등합니다.

>>> C.__dict__['foo'].__get__(None, C)
<unbound method C.foo>

는 함수에 a 가 있기 때문입니다.__get__이치노None클래스 인스턴스입니다.

>>> c = C()
>>> C.__dict__['foo'].__get__(c, C)
<bound method C.foo of <__main__.C object at 0x17bd4d0>>

Python python python은 python python python python python python?메서드 개체가 함수의 첫 번째 매개 변수를 클래스의 인스턴스에 바인딩하기 때문입니다.거기서 자아가 나온다.staticmethod★★★★

 class C(object):
  @staticmethod
  def foo():
   pass

staticmethod는 당신의 합니다.__get__메서드가 아닌 함수로 래핑된 함수를 반환합니다.

>>> C.__dict__['foo'].__get__(None, C)
<function foo at 0x17d0c30>

그게 설명이 됐으면 좋겠어요.

클래스 멤버를 호출하면 Python은 오브젝트에 대한 참조를 첫 번째 파라미터로 자동으로 사용합니다. ''self라고 할 수 .gargaloo원하신다면요그렇긴 하지만,method_two TypeErrorPython은 파라미터가 없는 것으로 정의된 메서드에 파라미터(부모 오브젝트에 대한 참조)를 자동으로 전달하려고 하기 때문입니다.

실제로 작동하려면 클래스 정의에 다음을 추가할 수 있습니다.

method_two = staticmethod(method_two)

'어울릴 수 없다'를 할 수도 있어요.@staticmethod 기능 데코레이터

>>> class Class(object):
...     def __init__(self):
...         self.i = 0
...     def instance_method(self):
...         self.i += 1
...         print self.i
...     c = 0
...     @classmethod
...     def class_method(cls):
...         cls.c += 1
...         print cls.c
...     @staticmethod
...     def static_method(s):
...         s += 1
...         print s
... 
>>> a = Class()
>>> a.class_method()
1
>>> Class.class_method()    # The class shares this value across instances
2
>>> a.instance_method()
1
>>> Class.instance_method() # The class cannot use an instance method
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method instance_method() must be called with Class instance as first argument (got nothing instead)
>>> Class.instance_method(a)
2
>>> b = 0
>>> a.static_method(b)
1
>>> a.static_method(a.c) # Static method does not have direct access to 
>>>                      # class or instance properties.
3
>>> Class.c        # a.c above was passed by value and not by reference.
2
>>> a.c
2
>>> a.c = 5        # The connection between the instance
>>> Class.c        # and its class is weak as seen here.
2
>>> Class.class_method()
3
>>> a.c
5

method_2는 멤버 함수를 정의하고 있지만 함수의 멤버를 알리지 않기 때문에 동작하지 않습니다.마지막 행을 실행하면 다음과 같이 표시됩니다.

>>> a_test.method_two()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: method_two() takes no arguments (1 given)

클래스의 멤버 함수를 정의하는 경우 첫 번째 인수는 항상 'self'여야 합니다.

위의 Armin Ronacher의 정확한 설명, 나 같은 초보자가 잘 이해할 수 있도록 그의 답변을 확장합니다.

클래스에서 정의된 메서드의 차이는 스태틱 메서드인지 인스턴스 메서드인지에 따라 달라집니다(여기에서는 설명되지 않으므로 건너뜁니다).예를 들어, 메서드가 런타임 중에 클래스 인스턴스에 대한 참조를 수신하는지 여부를 확인합니다.

class C:
    a = [] 
    def foo(self):
        pass

C # this is the class object
C.a # is a list object (class property object)
C.foo # is a function object (class property object)
c = C() 
c # this is the class instance

__dict__은 클래스 객체의 및 에 대한 합니다.따라서 클래스 객체의 모든 및 메서드에 대한 참조를 보유합니다.

>>> C.__dict__['foo']
<function foo at 0x17d05b0>

foo 메서드는 위와 같이 접근할 수 있습니다.여기서 주의해야 할 중요한 점은 python의 모든 것은 객체이기 때문에 위의 사전의 참조 자체가 다른 객체를 가리키고 있다는 것입니다.Class Property Objects - 또는 간략하게 답변할 수 있는 범위 내의 CPO라고 부릅니다.

합니다.__get__()공인회계사

CPO가 디스크립터인지 아닌지를 판단하기 위해 파이썬인터프리터는 디스크립터 프로토콜을 구현하고 있는지 여부를 확인합니다.기술자 프로토콜을 구현하는 것은 세 가지 방법을 구현하는 것이다.

def __get__(self, instance, owner)
def __set__(self, instance, value)
def __delete__(self, instance)

예를 들어,

>>> C.__dict__['foo'].__get__(c, C)

어디에

  • self 스트링,등의 일 수 이며 runtimeCPO(runtimeCPO, "truntime", "truntime, "truntime", "truntime, "truntimeCPO")에 됩니다.
  • instance는 이 되어 있는 로, 의 CPO가 제공하는 합니다.
  • owner는 이 되어 있는 클래스 당사가 가 있습니다.「 CPO 」 、 「 C 」 、 「 C 」 。, 때 또는 할 수 있기 에 이 .인스턴스에서 호출할 때 런타임은 인스턴스 또는 클래스(다형성)를 제공할 수 있기 때문에 제공할 필요가 없습니다.
  • value이며 usCPO에되어야 합니다.

모든 CPO가 디스크립터인 것은 아닙니다.예를들면

>>> C.__dict__['foo'].__get__(None, C)
<function C.foo at 0x10a72f510> 
>>> C.__dict__['a'].__get__(None, C)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__get__'

이는 목록 클래스가 기술자 프로토콜을 구현하지 않기 때문입니다.

'의 논거는 '자아'c.foo(self) 메서드의 는 이 메서드이기 때문에 합니다.C.__dict__['foo'].__get__(c, C)(위에서 설명한 바와 같이 C는 검출 또는 폴리모핑이 가능하므로 필요하지 않습니다).또한 이것이 필요한 인스턴스 인수를 전달하지 않으면 TypeError가 표시되는 이유입니다.

메서드가 클래스 오브젝트C에서 계속 참조되고 있으며 클래스 인스턴스와의 바인딩은 인스턴스 오브젝트 형식의 컨텍스트를 이 함수에 전달함으로써 이루어집니다.

하지 않거나 않기로 CPO를 이었기 때문에 .__get__()이치노 적용됩니다.@staticmethod

class C(object):
  @staticmethod
  def foo():
   pass

CPO에 .foo 다음과 할 수 .

>>> C.__dict__['foo'].__get__(None, C)
<function foo at 0x17d0c30>

정적 메서드의 사용 사례는 네임스페이스와 코드 유지보수에 가깝습니다(클래스에서 삭제하여 모듈 전체에서 사용 가능).

메서드(액세스인스턴스 변수, 클래스 변수 등)를 일치시킬 필요가 없는 한 인스턴스 메서드보다 스태틱메서드를 작성하는 것이 좋을 수 있습니다.한 가지 이유는 개체에 대한 원치 않는 참조를 유지하지 않음으로써 가비지 수집을 용이하게 하기 위함입니다.

그것은 오류입니다.

첫 번째 줄은 이렇게 해야 합니다(대문자에 주의).

class Test(object):

클래스의 메서드를 호출할 때마다 첫 번째 인수(따라서 self라는 이름)로 지정되며 method_2는 이 오류를 발생시킵니다.

>>> a.method_two()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method_two() takes no arguments (1 given)

두 번째 것은 python이 내부적으로 a_test 인스턴스를 첫 번째 인수로 호출하려고 하는데 method_two가 인수를 받아들이지 않기 때문에 동작하지 않고 런타임 오류가 발생합니다.static 메서드와 동등한 값을 원하는 경우 클래스 메서드를 사용할 수 있습니다.Python의 클래스 메서드는 Java나 C#과 같은 언어의 정적 메서드보다 훨씬 덜 필요합니다.대부분의 경우 클래스 정의 밖에서 모듈 내의 메서드를 사용하는 것이 가장 좋습니다.이러한 메서드는 클래스 메서드보다 더 효율적으로 동작합니다.

method_2에 대한 호출은 Python 런타임에서 자동으로 self 파라미터를 받아들이지 않는 예외를 발생시킵니다.

클래스에서 Python .staticmethod decorator.

Class Test(Object):
  @staticmethod
  def method_two():
    print "Called method_two"

Test.method_two()

Guido First Class의 모든 문서를 읽어보십시오. Unbound, Bound 메서드가 어떻게 탄생하는지 명확하게 설명합니다.

바인딩 메서드 = 인스턴스 메서드

Unbound method = static method입니다.

method_two무효입니다.전화할 때method_two 하면 '이렇게 하다'가 TypeError: method_two() takes 0 positional arguments but 1 was given역사사통

는 '경계함수'라고 '입니다.a_test.method_two()으로 받아들여집니다.self의 인스턴스를 가리키고 있습니다.Test를 첫 번째 파라미터로 지정합니다.를 통해self오브젝트 상에서 할 수 .instance Atribute는 Atribute를 사용합니다.

Unbound 메서드

Unbound 메서드는 아직 특정 클래스 인스턴스에 바인딩되지 않은 메서드입니다.

바인드 메서드 방식

바인딩된 메서드는 클래스의 특정 인스턴스에 바인딩된 메서드입니다.

여기서 설명한 바와 같이, 자아는 함수의 구속, 구속 또는 정적인 것에 따라 다른 것을 참조할 수 있습니다.

다음의 예를 참조해 주세요.

class MyClass:    
    def some_method(self):
        return self  # For the sake of the example

>>> MyClass().some_method()
<__main__.MyClass object at 0x10e8e43a0># This can also be written as:>>> obj = MyClass()

>>> obj.some_method()
<__main__.MyClass object at 0x10ea12bb0>

# Bound method call:
>>> obj.some_method(10)
TypeError: some_method() takes 1 positional argument but 2 were given

# WHY IT DIDN'T WORK?
# obj.some_method(10) bound call translated as
# MyClass.some_method(obj, 10) unbound method and it takes 2 
# arguments now instead of 1 

# ----- USING THE UNBOUND METHOD ------
>>> MyClass.some_method(10)
10

인스턴스를 하지 않았기 에:obj마지막 통화에서는 정적 방식이라고 할 수 있습니다.

만약 그렇다면, 와의 차이는 무엇입니까?MyClass.some_method(10) 및 을 사용하여 합니다.@staticmethod★★★★★★★★★★★★★★★★★★?

데코레이터를 사용함으로써 먼저 인스턴스를 작성하지 않고 메서드를 사용하는 것을 명확히 합니다.일반적으로 클래스 멤버 메서드가 인스턴스 없이 사용될 것으로 예상하지 않으며, 이러한 메서드에 액세스하면 메서드의 구조에 따라 오류가 발생할 수 있습니다.

「」, 「」를 추가해 주세요.@staticmethod데코레이터는 물건을 통해서도 닿을 수 있도록 하고 있습니다.

class MyClass:    
    def some_method(self):
        return self    

    @staticmethod
    def some_static_method(number):
        return number

>>> MyClass.some_static_method(10)   # without an instance
10
>>> MyClass().some_static_method(10)   # Calling through an instance
10

인스턴스 메서드에서는 위의 예를 수행할 수 없습니다.콜은 로) 수 두 콜은 됩니다.MyClass.some_method(obj, 10) 그그 a a a a 를 올릴 수 있다.TypeError인스턴스 메서드가 하나의 인수를 사용하고 의도하지 않게 두 개의 인수를 통과하려고 했기 때문입니다.

다음, 를 통해서 메서드를 할 수 , 정적인 메서드를 호출할 수 있다'라고 수 "인스턴스와 클래스를 모두 통해 스태틱메서드를 호출할 수 있다면,MyClass.some_static_method ★★★★★★★★★★★★★★★★★」MyClass().some_static_method!은."."."."."."."."."."."."."."!

언급URL : https://stackoverflow.com/questions/114214/class-method-differences-in-python-bound-unbound-and-static

반응형