列出Python中子类实例的属性

时间:2017-12-10 09:24:39

标签: python introspection legacy

我试图建立一些" ORM喜欢" Python中的行为。为此,我有一个Model类,并希望生成任何类型的子类。我的问题是当我尝试列出我的子类实例的属性时。 这是我的Model类:

class Model:
    def __init__(self):
        self.className = type(self).__name__

    def listAttributes(self):
        from modules.users.user import User
        instance = User()
        meta = vars(instance)

用户子类:

class User(models.Model):
    name = models.FieldChar()
    password = models.FieldChar()
    age = models.FieldInteger()

当我从User实例调用listAttributes方法时,我没有达到我的期望,但可能我应该: meta var仅包含className 。这是我如何调用该方法:

from modules.users import user
user = user.User()
user.listAttributes()

当我覆盖User()中的listAttributes方法时的行为相同:

def listAttributes(self):
    meta = vars(self)
    print(meta)

有没有办法列出我调用listAttributes方法的对象的属性?

谢谢你的灯!

1 个答案:

答案 0 :(得分:1)

您可以将listAttributes方法设为classmethod并尝试以下操作:

class Model(object):
    @classmethod
    def listAttributes(cls):
        return [
            a for a in dir(cls) if not
            callable(getattr(cls, a)) and not 
            a.startswith("__")
        ]

如果您只想拥有“字段”类型的属性(FieldChar,FieldInt ...),那么您可以为名为的字段创建基类,例如ModelField并根据此基本类型检查您的属性:

class Model(object):
    @classmethod
    def listAttributes(cls):
        attributes = []
        for a in dir(cls):
            if ((not callable(getattr(cls, a)) and not
                 a.startswith("__") and
                 getattr(cls, a).__class__.__bases__[0] == ModelField)):
                attributes.append(a)

您甚至可以返回对象而不仅仅是名称。或者将对象附加到Model类中的dict(以便在代码中使用更容易)。我像这样构建了我的ORM:

class ModelField(object):
    ...

class IntField(ModelField):
    ...

class Model(object):
    id = IntField(pk=True)

    def __init__(self, *args, **kwargs):
        try:
            self.modelFields
        except AttributeError:
            self.__class__.introspect()
        for key, modelfield in self.modelFields.items():
            setattr(self, key, kwargs.get(key, None))

    @classmethod
    def introspect(cls):
        cls.modelFields = {}
        for a in dir(cls):
            if ((not callable(getattr(cls, a)) and not
                 a.startswith("__") and
                 getattr(cls, a).__class__.__bases__[0] == ModelField)):
                cls.modelFields[a] = getattr(cls, a)

然后我使用cls.introspect设置modelFields dict并使用此dict来例如使用ModelField类的属性自动生成db-table或构造查询。