简单函数 __get__ 的目的

Žil*_*nis 2 python python-2.7

我想问简单函数的目的是什么__get__以及为什么 if 的行为与描述符类不同__get__

我的调查:

import inspect

def a(x, y):
    return x + y

def wr(f):
    def wrapper(*args, **kwargs):
        print f.__name__, 'called with', args, kwargs
        return f(*args, **kwargs)
    return wrapper

print inspect.getsource(a)
# def a(x, y):
#     return x + y

print inspect.getsource(a.__get__) # we cannot inspect it because it is a method-wrapper
# Traceback (most recent call last):
# ...
#     'function, traceback, frame, or code object'.format(object))
# TypeError: <method-wrapper '__get__' of function object at 0x7fd43591e140> is not a module, class, method, function, traceback, frame, or code object

a.__get__ = wr(a.__get__) # replace with function that delegates work and prints passed arguments
a2 = a.__get__(2) # we can use __get__ for functools.partial purposes
# __get__ called with (2,) {}

print a.__class__, a2.__class__ # it looks like a is a normal function and a2 is a bound function, but there is no instance
# <type 'function'> <type 'instancemethod'>

print 'a2 result:', a2(3)
# a2 result: 5

print inspect.getsource(a2) # source the same as function a
# def a(x, y):
#     return x + y
Run Code Online (Sandbox Code Playgroud)

我们知道描述符类__get__方法签名object.__get__(self,instance,owner),它看起来与函数a.__get__签名不匹配。

Bre*_*arn 6

Python 函数是描述符。这就是方法对象的创建方式。当您这样做时obj.method,描述符协议被激活,并且函数的__get__方法被调用。这将返回一个绑定方法。

这就是为什么您将其视为a2实例方法。当您这样做时a.__get__(2),您将2作为“实例”参数传递给__get__。如果你这样做print(a2),你会看到<bound method ?.a of 2>,表明Python认为a2是该对象的绑定方法2

owner参数在描述符协议中是可选的(或者至少在它的函数实现中),这就是为什么您只能__get__使用一个参数进行调用。您可以调用a.__get__(2, 1)并取回类似的对象。