为什么通过类访问方法时,`ismethod` 返回 False?

问题描述 投票:0回答:1

定义一个简单的方法:

class Foo:
    def bar(self):
        print('bar!')

现在使用

inspect.ismethod

>>> from inspect import ismethod
>>> ismethod(Foo.bar)
False

这是为什么呢?

bar
不是方法吗?

python python-inspect
1个回答
0
投票

查阅文档

inspect.ismethod(object)

如果对象是用 Python 编写的绑定方法,则返回

True

所以

ismethod
实际上只是测试 bound 方法。这意味着如果您创建一个实例并通过该实例访问该方法,
ismethod
将返回
True
:

>>> obj = Foo()
>>> ismethod(obj.bar)
True

“绑定”方法意味着已经绑定到对象的方法,因此该对象作为

self
参数提供。这就是您如何在不带参数的情况下调用
obj.bar()
,即使
bar
被声明为具有一个参数。

我们还可以通过查看类型来看出区别:

>>> Foo.bar
<function Foo.bar at 0x7853771f1ab0>
>>> obj.bar
<bound method Foo.bar of <__main__.Foo object at 0x7853771e4850>>

只有后者才是绑定方法。

Foo.bar
是一个函数,Python的类型系统不认为它是一个方法。


那么为什么

inspect.ismethod
会有这样的行为呢?

从Python的角度来看,

bar
是一个普通函数,恰好被类
Foo
的属性引用。为了清楚地说明这一点,假设您在类外部定义了一个函数,然后将其分配给类属性:

def baz(self):
    print('baz!')

Foo.baz = baz

如果你调用

ismethod(baz)
,你应该期望它是
False
,因为
baz
显然只是在外部作用域中声明的函数。如果调用
ismethod(Foo.baz)
,你会得到相同的结果,因为
Foo.baz
只是对同一函数的引用。事实上,表达式
Foo.baz
被求值以获取对函数 before 的引用,该引用作为参数传递给
ismethod
;当然,
ismethod
不能根据该论点的来源对同一论点给出不同的答案。

当函数

bar
在类
Foo
内声明时,同样适用。类在 Python 中的工作方式几乎相当于在类外部声明函数,然后将其分配给与函数同名的类属性。所以
bar
baz
的工作方式完全相同:

>>> obj.baz
<bound method baz of <__main__.Foo object at 0x7853771e4850>>
>>> obj.baz()
baz!

简而言之,

Foo.bar
“不是方法”,因为在 Python 中,“方法”在绑定到实例之前只是普通函数。

© www.soinside.com 2019 - 2024. All rights reserved.