【问题标题】:kwargs overriding dict subclasskwargs 覆盖 dict 子类
【发布时间】:2016-10-15 14:15:37
【问题描述】:

一个最小的例子如下:

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 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() 但没有成功。接下来,我将所有未定义的 dict 方法设置为 None 以查看是否调用了任何方法 - 也没有成功。

底线 - 如何让 **kwargs 解包以使用 __getitem__ 或其他方法?
这甚至可能吗?

如果可能的话,我还想避免在类 dval 中定义 mul、add、div 等。

【问题讨论】:

  • 您是否有任何理由要使用dval 而不是直接将值设置为整数?
  • 是的 - 我想要这些项目的只读指针。我没有发布完整的代码,我坚持认为这不相关,但是还有另一个名为 dview 的内部类,它有一个 val 属性,它返回指向的整数,并且不允许设置。

标签: python dictionary keyword-argument


【解决方案1】:

在这里找到了答案,应该有一种方法可以更容易找到: Does argument unpacking use iteration or item-getting?

总结: 从 builtins (dict,list...) 继承是有问题的,因为 python 可能会完全忽略您的 python API(就像它对我所做的那样)并使用底层 C。这发生在参数解包中。

解决方案:使用可用的抽象。在我的示例中添加:

from UserDict import UserDict

并将代码中出现的所有“dict”替换为 UserDict。这个解决方案应该适用于列表和元组。

【讨论】:

    猜你喜欢
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    相关资源
    最近更新 更多