Python 获取简单函数的目的

Python 获取简单函数的目的,python,python-2.7,Python,Python 2.7,我想问一下简单函数\uu get\uu的用途是什么,以及为什么if的行为与描述符类\uu get\uu不同 我的调查: 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

我想问一下简单函数
\uu get\uu
的用途是什么,以及为什么if的行为与描述符类
\uu get\uu
不同

我的调查:

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
导入检查
定义a(x,y):
返回x+y
def wr(f):
def包装(*args,**kwargs):
打印f
返回f(*args,**kwargs)
返回包装器
打印检查.getsource(a)
#定义a(x,y):
#返回x+y
print inspect.getsource(a.uu get_uu)#我们无法检查它,因为它是一个方法包装器
#回溯(最近一次呼叫最后一次):
# ...
#“函数、回溯、帧或代码对象”。格式(对象))
#TypeError:不是模块、类、方法、函数、回溯、帧或代码对象
a、 _uuuget_uuu=wr(a.uu get_uuu)#替换为委托工作并打印传递参数的函数
a2=a.uuu get_uuu(2)#我们可以将uu get_uuu用于functools.partial目的
#用(2,){}调用
打印a.uuu类uuu,a2.uuu类uuu#看起来a是一个普通函数,a2是一个绑定函数,但没有实例
#  
打印“a2结果:”,a2(3)
#a2结果:5
打印检查。获取源(a2)#源与函数a相同
#定义a(x,y):
#返回x+y

我们知道描述符类
\uuuu get\uuu
方法签名,它看起来与函数
a不匹配。

Python函数是描述符。这就是创建方法对象的方式。执行
obj.method
时,描述符协议被激活,函数的
\uuuuu get\uuuu
方法被调用。这将返回一个绑定方法

这就是为什么您将
a2
视为实例方法。当您执行
a.\uuuu get\uuuu(2)
时,您将
2
作为“实例”参数传递给
\uu get\uuuu
。如果您打印(a2)
,您将看到
,这表明Python认为
a2
是对象
2
的绑定方法


owner
参数在描述符协议中是可选的(或至少在函数的实现中是可选的),这就是为什么您可以只使用一个参数调用
\uuuuuuuuuuuuu\uuuuuu
。您可以调用
a.\uuuu get\uuuu(2,1)
并获取一个类似的对象。

\uuu get\uuuuu
是一个标准描述符
\uu get\uuuu
。数据模型没有反映这一点,但是
\uuuu get\uuu
owner
参数通常是可选的,因为它不为非
None
实例提供额外信息。这并不违反描述符协议

作为属性访问的一部分,函数的
\uuuuuuu get\uuuuu
通常被称为正常方式描述符
\uuuuu get\uuuuu
方法:

class Foo(object):
    def bar(self):
        return 3

foo = Foo()

# The following attribute access calls bar.__get__(foo, Foo) to create a method object.
bar_method = foo.bar

当我们在传递参数时对函数调用
\uuu get\uuu(self,instance,owner)
时:
self
本身就是一个函数,instance是
2
,owner是
None
,因为它是可选的。函数
\uuuu get\uuuu
方法期望函数本身期望实例(
self
)作为第一个参数,因此它返回绑定方法,该方法总是将传递的实例作为第一个参数。因为我们传递
2
来代替实例,所以我们得到
2
作为
a2
函数中的第一个参数传递。我说的对吗?@user1915011:我不确定我是否理解你
a.\uuu get\uuu
实际上并不关心
a
接受哪些参数。传递给
a.\uuuu get\uuuu
self
是函数
a
本身
a.\uu get\uu
不“检查”以查看
a
接受哪些参数。如果
a
是一个函数,
a.\uuuu get\uuuu
总是返回一个绑定方法对象,除非将
None
作为“实例”参数传递(在这种情况下,它返回一个未绑定的方法)。