检查函数是否属于一个类

5

我正在尝试编写一款文档测试工具,它可以检查文档字符串是否与实际函数签名相匹配(以及其他内容)。然而,我遇到了一个难题。我找不到一种方法来确定给定的函数是否属于一个类。

import inspect

def func1():
    pass


class Foo:
    def method(self):
        pass

print(inspect.ismethod(func1))  # prints False
print(inspect.ismethod(Foo().method)) # prints True
print(inspect.ismethod(Foo.method)) # prints False - I want something that prints True here

问题在于方法通常将self作为它们的第一个参数,而这从未被记录在文档中(因为显而易见的原因)。这将导致我的测试失败,因为它们会遇到一个未记录的参数。
我希望不必明确检查第一个参数是否称为self并跳过它,因为a)没有任何东西阻止函数具有称为self的参数,b)名称self本身是一种约定(因此您可以拥有一个名为this_is_definitely_not_self的第一个参数的方法),并且我的工具将在任何情况下都失败。我也不能只初始化一个对象并检查函数是否是方法,因为这将在其__init__中需要必需参数的任何类中失败。
所以问题是,有没有办法在将函数绑定到对象之前检测函数是否是方法?还是我需要接受仅检查第一个参数是否称为self的事实?

你可以在函数名中查找 .inspect.ismethod(Foo.method) or '.' in Foo.method.__name__ - Patrick Haugh
2
@patrick Foo.method.__name__ 将会是 method。不过,__qualname__ 可能更适合这个情况。 - internet_user
1
从语义上讲,你最多只能检测到函数最初是在类体中定义的。仅此而已。你试图解决的实际用例是什么? - Martijn Pieters
我不应该是第一个想到这个的人。但由于没有人谈论它,这对这种情况来说肯定不正确。所以,请告诉我为什么不在dir(Foo)中执行“'method'”。 - Abhijeetk431
@Abhijeetk431 因为我想要能够在任意对象上检查这个。考虑到我要测试10多个类中的数百个函数/方法。给定这个列表中的任意可调用对象,我希望有一种方法来检测它是否属于一个类(任何类),以便可以从参数检查中排除“self”,或者它是否是独立的,这样我就可以检查所有的参数。 - Chinmay Kanchi
显示剩余5条评论
1个回答

6

一个选项是__qualname__。对于方法,这包括您可以使用的类名。这是添加此属性的原因之一:

definition.__qualname__

类、函数、方法、描述符或生成器实例的限定名称。

有关此属性的更多信息,请参见PEP 3155的提案

当然,由于__qualname__在类定义期间设置,因此当函数被动态添加到类中时,可能会出现误报。因此,该答案基本上涵盖了一个函数是否已在类中定义的问题。

因为类内定义的函数和类外定义的函数没有区别(除了在大多数情况下的__qualname__),所以没有明确的方法来检测这个问题。
一个明智的做法是使用__qualname__作为“快速”检查,看看函数是否在类内定义,如果为False,则回退到使用inspect.signature函数检查self,并检查'self' in signature(func).parameters
你无法涵盖所有情况,因为这是Python,我可以做任何我想做的事情。尽管如此,我们都是自愿的成年人。 :)

1
哎呀!这真是个讨厌的陷阱,我可以看出它会导致一些很难找到的错误。不确定在这种情况下是否比仅仅检查self更好:\ 不管怎样,给你点赞! - Chinmay Kanchi
1
@ChinmayKanchi 是的,我能理解检查self的方法也可能会导致一些麻烦。我不认为有一种方法可以涵盖所有边缘情况,似乎需要结合多种方法。 - Dimitris Fasarakis Hilliard
我可能会坚持检查 self。由于这是一个文档测试工具,我认为我可以合理地假设任何关心运行它的人都会足够关心,不会做出像重命名 self 这样完全愚蠢的决定 :p - Chinmay Kanchi
此外,我认为我从未见过野外代码中使用未绑定函数的 self 或者调用绑定方法的第一个参数以外的任何名称。不过,我确实看到过在运行时向对象/类添加方法的代码(甚至在自动生成测试时也写过一些)! - Chinmay Kanchi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接