hasattr(obj, attribute) 用于检查对象是否具有指定的属性,但是给定一个属性,有没有办法知道它在哪里(全部)定义?

假设我的代码以字符串形式获取属性(或类方法)的名称,并且我想调用 classname.attribute 但我没有类名。

我想到的一种解决方案是

def finder(attr):
    for obj in globals():
        try:
            if globals()[obj].__dict__[attr]:
                return(globals()[obj])
        except:
            ...

用法:
class Lime(object):
    @classmethod
    def lfunc(self):
        print('Classic')

getattr(finder('lfunc'),'lfunc')() #Runs lfunc method of Lime class

我很确定这不是最好的(甚至是正确的方法)。有人可以提供更好的方法。

最佳答案

它总是“可能的”。它是否可取是另一回事。

一种快速而肮脏的方法是线性迭代所有类并检查是否有任何定义您拥有的属性。当然,这会发生冲突,并且会产生第一个具有此类命名属性的类。如果它存在多个,则由您决定要使用哪种:

def finder(attr):
    for cls in object.__subclasses__():
         if hasattr(cls, attr):
              return cls
    raise ValueError

不是在“全局”中搜索,而是搜索“对象”的所有子类 - 因此要找到的类不需要在 finder 函数所在的模块的命名空间中。

但是,如果您的方法在您搜索的一组类中是唯一的,也许您可​​以组装所有方法的映射并使用它来调用它们。

假设您的所有类都来自名为“Base”的类:
mapper = {attr_name:getattr(cls, attr_name)  for cls in base.__subclasses__() for attr_name, obj in cls.__dict__.items()
             if isinstance(obj, classmethod) }

然后你用 mapper['attrname']() 调用它们

这避免了每次方法调用时的线性搜索,因此会好得多。

- 编辑 -
__subclassess__ 只是找到一个类的直接子类,而不是继承树 - 所以它在“现实生活”中没有用 - 也许它是在 OP 掌握的特定情况下。
如果需要跨继承树查找内容,则还需要对每个子类进行递归。

至于旧式类:当然这行不通——这是它们在新代码中默认被破坏的动机之一。

至于非类属性:无论如何只能在检查实例时找到它们 - 所以必须考虑另一种方法 - 在这里似乎不是 O.P. 的关注点。

关于python - Python 中 hasattr 的倒数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16042880/

10-11 02:20