如何从内置类型派生时设置“the”值?

时间:2017-01-29 07:58:30

标签: python python-2.7

我(尝试)做一些元编程,事情似乎正在发挥作用,直到我尝试做一套。

class MetaField(type):

    def __new__(meta, clsname, bases, attrs):
        bases = (Field,) + bases
        return super(MetaField, meta).__new__(meta, clsname, bases, attrs)

    def __call__(cls, *args, **kw):
        cls._primary_key = kw.pop('primary_key', False)
        return super(MetaField, cls).__call__(*args, **kw)

class Field(object):

    def __new__(cls, *args, **kw):
        return super(Field, cls).__new__(cls, *args)

    #def __set__(self, instance, value):
    #    magic needs to go here

    #def __get__(self, instance, owner):
    #    more magic here

    @property
    def primary_key(self):
        return self._primary_key

class IntField(int):
    __metaclass__ = MetaField

class SomeObject(object):
    # trying with descriptors here
    i = IntField(10, primary_key=True, foo='set')


obj = SomeObject()
assert obj.i == 10
assert obj.i.primary_key == True

obj.i = 11
assert obj.i == 11

assert obj.i.primary_key == True
AttributeError: 'int' object has no attribute 'primary_key'

这是有道理的,因为obj.i不再是IntField,而是普通int

所以在Field.__set__如果我可以做的话 super(self) = value selfIntField仍然是超级ProxyFieldDescriptor 骗子。

我已经尝试按照中所述实现__get__ http://blog.kevinastone.com/django-model-descriptors.html但是当您从_primary_key返回时,您会丢失所有补充信息,例如int

如何在派生类中设置data-ng-options的实际值?

2 个答案:

答案 0 :(得分:1)

首先,如果您在生产代码上执行此操作,您可能应该在开发人员中烧掉地狱。其次,这是你要做的事情:

class MetaField(type):
    def __new__(meta, clsname, bases, attrs):
        bases = (Field,) + bases
        return super(MetaField, meta).__new__(meta, clsname, bases, attrs)

    def __call__(cls, *args, **kw):
        cls._primary_key = kw.pop('primary_key', False)
        cls._name = kw.pop('name')
        return super(MetaField, cls).__call__(*args, **kw)


class Field(object):

    def __getattr__(self, item):
        if item == 'primary_key':
            return self._primary_key
        else:
            return self.__dict__[item]

    def __set__(self, instance, value):
        instance.__dict__[self._name] = IntField(value, primary_key=self.primary_key, name=self._name)


class IntField(int):
    __metaclass__ = MetaField


class SomeObject(object):
    # trying with descriptors here
    i = IntField(10, primary_key=True, name='i')


if __name__ == '__main__':
    obj = SomeObject()
    assert obj.i == 10
    assert obj.i.primary_key == True

    obj.i = 11
    assert obj.i == 11

    assert obj.i.primary_key == True
# g2g

这里的关键是,与描述符的情况一样,你需要命名它们。如果您没有为它们命名,则在您需要设置/获取实例变量时无法访问实例变量。如果这不是问题,则不需要名称。但在这种情况下,你做到了。我做了必要的调整。

虽然我确信你很清楚这一点,但你可以通过更轻松的方式来完成你想要完成的事情......这是黑暗面的道路。

答案 1 :(得分:0)

这是__init__方法的工作。它充当构造函数,并在将类实例化为对象时调用。

  class A:
    def __init__(self, x, y):
      self.x = x
      self.y = y

  a = A(5, 6)
  assert a.x == 5 and a.y == 6

您定义事物的方式,那些是类属性,并且与特定实例无关。