我试图理解为什么显式指定签名参数不起作用,而只是盲目地执行*args,**kwargs有效!我真的看不出这两者有多大区别?
不起作用的例子:
from django.db.models import CharField as _CharField
class CharField(_CharField):
def get_db_prep_value(self, value, connection, prepared=False):
if self.blank == self.null == self.unique == True and value == '':
value = None
return super(CharField, self).get_db_prep_value(value, connection, prepared) # <--- this does not work!我得到了以下错误:
File "/home/googledroid/Workspace/eclipse/gameproject/virtualenv/lib/python2.6/site-packages/django/db/models/fields/__init__.py", line 276, in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False)
File "/home/googledroid/Workspace/eclipse/gameproject/virtualenv/lib/python2.6/site-packages/django/db/models/fields/subclassing.py", line 53, in inner
return func(*args, **kwargs)
File "/home/googledroid/Workspace/eclipse/gameproject/src/fields/__init__.py", line 13, in get_db_prep_value
return super(CharField, self).get_db_prep_value(value, connection, prepared)
File "/home/googledroid/Workspace/eclipse/gameproject/virtualenv/lib/python2.6/site-packages/django/db/models/fields/subclassing.py", line 53, in inner
return func(*args, **kwargs)
File "/home/googledroid/Workspace/eclipse/gameproject/virtualenv/lib/python2.6/site-packages/django/db/models/fields/subclassing.py", line 53, in inner
return func(*args, **kwargs)
TypeError: get_db_prep_value() got multiple values for keyword argument 'connection'虽然这个很好用:
from django.db.models import CharField as _CharField
class CharField(_CharField):
def get_db_prep_value(self, value, *args, **kwargs):
if self.blank == self.null == self.unique == True and value == '':
value = None
return super(CharField, self).get_db_prep_value(value, *args, **kwargs) 在django source,django.db.models.subclassing.call_with_connection_and_prepared.inner()中,我看到有一些kwargs的删除,但不完全确定为什么?
发布于 2011-08-16 01:32:52
问题是,connection参数应该始终作为关键字参数传入。django.db.models.fields.subclassing中的代码只检查它是否存在于kwargs字典中,如果不存在,它将发出一个DeprecationWarning并将其添加到其中。位置参数不会被检查,所以最后发生的事情是,您传递的位置参数都会被转发,但函数包装器默认提供的关键字参数也会被传入。这就是冲突的原因。
要让你的代码正常工作,你需要做的就是:
return super(CharField, self).get_db_prep_value(value, connection=connection, prepared=prepared)仅供参考,在开发版本中,所有这些包装器都被删除了,这意味着您当前的代码可能会对主干起作用。但是,最好将参数保留在kwargs中。
发布于 2011-08-16 01:36:19
我没有可用的django源代码,所以这只是一个猜测:
请注意,根据Bar和Baz中的调用签名,传递给Foo的内容会有所不同
class Foo(object):
def get_db_prep_value(self,*args,**kwargs):
print(args,kwargs)
class Bar(Foo):
def get_db_prep_value(self,value,connection,prepared=False):
super(Bar,self).get_db_prep_value(value,connection,prepared)
class Baz(Foo):
def get_db_prep_value(self,*args,**kwargs):
super(Baz,self).get_db_prep_value(*args,**kwargs)
bar=Bar()
bar.get_db_prep_value(1,2,prepared=True)
# ((1, 2, True), {})
baz=Baz()
baz.get_db_prep_value(1,2,prepared=True)
# ((1, 2), {'prepared': True})当您使用
super(Bar,self).get_db_prep_value(value,connection,prepared)prepared被传递到位置参数列表args中。
但是当你使用
super(Baz,self).get_db_prep_value(*args,**kwargs)prepared被传递到关键字dict kwargs中。
发布于 2011-08-16 03:28:59
对于使用"double splat“语法定义的函数(我称之为”double splat“),调用者必须显式为每个关键字参数提供字典键。我敢打赌,get_db_prep_value的定义与下面的第一个函数类似。
def usessplat(**kwargs):
print 'connection = ' + kwargs.get('connection', 'None')
def nosplat(connection=None)
print 'connection = ' + str(connection)
usessplat('foo') # raises TypeError
nosplat('foo') # no exceptionhttps://stackoverflow.com/questions/7068057
复制相似问题