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

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

我想到的一个解决方案就是这个

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

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

===============>>#1 票数:4 已采纳

它总是“可能的”。 另一个历史是可取的。

快速而肮脏的方法是在所有类上线性迭代,并检查是否有任何定义属性。 当然,这会受到冲突的影响,并且会产生具有这种命名属性的第一个类。 如果它存在于多个中,则由您自行决定您想要的内容:

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掌握的特定情况。
如果需要在继承树中查找内容,则还需要对每个子类进行递归。

对于旧式类:当然这不起作用 - 这是新代码中默认情况下被破解的动机之一。

至于非类属性:它们只能被发现检查实例 - 所以必须考虑另一种方法 - 这似乎不是OP的关注点。

===============>>#2 票数:2

这可能有所帮助:

import gc


def checker(checkee, maxdepth = 3):

    def onlyDict(ls):
        return filter(lambda x: isinstance(x, dict), ls)

    collection = []
    toBeInspected = {}
    tBI = toBeInspected
    gc.collect()
    for dic in onlyDict(gc.get_referrers(checkee)):
        for item, value in dic.iteritems():
            if value is checkee:
                collection.append(item)
            elif item != "checker":
                tBI[item] = value

    def _auxChecker(checkee, path, collection, checked, current, depth):
        if current in checked: return
        checked.append(current)
        gc.collect()
        for dic in onlyDict(gc.get_referents(current)):
            for item, value in dic.iteritems():
                currentPath = path + "." + item
                if value is checkee:
                    collection.append(currentPath)
                else:
                    try:
                        _auxChecker(checkee, currentPath, collection,
                                    checked, value, depth + 1)
                        if depth < maxdepth else None
                    except TypeError:
                        continue
    checked = []
    for item, value in tBI.iteritems():
        _auxChecker(checkee, item, collection, checked, value, 1)
    return collection

如何使用:

referrer = []

class Foo:        
        pass          

noo = Foo()       
bar = noo         
import xml        
import libxml2    
import sys        
import os         
op = os.path      
xml.foo = bar     
foobar = noo      

for x  in checker(foobar, 5):
    try:
        y= eval(x)
        referrer.append(x)
    except:
        continue

del x, y

ps:对于checkee本身的递归或嵌套引用,不会进一步检查checkee的属性。

===============>>#3 票数:1

这应该适用于所有情况,但仍需要大量测试:

import inspect
import sys


def finder(attr, classes=None):
    result = []
    if classes is None:
        # get all accessible classes
        classes = [obj for name, obj in inspect.getmembers(
            sys.modules[__name__])]
    for a_class in classes:
        if inspect.isclass(a_class):
            if hasattr(a_class, attr):
                result.append(a_class)
            else:
                # we check for instance attributes
                if hasattr(a_class(), attr):
                    result.append(a_class)
            try:
                result += finder(attr, a_class.__subclasses__())
            except:
                # old style classes (that don't inherit from object) do not
                # have __subclasses; not the best solution though
                pass
    return list(set(result))  # workaround duplicates


def main(attr):
    print finder(attr)
    return 0


if __name__ == "__main__":
    sys.exit(main("some_attr"))

  ask by Dev Maha translate from so

未解决问题?本站智能推荐:

1回复

在Python中使用hasattr而不是hasattr

我需要针对我的特定目的使用python hasattr 。 我需要检查对象是否具有属性, 而不具有其他属性。 考虑一个名为model的类对象,我需要检查它是否具有一个名为domain_id的属性: 我还需要检查另外一个条件,即该条件不应具有称为type属性。 如何在这里结
3回复

如何使用hasattr检查Python中的子模块

在运行时,Python代码获取要加载的子模块的名称,我之前不知道。 现在,我要检查此子模块是否存在于现有模块中。 考虑以下结构,可以在其中指定foo和bar : 现在,通常我会这样做,它适用于defs和变量: 或者我正在捕获AttributeError,它同样起作用。
2回复

函数'hasattr()'不能按我在Python中预期的那样工作

函数'hasattr()'不能按我在Python中预期的那样工作 我有以下代码: 当我运行它时,它给我的输出是: hasn't 。 我不知道如何检查该属性是否存在。 我试图在Brazil之前删除u ,但是它不起作用。 怎么解决呢?
2回复

Python hasattr vs getattr

我最近一直在阅读一些关于hasattr的推文和python文档 ,它说: hasattr(对象,名称) 参数是一个对象和一个字符串。 如果字符串是>>对象属性之一的名称,则结果为True,否则返回False。 (这是通过调用getattr(object,n
3回复

python hasattr()来区分方法和属性

正如一些好人告诉我callable()可以用来解决这个问题,我仍然发现它是一个不同的问题,因为任何有这个问题的人都找不到答案,因为他不会直接将它连接到callable() 。 另外,我发现了一种不使用callable()的可能方法,即使用我自己的一个答案中显示的type() 。 假设我创
2回复

可以在Python中深入研究多个孩子吗?

如果我有node.child1.child2 ,我可以有效地使用h asattr(node, 'child1.child2')吗? 如果没有child1或只是返回false,它会出错吗?
1回复

Python 3和Python 2之间的type()和hasattr()的区别

当我试图在Python 3和Python 2检查class声明的类型时,我得到了奇怪的结果,如下所示, Python 2的MyClass type是classobj而MyClass没有__call__属性。 这就是我的期望。 但是,在Python 3 , MyClass的typ
2回复

用于识别类型的hasattr()选择的Python参考

是否有一个很好的一站式Python参考,用于选择要与hasattr()一起使用以识别类型的属性。 例如,以下内容适用于不是字符串的序列: def is_sequence(arg): return (not hasattr(arg, "strip") and
5回复

在hasattr()上没有eval的Python延迟属性

当你尝试使用hasattr()访问它时,是否有可能使一个装饰器使属性变得懒惰而不是eval? 我弄清楚如何让它变得懒惰,但是hasattr()会让它过早地进行评估。 例如,
1回复

Python的hasattr有时会返回不正确的结果

为什么hasattr说实例没有foo属性? 我期望: