![](/img/trans.png)
[英]What exactly is Python multiprocessing Module's .join() Method Doing?
[英]What exactly is a method in Python?
在下面的代码中,object a
有两个函数作为属性:一个是 class 属性,一个是它自己的实例属性。
class A:
def foo(*args):
pass
a = A()
def bar(*args):
pass
a.bar = bar
print(a.foo)
print(a.bar)
我所期望的是bar()
和foo()
都将是 object a
方法,但是,从这段代码的 output 来看,事实并非如此——只有foo
是a
的方法。
<bound method A.foo of <__main__.A object at 0x0000016F5F579AF0>>
<function bar at 0x0000016F5F5845E0>
那么Python中的方法到底是什么? 是不是一个包含 function 定义的 class 属性,似乎是这样。
为什么 Python 不将属性bar
视为一种方法? Python 这种行为背后的想法究竟是什么?
方法是 class 方法的实例,该方法由function
值的class属性的__get__
method
返回。
a.bar
是实例属性,而不是 class 属性。
在寻找a.foo
时,Python 首先寻找A.foo
。 找到它后,它接下来检查它的值是否有__get__
方法(作为function
值,它确实有。)因为A.foo
是一个描述符(即有一个__get__
方法),它的__get__
方法被调用a.foo
与A.foo.__get__(a, A)
相同。 返回值是一个method
object,其__call__
方法调用底层function,object和它自己的ZDBC16FB4CAA5BDA8ED7BDA77。 那是,
a.foo(x) == A.foo.__get__(a, A)(x)
== A.foo(a, x)
因为a.bar
是一个实例属性,所以不调用描述符协议,所以a.bar
与bar
完全相同 object 。
(这是Descriptor HowTo Guide内容的一个极其精简的版本,尤其是关于方法的部分。我强烈推荐阅读它。)
a.bar
的查找首先在A.__dict__
中查找bar
。 如果找不到, Python 会查找a.__dict__
,并找到function
来调用:故事结束。
这是因为您将属性设置为 class 的实例,而不是其本身。
按照您的示例,让我们设置:
A.bar = bar
您会看到 output 是:
print(A.bar)
# <function bar at 0x0000021821D57280>
c = A()
print(c.bar)
# <bound method bar of <__main__.A object at 0x0000021821EEA400>>
绑定方法是需要 class 本身的实际实例的方法。 这就是为什么我们通常将self
作为第一个参数:实例知道在调用时将自己传递给 function。 通过将function设置为实例的属性,方法不绑定,第一个参数不会是自己。
如果我们将 function bar
设置为如下所示,我们可以看到这种行为:
def bar(*args):
print("Argument types:", *map(type, args))
a.bar = bar
a.bar()
# Argument types:
A.bar = bar
c = A()
c.bar()
# Argument types: <class '__main__.A'>
我们看到,使用绑定方法,它会将自身传递给 function。 这是将方法设置为属性与实际将其设置为 class 本身的区别。
a.bar
不是 BOUND 方法。 它是一个已设置为属性的可调用对象。 这意味着,除其他外,它不会自动获取self
。
class A:
def __init__(self):
self.baz = 'baz'
def foo(self):
print(self.baz)
def bar(obj):
print(obj.baz)
a = A()
a.bar = bar
a.foo()
# prints baz
a.bar()
# raises TypeError: bar() missing 1 required positional argument: 'obj'
a.bar(a)
# prints baz
您可以使用types.MethodType
将方法变成绑定方法:
a.bar = types.MethodType(bar, a)
a.bar()
# prints baz
这只会将它绑定到实例; 其他实例将没有此属性
a2 = A()
a2.bar()
# AttributeError: 'A' object has no attribute 'bar'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.