Python 在从Django'派生的类上使用uuu new uuu;s模型不起作用
这件事让我感到困惑,但我无法得到一个明确的答案。在从DJango模型派生的类中使用Python 在从Django'派生的类上使用uuu new uuu;s模型不起作用,python,django,django-models,Python,Django,Django Models,这件事让我感到困惑,但我无法得到一个明确的答案。在从DJango模型派生的类中使用\uuuu new\uuu方法(或者更准确地说,静态方法) 这就是理想情况下应该如何使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(因为我们使用的是Django,所以我们可以假设使用的是python的2 实例化上述类中的对象的工作方式与预期相同。现在,当我们在从Django模型派生的类上尝试类似的方法时,会发生意想不到的事情: clas
\uuuu new\uuu
方法(或者更准确地说,静态方法)
这就是理想情况下应该如何使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
(因为我们使用的是Django,所以我们可以假设使用的是python的2
实例化上述类中的对象的工作方式与预期相同。现在,当我们在从Django模型派生的类上尝试类似的方法时,会发生意想不到的事情:
class Test(models.Model):
def __new__(self, *args, **kwargs):
return super(Test, self).__new__(self, *args, **kwargs)
实例化上述类中的对象会导致此错误:
TypeError:必须使用测试实例作为第一个参数调用未绑定的方法\uuuuu new\uuuuuu()(改为使用ModelBase实例)
我不明白为什么会发生这种情况(尽管我知道由于Django框架,一些类魔术正在幕后发生)
任何答案都将不胜感激。
\uuu new\uuu
不接收实例作为其第一个参数。当(a)它是一个静态方法,正如您所注意到的,(b)它的工作是创建一个实例并返回它时,它怎么可能呢!\uuuu new\uuuu
的第一个参数通常称为cls
,因为它是类
这使得您引用的错误消息非常奇怪;它通常是调用未绑定方法时得到的错误消息(即通过访问ClassName.methodName
)而不是将该类的实例作为self
参数。但是,staticmethods(包括\uuuuu new\uuuu
)并不是未绑定的方法,它们只是碰巧是类属性的简单函数:
>>> class Foo(object):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
def method(self):
pass
>>> class Bar(object):
pass
>>> Foo.method
<unbound method Foo.method>
>>> Foo.__new__
<function __new__ at 0x0000000002DB1C88>
>>> Foo.method(Bar())
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
Foo.method(Bar())
TypeError: unbound method method() must be called with Foo instance as first argument (got Bar instance instead)
>>> Foo.__new__(Bar)
<__main__.Bar object at 0x0000000002DB4F28>
(attrs
是包含类块中所有定义的字典,包括\uuuuu new\uuuuu
函数;add\u to\u class
是一个元类方法,主要是setattr
)
我现在99%确定问题在这里,因为\uuuu new\uuu
是一种奇怪的隐式静态方法。因此,与其他静态方法不同,您没有对其应用staticmethod
decorator。Python(在某种程度上)只识别\uuuu new\uuu
方法,并将其作为静态方法处理,而不是普通方法[1]。但我敢打赌,只有在类块中定义\uuuu new\uuuu
时才会发生这种情况,而不是在使用setattr
进行设置时
因此,您的\uuuuu new\uuuuu
,应该是一个静态方法,但尚未由staticmethod
decorator处理,正在转换为一个普通实例方法。然后,当Python调用它通过类测试
时,按照正常的实例创建协议,它会抱怨没有得到测试
的实例
如果这些都是正确的,那么:
\uuuu new\uuuu
是静态的不一致性@staticmethod
应用到您的\uuuuuuuuuuuu新的\uuuuuuuuuuu
方法来实现这一点,即使您不必这样做[1] 我相信这是Python的一个历史怪癖,因为
\uuuuuuuuuuuuuuuuuuuuuu
是在staticmethod
decorator之前引入的,但\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
不能以一个实例为例,因为没有实例可以调用它。。在最后一段代码中,应该是test
还是test
?另外,缩进已关闭。是的,return super(test,self).
应该是return super(test,sefl).
。大家好,对不起,我在编辑器中很快输入了示例(我没有在那里复制和粘贴代码)-因此,对于错误,我深表歉意。即使考虑到你上面的两条评论,它仍然不起作用。顺便说一句:我已经修复了上面的代码片段。models.Model.\uuuuu new\uuuuu(Test,*args,**kwargs)
有效吗?不幸的是,我仍然收到相同的错误:(非常好,谢谢Ben。这正是我一直在寻找的答案。当我使用静态装饰器时,它现在工作得非常好。\uuuu new\uuuuu
也可以是classmethod
@J.F.Sebastian:从某种意义上说,它显然应该是一个classmethod,从逻辑上看。无论多么正常的\uu new\uu
方法都是最确定的ly不是类方法,它们是静态方法。这也是一个历史怪癖,因为\uuuuu new\uuuuu
早于类方法
装饰器。鉴于\uuuuu new\uuuuuu
已经是“特殊的”,并且是Python OO模型的核心所依赖的,我不会尝试在生产代码中使用类方法,尽管它可以我做得很好。@Ben:这是对“必须是静态的”的评论,也就是说,\uuuu new\uuuu
是一种静态方法
,但也可以是类方法
。BDFL说\uu new\uuuuuuuuu
是类方法
出现的原因。@J.F.Sebastian啊!我用“静态”的意思只是“不作用于实例”在那句话里,你说得很对,让人困惑。我已经改写了。
>>> class Foo(object):
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
def method(self):
pass
>>> class Bar(object):
pass
>>> Foo.method
<unbound method Foo.method>
>>> Foo.__new__
<function __new__ at 0x0000000002DB1C88>
>>> Foo.method(Bar())
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
Foo.method(Bar())
TypeError: unbound method method() must be called with Foo instance as first argument (got Bar instance instead)
>>> Foo.__new__(Bar)
<__main__.Bar object at 0x0000000002DB4F28>
# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)