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

前端之家收集整理的这篇文章主要介绍了递归地dir()一个python对象来查找某个类型或某个值的值前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

  1. import weakref
  2. def findWeakRef(streamObj,memo=None):
  3. weakRefList = []
  4. if memo is None:
  5. memo = {}
  6. for x in dir(streamObj):
  7. xValue = getattr(streamObj,x)
  8. if id(xValue) in memo:
  9. continue
  10. else:
  11. memo[id(xValue)] = True
  12. if type(xValue) is weakref.ref:
  13. weakRefList.append(x,xValue,streamObj)
  14. if hasattr(xValue,"__iter__"):
  15. for i in xValue:
  16. if id(i) in memo:
  17. pass
  18. else:
  19. memo[id(i)] = True
  20. weakRefList.extend(findWeakRef(i),memo)
  21. else:
  22. weakRefList.extend(findWeakRef(xValue),memo)
  23. return weakRefList

我可能会继续插入这个漏洞(例如,它不是我想要的替代词),但在我投入更多时间之前,想知道是否有人知道更简单的答案.它可能是一个非常有用的通用工具.

最佳答案
这似乎是答案的开始.我不得不从Python 3.2 inspect.getattr_static向后移植一些项目以使其工作,因此它不会调用生成新对象的属性.这是我提出的代码

  1. #-------------------------------------------------------------------------------
  2. # Name: treeYield.py
  3. # Purpose: traverse a complex datastructure and yield elements
  4. # that fit a given criteria
  5. #
  6. # Authors: Michael Scott Cuthbert
  7. #
  8. # Copyright: Copyright © 2012 Michael Scott Cuthbert
  9. # License: CC-BY
  10. #-------------------------------------------------------------------------------
  11. import types
  12. class TreeYielder(object):
  13. def __init__(self,yieldValue = None):
  14. '''
  15. `yieldValue` should be a lambda function that
  16. returns True/False or a function/method call that
  17. will be passed the value of a current attribute
  18. '''
  19. self.currentStack = []
  20. self.yieldValue = yieldValue
  21. self.stackVals = []
  22. t = types
  23. self.nonIterables = [t.IntType,t.StringType,t.UnicodeType,t.LongType,t.FloatType,t.NoneType,t.BooleanType]
  24. def run(self,obj,memo = None):
  25. '''
  26. traverse all attributes of an object looking
  27. for subObjects that meet a certain criteria.
  28. yield them.
  29. `memo` is a dictionary to keep track of objects
  30. that have already been seen
  31. The original object is added to the memo and
  32. also checked for yieldValue
  33. '''
  34. if memo is None:
  35. memo = {}
  36. self.memo = memo
  37. if id(obj) in self.memo:
  38. self.memo[id(obj)] += 1
  39. return
  40. else:
  41. self.memo[id(obj)] = 1
  42. if self.yieldValue(obj) is True:
  43. yield obj
  44. ### now check for sub values...
  45. self.currentStack.append(obj)
  46. tObj = type(obj)
  47. if tObj in self.nonIterables:
  48. pass
  49. elif tObj == types.DictType:
  50. for keyX in obj:
  51. dictTuple = ('dict',keyX)
  52. self.stackVals.append(dictTuple)
  53. x = obj[keyX]
  54. for z in self.run(x,memo=memo):
  55. yield z
  56. self.stackVals.pop()
  57. elif tObj in [types.ListType,types.TupleType]:
  58. for i,x in enumerate(obj):
  59. listTuple = ('listLike',i)
  60. self.stackVals.append(listTuple)
  61. for z in self.run(x,memo=memo):
  62. yield z
  63. self.stackVals.pop()
  64. else: # objects or uncaught types...
  65. ### from http://bugs.python.org/file18699/static.py
  66. try:
  67. instance_dict = object.__getattribute__(obj,"__dict__")
  68. except AttributeError:
  69. ## probably uncaught static object
  70. return
  71. for x in instance_dict:
  72. try:
  73. gotValue = object.__getattribute__(obj,x)
  74. except: # ?? property that relies on something else being set.
  75. continue
  76. objTuple = ('getattr',x)
  77. self.stackVals.append(objTuple)
  78. try:
  79. for z in self.run(gotValue,memo=memo):
  80. yield z
  81. except RuntimeError:
  82. raise Exception("Maximum recursion on:\n%s" % self.currentLevel())
  83. self.stackVals.pop()
  84. self.currentStack.pop()
  85. def currentLevel(self):
  86. currentStr = ""
  87. for stackType,stackValue in self.stackVals:
  88. if stackType == 'dict':
  89. if isinstance(stackValue,str):
  90. currentStr += "['" + stackValue + "']"
  91. elif isinstance(stackValue,unicode):
  92. currentStr += "[u'" + stackValue + "']"
  93. else: # numeric key...
  94. currentStr += "[" + str(stackValue) + "]"
  95. elif stackType == 'listLike':
  96. currentStr += "[" + str(stackValue) + "]"
  97. elif stackType == 'getattr':
  98. currentStr += ".__getattribute__('" + stackValue + "')"
  99. else:
  100. raise Exception("Cannot get attribute of type %s" % stackType)
  101. return currentStr

代码允许您运行以下内容

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

得到:

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

或运行:

  1. high = lambda x: isinstance(x,(int,float)) and x > 10
  2. ty = TreeYielder(high)
  3. for val in ty.run(myList):
  4. print(val,ty.currentLevel())

得到:

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

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

猜你在找的Python相关文章