kwargs 覆盖 dict 子类
kwargs overriding dict subclass
一个最小的例子如下:
class sdict(dict):
class dval:
def __init__(self, val):
self.val = val
def __init__(self, args):
dictionary = dict(args)
for k,v in dictionary.items():
self[k] = v
def __setitem__(self,key,value):
try: self[key].val = value
except KeyError: dict.__setitem__(self,key,self.dval(value))
def __getitem__(self,key):
return dict.__getitem__(self,key).val
现在我可以在容器中使用这个 class 来覆盖赋值内容:
class cont(object):
def __init___(self):
self._mydict = sdict(())
@property
def mydict(self):
return self._mydict
@mydict.setter
def mydict(self,dict_initializor):
self._mydict = sdict(dict_initializor)
return self.mydict
我使用它,所以我的容器包含一个带有可指向基元的字典(即在 python 语言中可变),但每当我检索项目时,我都会得到基元本身。在我的例子中,浮点数,我乘以,添加等...添加 __str__/__repr__ 函数可以使它在打印这些时起作用,但出于调试目的,这些被省略了。
这几乎在任何地方都能很好地工作,除非使用 kwargs 传递它:
def test(a,b): return a*b
c = cont()
c.mydict = {'a':1,'b':2}
print c.mydict['a']+c.mydict['b'],type(c.mydict['a']+c.mydict['b'])
print test(**c.mydict)
输出:
3 <type 'int'>
Traceback (most recent call last):
File "D:\kabanus\workspace\py-modules\test.py", line 32, in <module>
print test(**c.mydict)
File "D:\kabanus\workspace\py-modules\test.py", line 28, in test
def test(a,b): return a*b
TypeError: unsupported operand type(s) for *: 'instance' and 'instance'
显然解包过程不使用__getitem__ 来为关键字创建值。我还试图覆盖 values() 和 items() 但没有成功。接下来我将所有未定义的字典方法设置为 None 以查看是否调用了任何方法 - 也没有成功。
底线 - 你如何获得 **kwargs 解包以使用 __getitem__ 或其他一些方法?
这可能吗?
我还想尽可能避免在 class dval 中定义 mul、add、div 等。
在这里找到了答案,并且应该有一种方法可以使它更容易找到:
Does argument unpacking use iteration or item-getting?
总结:
从内置函数 (dict,list...) 继承是有问题的,因为 python 可能会完全忽略你的 python API (就像它对我所做的那样)并使用底层 C。这发生在参数中开箱.
解决方案:使用可用的抽象。在我的示例中添加:
from UserDict import UserDict
并将代码中出现的所有 "dict" 处替换为 UserDict。这个解决方案应该适用于列表和元组。
一个最小的例子如下:
class sdict(dict):
class dval:
def __init__(self, val):
self.val = val
def __init__(self, args):
dictionary = dict(args)
for k,v in dictionary.items():
self[k] = v
def __setitem__(self,key,value):
try: self[key].val = value
except KeyError: dict.__setitem__(self,key,self.dval(value))
def __getitem__(self,key):
return dict.__getitem__(self,key).val
现在我可以在容器中使用这个 class 来覆盖赋值内容:
class cont(object):
def __init___(self):
self._mydict = sdict(())
@property
def mydict(self):
return self._mydict
@mydict.setter
def mydict(self,dict_initializor):
self._mydict = sdict(dict_initializor)
return self.mydict
我使用它,所以我的容器包含一个带有可指向基元的字典(即在 python 语言中可变),但每当我检索项目时,我都会得到基元本身。在我的例子中,浮点数,我乘以,添加等...添加 __str__/__repr__ 函数可以使它在打印这些时起作用,但出于调试目的,这些被省略了。
这几乎在任何地方都能很好地工作,除非使用 kwargs 传递它:
def test(a,b): return a*b
c = cont()
c.mydict = {'a':1,'b':2}
print c.mydict['a']+c.mydict['b'],type(c.mydict['a']+c.mydict['b'])
print test(**c.mydict)
输出:
3 <type 'int'>
Traceback (most recent call last):
File "D:\kabanus\workspace\py-modules\test.py", line 32, in <module>
print test(**c.mydict)
File "D:\kabanus\workspace\py-modules\test.py", line 28, in test
def test(a,b): return a*b
TypeError: unsupported operand type(s) for *: 'instance' and 'instance'
显然解包过程不使用__getitem__ 来为关键字创建值。我还试图覆盖 values() 和 items() 但没有成功。接下来我将所有未定义的字典方法设置为 None 以查看是否调用了任何方法 - 也没有成功。
底线 - 你如何获得 **kwargs 解包以使用 __getitem__ 或其他一些方法?
这可能吗?
我还想尽可能避免在 class dval 中定义 mul、add、div 等。
在这里找到了答案,并且应该有一种方法可以使它更容易找到: Does argument unpacking use iteration or item-getting?
总结: 从内置函数 (dict,list...) 继承是有问题的,因为 python 可能会完全忽略你的 python API (就像它对我所做的那样)并使用底层 C。这发生在参数中开箱.
解决方案:使用可用的抽象。在我的示例中添加:
from UserDict import UserDict
并将代码中出现的所有 "dict" 处替换为 UserDict。这个解决方案应该适用于列表和元组。