避免太快/无效重复标记的重要说明 - 请在回答前阅读。
请不要建议任何更改原始类代码的解决方案 - 不允许更改代码反射和解析。
How to read class attributes in the same order as declared?是解决方案 - 它需要替换所有类中的元类并增加开销 - 绝对不是反射使用。
考虑到我不能或不想更改代码来扫描类(class)成员顺序。类可以具有或已经具有未知的元类 - 不可能无缘无故地添加元类或增加性能开销。
只能使用反射或解析文件。
我想避免编写解析器并按声明顺序读取类属性。
在 Python 中如何使用反射(和简单的解析)?
让我举个例子:
class A(object):
b = 1
a = 1
c = 1
dir(A)
给出字母顺序,但要求是声明顺序。如何做到这一点 - 请帮忙?
最佳答案
你必须求助于解析。您不需要在这里编写解析器; ast
module可以为您做到这一点。
使用 ast.parse()
解析源代码,然后遍历生成的树:
class ClassOrder(ast.NodeVisitor):
identifiers = None
def visit_ClassDef(self, node):
self.identifiers = []
for child in node.body:
if isinstance(child, ast.Assign):
for target in child.targets:
self.visit(target)
elif isinstance(child, ast.FunctionDef):
self.identifiers.append(child.name)
def visit_Name(self, node):
if self.identifiers is not None:
self.identifiers.append(node.id)
tree = ast.parse(sourcecode)
order = ClassOrder()
order.visit(tree)
print order.identifiers
打印出所有类定义中赋值和方法的顺序。
演示:
>>> sourcecode = '''\
... class A(object):
... b = 1
... a = 1
... c = 1
... '''
>>> tree = ast.parse(sourcecode)
>>> order = ClassOrder()
>>> order.visit(tree)
>>> print order.identifiers
['b', 'a', 'c']
>>> tree = ast.parse(inspect.getsource(ast.NodeVisitor))
>>> order = ClassOrder()
>>> order.visit(tree)
>>> print order.identifiers
['visit', 'generic_visit']
使用 inspect.getsource()
捆绑为函数:
import inspect
def get_identifiers(obj):
source = inspect.getsource(obj)
tree = ast.parse(source)
order = ClassOrder()
order.visit(tree)
return order.identifiers
inspect.getsource()
可以处理任何源可用的对象。对于类,它将仅提取定义该类的源 block (如果可用)。
关于python - 如何使用反射或解析读取Python类中声明成员的顺序(禁止元类替换)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24340197/