4

hasattr(obj, attribute)オブジェクトが指定された属性を持っているかどうかを確認するために使用されますが、属性が与えられた場合、それが定義されている場所 (すべて) を知る方法はありますか?

コードが属性 (またはクラスメソッド) の名前を文字列として取得していて、呼び出したいのですclassname.attributeが、クラス名がないとします。

私の頭に浮かぶ1つの解決策はこれです

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

これが最善の方法ではないことは確かです(適切な方法であっても)。誰かがより良い方法を提供してください。

4

3 に答える 3

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: チェック対象自体への再帰的またはネストされた参照については、チェック対象の属性はそれ以上チェックされません。

于 2013-04-16T17:24:08.520 に答える
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"))
于 2013-04-16T17:39:45.680 に答える