Python:如何从另一个属性的对象中读取属性?

时间:2014-08-08 22:37:32

标签: python sqlalchemy

我不知道如何找到这个,这是一个简化的例子

我有一个班级:

class MyField():

    def __init__(self, model=None, source=None, id=None):
        self.source = source
        self.model = model
        self.id = id

    def somemethod(self):
        ...

用于其他课程

class MyClass(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    somefield = db.Column(db.String(255))

    @property
    def someproperty(self):

        specs = MyField(
            source=self.somefield,
            model=self.__class__.__name__,
            id=self.id
        )

        return specs.somemethod()

这对我来说并不理想,我希望为第二类编写更简单的代码,所以让它看起来像这样:

class MyClass(db.Model):
    somefield = db.Column(db.String(255))

    someproperty = MyField(source='somefield')

并在第一个类上拥有处理该数据的所有逻辑。在这里我不知道如何阅读'somefield'和id的内容,'somefield'可能会有所不同,并且有另一个名字,这就是为什么我用它作为参数,'id'对每个类来说都是一样的

1 个答案:

答案 0 :(得分:1)

@property所做的只是返回__get__方法调用您的函数的自定义descriptor。所以,你可以直接这样做。

我无法对此进行测试,因为我在这里没有安装sqlalchemy,但是这样的话:

class FieldProperty(object):
    def __init__(self, field, source):
        self.field, self.source = field, source
    def __get__(self, obj, typ=None):
        if typ is None:
            typ = obj.__class__
        specs = self.field(
            source = getattr(obj, self.source),
            model = typ.__name__,
            id = obj.id)
        return specs.somemethod()

现在:

class MyClass(db.Model):
    somefield = db.Column(db.String(255))

    someproperty = FieldProperty(MyField, source='somefield')

或者,如果您愿意,可以为所有字段创建基类或mixin,以添加为您执行此操作的类方法:

class BaseField(object):
    @classmethod
    def make_property(cls, source):
        return FieldProperty(cls, source)

现在:

class MyClass(db.Model):
    somefield = db.Column(db.String(255))

    someproperty = MyField.make_property('somefield')

请注意上面的FieldProperty(object)。描述符必须是新式类,它们只能用于新式类。在Python 3.x中,新的类就是它们,但是如果你使用2.x,那么每次定义一个没有基类的类时,你就会得到一个旧式的类。这只是你不想要一个旧式课程的众多原因之一;他们还处理一些错误的特殊方法,打破多重继承,让你看起来像一个复古的时髦,潜入你的房间,在你睡觉时偷钱从你的钱包里。