gpt4 book ai didi

python - 如何在保留顺序的同时收集类变量

转载 作者:行者123 更新时间:2023-12-01 05:10:56 24 4
gpt4 key购买 nike

我正在尝试创建类似于 SQLAlchemy declarative_base 的架构类。模式类应该可以使用继承进行扩展。到目前为止,这是我的尝试。除了属性(类变量)按字母顺序排序之外,它工作正常。

import inspect
class BaseProp(object):
def __init__(self, name):
self.name = name
class StringProp(BaseProp): pass
class EmailProp(BaseProp): pass

class BaseSchema(object):
@classmethod
def _collect_props(cls):
prop_filter = lambda a:not(inspect.isroutine(a)) and issubclass(a.__class__, BaseProp)
return inspect.getmembers(cls, prop_filter)

@classmethod
def as_list(cls):
return cls._collect_props()

@classmethod
def as_dict(cls):
return dict(cls._collect_props())

class UserIdentSchema(BaseSchema):
email = EmailProp('email')
password = StringProp('password')

class UserProfileSchema(UserIdentSchema):
name = StringProp('name')
phone = StringProp('phone')

from pprint import pprint
pprint(UserProfileSchema.as_list())

这是结果。请注意,属性是按字母顺序排序的。

[('email', <__main__.EmailProp object at 0x10518a950>),
('name', <__main__.StringProp object at 0x10517d910>),
('password', <__main__.StringProp object at 0x10517d8d0>),
('phone', <__main__.StringProp object at 0x10517d950>)]

我希望将基本架构 Prop 放在顶部,然后将子类的 Prop 放在顶部。实现这一目标的最佳方法是什么?我必须通过 AST...吗?

编辑:我还需要保持类中属性的顺序。

最佳答案

所以这是一个可行的解决方案 - 我不保证这是值得生产的代码......例如我没有过多考虑如果您尝试将另一个(非 BaseSchema )类与 BaseSchema 混合在一起会发生什么。子类。我认为这可能有效,但你需要尝试一下才能看到......

import ast
import inspect
from collections import OrderedDict

class _NodeTagger(ast.NodeVisitor):
def __init__(self):
self.class_attribute_names = {}

def visit_Assign(self, node):
for target in node.targets:
self.class_attribute_names[target.id] = target.lineno

# Don't visit Assign nodes inside Function Definitions.
def visit_FunctionDef(self, unused_node):
return None


class BaseProp(object):
def __init__(self, name):
self.name = name


class StringProp(BaseProp): pass


class EmailProp(BaseProp): pass


class _BaseSchemaType(type):
def __init__(cls, name, bases, dct):
cls._properties = OrderedDict()
for b in bases:
# if the object has a metaclass which is this
# class (or subclass of this class...)
# then we add it's properties to our own.
if issubclass(type(b), _BaseSchemaType):
cls._properties.update(b._properties)

# Finally, we add our own properties. We find our own source code
# read it and tag the nodes where we find assignment.
source = inspect.getsource(cls)
nt = _NodeTagger()
nt.visit(ast.parse(source))
attr_names = nt.class_attribute_names
properties = {n: prop for n, prop in dct.items()
if isinstance(prop, BaseProp)}
sorted_attrs = sorted(properties.items(),
key=lambda item: attr_names[item[0]])
cls._properties.update(sorted_attrs)

# methods on a metaclass are basically just classmethods ...
def as_list(cls):
return list(cls._properties.items())

def as_dict(cls):
return cls._properties.copy()


class BaseSchema(object):
__metaclass__ = _BaseSchemaType

class UserIdentSchema(BaseSchema):
email = EmailProp('email')
password = StringProp('password')

class UserProfileSchema(UserIdentSchema):
name = StringProp('name')
phone = StringProp('phone')

from pprint import pprint
pprint(UserProfileSchema.as_list())

对元类感到抱歉——但它确实让事情变得更容易。现在,当类被导入时,所有的魔法都发生了——每次调用 as_list 时都不会出现困惑的内省(introspection)。 。它还使我能够快速访问该类的属性以及我需要从 __dict__ 中提取的基础。和__bases__否则(或从 inspect 中找出)。

关于python - 如何在保留顺序的同时收集类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24236420/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com