함수, 바인딩되지 않은 메서드 및 바인딩 된 메서드의 차이점은 무엇입니까?
나는 때문에 코멘트 스레드에서 토론의이 질문을 부탁 해요 이 답변 . 나는 내 머리를 빙빙 돌릴 수있는 방법의 90 %입니다.
In [1]: class A(object): # class named 'A'
...: def f1(self): pass
...:
In [2]: a = A() # an instance
f1
세 가지 다른 형태로 존재합니다.
In [3]: a.f1 # a bound method
Out[3]: <bound method a.f1 of <__main__.A object at 0x039BE870>>
In [4]: A.f1 # an unbound method
Out[4]: <unbound method A.f1>
In [5]: a.__dict__['f1'] # doesn't exist
KeyError: 'f1'
In [6]: A.__dict__['f1'] # a function
Out[6]: <function __main__.f1>
바인딩 된 메서드 , 바인딩되지 않은 메서드 및 함수 개체 의 차이점은 무엇입니까 ? 모두 f1에 의해 설명됩니다. 이 세 가지 물체를 어떻게 부르나요? 그들은 어떻게 서로 변할 수 있습니까? 이 항목에 대한 문서 는 이해하기 매우 어렵습니다.
기능은 바이 만든 def
문, 또는에 의해 lambda
. Python 2에서 함수가 class
명령문 본문에 표시 되거나 type
클래스 생성 호출에 전달 되면 바인딩되지 않은 메서드 로 변환됩니다 . (Python 3에는 언 바운드 메서드가 없습니다. 아래 참조) 클래스 인스턴스에서 함수에 액세스 하면 메서드에 인스턴스를 첫 번째 매개 변수 로 자동으로 제공 하는 바인딩 된 메서드 로 변환됩니다 self
.
def f1(self):
pass
여기 f1
에 기능이 있습니다.
class C(object):
f1 = f1
지금 C.f1
은 언 바운드 방법입니다.
>>> C.f1
<unbound method C.f1>
>>> C.f1.im_func is f1
True
type
클래스 생성자를 사용할 수도 있습니다 .
>>> C2 = type('C2', (object,), {'f1': f1})
>>> C2.f1
<unbound method C2.f1>
f1
언 바운드 메서드로 수동으로 변환 할 수 있습니다.
>>> import types
>>> types.MethodType(f1, None, C)
<unbound method C.f1>
바인딩되지 않은 메서드는 클래스 인스턴스에 대한 액세스에 의해 바인딩됩니다.
>>> C().f1
<bound method C.f1 of <__main__.C object at 0x2abeecf87250>>
액세스는 설명자 프로토콜을 통해 호출로 변환됩니다.
>>> C.f1.__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
다음을 결합 :
>>> types.MethodType(f1, None, C).__get__(C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf87310>>
또는 직접 :
>>> types.MethodType(f1, C(), C)
<bound method C.f1 of <__main__.C object at 0x2abeecf871d0>>
함수와 바인딩되지 않은 메서드의 주요 차이점은 후자는 바인딩 된 클래스를 알고 있다는 것입니다. 바인딩되지 않은 메서드를 호출하거나 바인딩하려면 해당 클래스 유형의 인스턴스가 필요합니다.
>>> f1(None)
>>> C.f1(None)
TypeError: unbound method f1() must be called with C instance as first argument (got NoneType instance instead)
>>> class D(object): pass
>>> f1.__get__(D(), D)
<bound method D.f1 of <__main__.D object at 0x7f6c98cfe290>>
>>> C.f1.__get__(D(), D)
<unbound method C.f1>
함수와 바인딩되지 않은 메서드의 차이가 매우 적기 때문에 Python 3는 그 차이를 제거합니다. Python 3에서 클래스 인스턴스의 함수에 액세스하면 함수 자체가 제공됩니다.
>>> C.f1
<function f1 at 0x7fdd06c4cd40>
>>> C.f1 is f1
True
Python 2와 Python 3 모두에서 다음 세 가지는 동일합니다.
f1(C())
C.f1(C())
C().f1()
함수를 인스턴스에 바인딩하면 첫 번째 매개 변수 (일반적으로라고 함 self
)를 인스턴스 에 고정하는 효과가 있습니다. 따라서 바인딩 된 메서드 C().f1
는 다음 중 하나와 동일합니다.
(lamdba *args, **kwargs: f1(C(), *args, **kwargs))
functools.partial(f1, C())
이해하기 꽤 어렵다
글쎄, 그것은 꽤 어려운 주제이며 설명자와 관련이 있습니다.
기능부터 시작하겠습니다. 여기에서 모든 것이 명확합니다. 호출하기 만하면 모든 제공된 인수가 실행되는 동안 전달됩니다.
>>> f = A.__dict__['f1']
>>> f(1)
1
TypeError
매개 변수 수에 문제가있는 경우 Regular 가 발생합니다.
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f1() takes exactly 1 argument (0 given)
자, 방법. 메서드는 약간의 향신료가있는 함수입니다. 여기서 설명자가 게임에 등장합니다. 설명 된 바와 같이 데이터 모델 , A.f1
및 A().f1
로 번역 A.__dict__['f1'].__get__(None, A)
하고 type(a).__dict__['f1'].__get__(a, type(a))
각각. 그리고 이것들 __get__
의 결과 는 원시 f1
함수 와 다릅니다 . 이러한 개체는 원본에 대한 래퍼 f1
이며 몇 가지 추가 논리를 포함합니다.
unbound method
이 논리의 경우 첫 번째 인수가 다음의 인스턴스인지 확인합니다 A
.
>>> f = A.f1
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method f1() must be called with A instance as first argument (got nothing instead)
>>> f(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method f1() must be called with A instance as first argument (got int instance instead)
이 검사가 성공하면 f1
해당 인스턴스를 첫 번째 인수로 사용하여 원본 을 실행합니다 .
>>> f(A())
<__main__.A object at 0x800f238d0>
해당 im_self
속성은 None
다음과 같습니다.
>>> f.im_self is None
True
경우 bound method
이 로직 공급 즉시 원래 f1
의 인스턴스 A
가 (이 경우 실제로 저장된다 작성된 im_self
특성) :
>>> f = A().f1
>>> f.im_self
<__main__.A object at 0x800f23950>
>>> f()
<__main__.A object at 0x800f23950>
따라서 bound
기본 함수가 일부 인스턴스에 바인딩되어 있음을 의미합니다. unbound
여전히 바인딩되어 있지만 클래스에만 적용됨을 의미합니다.
함수 개체는 함수 정의에 의해 생성 된 호출 가능한 개체입니다. 바인딩 된 메서드와 바인딩되지 않은 메서드는 모두 도트 이항 연산자가 호출하는 설명자에 의해 생성 된 호출 가능한 개체입니다.
Bound and unbound method objects have 3 main properties: im_func
is the function object defined in the class, im_class
is the class, and im_self
is the class instance. For unbound methods, im_self
is None
.
When a bound method is called, it calls im_func
with im_self
as the first parameter followed its calling parameters. unbound methods calls the underlying function with just its calling parameters.
One interesting thing I saw today is that, when I assign a function to a class member, it becomes an unbound method. Such as:
class Test(object):
@classmethod
def initialize_class(cls):
def print_string(self, str):
print(str)
# Here if I do print(print_string), I see a function
cls.print_proc = print_string
# Here if I do print(cls.print_proc), I see an unbound method; so if I
# get a Test object o, I can call o.print_proc("Hello")
Please refer to the Python 2 and Python 3 documentation for more details.
My interpretation is the following.
Class Function
snippets:
Python 3:
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
return types.MethodType(self, obj)
Python 2:
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
return types.MethodType(self, obj, objtype)
- If a function is called without class or instance, it is a plain function.
If a function is called from a class or an instance, its
__get__
is called to retrieve wrapped function:
a.B.x
is same asB.__dict__['x'].__get__(None, B)
. In Python 3, this returns plain function. In Python 2, this returns an unbound function.b.
b.x
is same astype(b).__dict__['x'].__get__(b, type(b)
. This will return a bound method in both Python 2 and Python 3, which meansself
will be implicitly passed as first argument.
What is the difference between a function, an unbound method and a bound method?
From the ground breaking what is a function perspective there is no difference. Python object oriented features are built upon a function based environment.
Being bound is equal to:
Will the function take the class (cls) or the object instance (self) as the first parameter or no?
Here is the example:
class C:
#instance method
def m1(self, x):
print(f"Excellent m1 self {self} {x}")
@classmethod
def m2(cls, x):
print(f"Excellent m2 cls {cls} {x}")
@staticmethod
def m3(x):
print(f"Excellent m3 static {x}")
ci=C()
ci.m1(1)
ci.m2(2)
ci.m3(3)
print(ci.m1)
print(ci.m2)
print(ci.m3)
print(C.m1)
print(C.m2)
print(C.m3)
Outputs:
Excellent m1 self <__main__.C object at 0x000001AF40319160> 1
Excellent m2 cls <class '__main__.C'> 2
Excellent m3 static 3
<bound method C.m1 of <__main__.C object at 0x000001AF40319160>>
<bound method C.m2 of <class '__main__.C'>>
<function C.m3 at 0x000001AF4023CBF8>
<function C.m1 at 0x000001AF402FBB70>
<bound method C.m2 of <class '__main__.C'>>
<function C.m3 at 0x000001AF4023CBF8>
The output shows the static function m3
will be never called bound. C.m2
is bound to the C
class because we sent the cls
parameter which is the class pointer.
ci.m1
and ci.m2
are both bound; ci.m1
because we sent self
which is a pointer to the instance, and ci.m2
because the instance knows that the class is bound ;).
To conclude you can bound method to a class or to a class object, based on the first parameter the method takes. If method is not bound it can be called unbound.
Note that method may not be originally part of the class. Check this answer from Alex Martelli for more details.
ReferenceURL : https://stackoverflow.com/questions/11949808/what-is-the-difference-between-a-function-an-unbound-method-and-a-bound-method
'developer tip' 카테고리의 다른 글
std :: is_struct 유형 특성이없는 이유는 무엇입니까? (0) | 2020.12.26 |
---|---|
Mac 프롬프트 "권한이 거부되었습니다"에서 스크립트 실행 (0) | 2020.12.26 |
Flask에서 url_for ()가 사용할 도메인을 어디에서 정의합니까? (0) | 2020.12.25 |
두 개의 Div가 서로 나란히 있으며 반응 형 변경으로 스택됩니다. (0) | 2020.12.25 |
완전히 파이썬으로 된 안드로이드 앱 (0) | 2020.12.25 |