递归地dir()一个python对象来查找某个类型或某个值的值

递归地dir()一个python对象来查找某个类型或某个值的值,第1张

概述我有一个复杂的Python数据结构(如果它很重要,它是一个很大的music21 Score对象),由于在对象结构内部某处存在弱化,它不会发痒.我以前用堆栈跟踪和python调试器调试过这样的问题,但总是很痛苦.是否有一个工具以递归方式对对象的所有属性运行dir(),查找隐藏在列表,元组,dicts等中的对象,并返回与特定值匹配的那些(lambda函数或类似的

我有一个复杂的Python数据结构(如果它很重要,它是一个很大的music21 score对象),由于在对象结构内部某处存在弱化,它不会发痒.我以前用堆栈跟踪和python调试器调试过这样的问题,但总是很痛苦.是否有一个工具以递归方式对对象的所有属性运行dir(),查找隐藏在列表,元组,dicts等中的对象,并返回与特定值匹配的那些(lambda函数或类似的东西).一个很大的问题是递归引用,因此需要某种备忘录函数(如copy.deepcopy使用).我试过了:

import weakrefdef finDWeakRef(streamObj,memo=None):    weakRefList = []    if memo is None:        memo = {}    for x in dir(streamObj):        xValue = getattr(streamObj,x)        if ID(xValue) in memo:            continue        else:            memo[ID(xValue)] = True        if type(xValue) is weakref.ref:            weakRefList.append(x,xValue,streamObj)        if hasattr(xValue,"__iter__"):            for i in xValue:                if ID(i) in memo:                    pass                else:                    memo[ID(i)] = True                    weakRefList.extend(finDWeakRef(i),memo)        else:            weakRefList.extend(finDWeakRef(xValue),memo)    return weakRefList

我可能会继续插入这个漏洞(例如,它不是我想要的替代词),但在我投入更多时间之前,想知道是否有人知道更简单的答案.它可能是一个非常有用的通用工具.最佳答案这似乎是答案的开始.我不得不从Python 3.2 inspect.getattr_static向后移植一些项目以使其工作,因此它不会调用仅生成新对象的属性.这是我提出的代码:

#-------------------------------------------------------------------------------# name:         treeYIEld.py# Purpose:      traverse a complex datastructure and yIEld elements#               that fit a given criteria## Authors:      Michael Scott Cuthbert## copyright:    copyright © 2012 Michael Scott Cuthbert# license:      CC-BY#-------------------------------------------------------------------------------import typesclass TreeYIElder(object):    def __init__(self,yIEldValue = None):        '''        `yIEldValue` should be a lambda function that        returns True/False or a function/method call that        will be passed the value of a current attribute        '''                self.currentStack = []        self.yIEldValue = yIEldValue        self.stackVals = []        t = types        self.nonIterables = [t.IntType,t.StringType,t.UnicodeType,t.LongType,t.floatType,t.nonetype,t.BooleanType]    def run(self,obj,memo = None):        '''        traverse all attributes of an object looking        for subObjects that meet a certain criteria.        yIEld them.        `memo` is a dictionary to keep track of objects        that have already been seen        The original object is added to the memo and        also checked for yIEldValue        '''        if memo is None:            memo = {}        self.memo = memo        if ID(obj) in self.memo:            self.memo[ID(obj)] += 1            return        else:            self.memo[ID(obj)] = 1        if self.yIEldValue(obj) is True:            yIEld obj        ### Now check for sub values...        self.currentStack.append(obj)        tObj = type(obj)        if tObj in self.nonIterables:            pass        elif tObj == types.DictType:            for keyX in obj:                dictTuple = ('dict',keyX)                self.stackVals.append(dictTuple)                x = obj[keyX]                for z in self.run(x,memo=memo):                    yIEld z                self.stackVals.pop()        elif tObj in [types.ListType,types.TupleType]:            for i,x in enumerate(obj):                ListTuple = ('Listlike',i)                self.stackVals.append(ListTuple)                for z in self.run(x,memo=memo):                    yIEld z                self.stackVals.pop()        else: # objects or uncaught types...            ### from http://BUGs.python.org/file18699/static.py            try:                instance_dict = object.__getattribute__(obj,"__dict__")            except AttributeError:                ## probably uncaught static object                return            for x in instance_dict:                try:                    gotValue = object.__getattribute__(obj,x)                except: # ?? property that relIEs on something else being set.                    continue                objTuple = ('getattr',x)                self.stackVals.append(objTuple)                try:                    for z in self.run(gotValue,memo=memo):                        yIEld z                except RuntimeError:                    raise Exception("Maximum recursion on:\n%s" % self.currentLevel())                self.stackVals.pop()                        self.currentStack.pop()    def currentLevel(self):        currentStr = ""        for stackType,stackValue in self.stackVals:            if stackType == 'dict':                if isinstance(stackValue,str):                    currentStr += "['" + stackValue + "']"                elif isinstance(stackValue,unicode):                    currentStr += "[u'" + stackValue + "']"                else: # numeric key...                    currentStr += "[" + str(stackValue) + "]"            elif stackType == 'Listlike':                currentStr += "[" + str(stackValue) + "]"            elif stackType == 'getattr':                currentStr += ".__getattribute__('" + stackValue + "')"            else:                raise Exception("Cannot get attribute of type %s" % stackType)        return currentStr

此代码允许您运行以下内容:

class Mock(object):    def __init__(self,mockThing,embedMock = True):        self.abby = 30        self.mocker = mockThing        self.mockList = [mockThing,40]        self.embeddedMock = None        if embedMock is True:            self.embeddedMock = Mock(mockThing,embedMock = False)mockType = lambda x: x.__class__.__name__ == 'Mock'subList = [100,60,-2]myList = [5,20,[5,12,17],30,{'hello': 10,'goodbye': 22,'mock': Mock(subList)},-20,Mock(subList)]myList.append(myList)ty = TreeYIElder(mockType)for val in ty.run(myList):    print(val,ty.currentLevel())

得到:

(<__main__.Mock object at 0x01DEBD10>,"[4]['mock']")(<__main__.Mock object at 0x01DEF370>,"[4]['mock'].__getattribute__('embeddedMock')")(<__main__.Mock object at 0x01DEF390>,'[6]')(<__main__.Mock object at 0x01DEF3B0>,"[6].__getattribute__('embeddedMock')")

或运行:

high = lambda x: isinstance(x,(int,float)) and x > 10ty = TreeYIElder(high)for val in ty.run(myList):    print(val,ty.currentLevel())

得到:

(20,'[1]')(12,'[2][1]')(17,'[2][2]')(30,'[3]')(22,"[4]['goodbye']")(100,"[4]['mock'].__getattribute__('embeddedMock').__getattribute__('mocker')[0]")(60,"[4]['mock'].__getattribute__('embeddedMock').__getattribute__('mocker')[1]")(40,"[4]['mock'].__getattribute__('embeddedMock').__getattribute__('mockList')[2]")

我还在试图找出为什么没有找到.abby,但我认为即使在这一点上它也值得发布,因为它比我开始时的正确轨道要多得多. 总结

以上是内存溢出为你收集整理的递归地dir()一个python对象来查找某个类型或某个值的值全部内容,希望文章能够帮你解决递归地dir()一个python对象来查找某个类型或某个值的值所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1205451.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存