[英]how do you set "the" value when deriving from built-in type?
I'm (trying) to do some meta programming and things seem to be working until I try to do a set.我正在(尝试)做一些元编程,在我尝试做一组之前,事情似乎一直在工作。
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'
Which makes sense since obj.i
is no longer a IntField
but a plain int
.这是有道理的,因为obj.i
不再是一个IntField
而是一个普通的int
。
So in Field.__set__
if I could do something along the lines of super(self) = value
but have self
still be a IntField
that'd be super duper.因此,在Field.__set__
如果我可以按照super(self) = value
做一些事情,但让self
仍然是一个IntField
,那将是超级IntField
。
I've tried to implement a ProxyFieldDescriptor
as described at http://blog.kevinastone.com/django-model-descriptors.html but when you return from __get__
you loose all your supplementary info like _primary_key
.我试图实现一个ProxyFieldDescriptor
,如http://blog.kevinastone.com/django-model-descriptors.html所述,但是当您从__get__
返回时,您会丢失所有补充信息,例如_primary_key
。
How do you set the actual value of int
from within a derived class?如何从派生类中设置int
的实际值?
First and foremost, you should probably burn in developer hell if you ever do this on production code.首先,如果你曾经在生产代码上这样做,你可能应该在开发人员地狱中燃烧。 Secondly, here's what you're trying to do:其次,这是你想要做的:
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
The key here is, as is often the case with descriptors, you need to name them.这里的关键是,就像描述符的情况一样,您需要为它们命名。 If you don't name them, there's no way to access the instance variable in the event you need to set/get with it.如果您不命名它们,则在需要设置/获取实例变量时无法访问实例变量。 If that's not an issue, you don't need a name.如果这不是问题,则不需要名称。 But in this case you do.但在这种情况下,你会这样做。 I made the necessary adjustments.我做了必要的调整。
Although I'm sure you're well aware of this there are way easier ways to do what you're trying to accomplish... this is the path of the dark side.虽然我相信你很清楚这一点,但有更简单的方法来完成你想要完成的事情……这是黑暗面的道路。
This is a job for the __init__
method.这是__init__
方法的工作。 It acts as a constructor and is called when your class is instantiated as an object.它充当构造函数,并在您的类实例化为对象时调用。
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
The way you were defining things, those were class attributes and were not associated with particular instances.您定义事物的方式是类属性,与特定实例无关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.