Python:如何使用元组多赋值功能进行重载?

10

所以我自己创建了一个基于字典的命名元组类:

class t(dict):
   def __getattr__(self, v):
      try:
         return self[v]
      except KeyError:
         raise AttributeError("Key " + str(v) + " does not exist.")
   def __init__(self, *args, **kwargs):
      for source in args:
         for i, j in source.items():
            self[i] = j
      for i, j in kwargs.items():
         self[i] = j

>>> thing = t(cow=10, moo='moooooooo')
>>> thing.cow
10
>>> thing.moo
'moooooooo'

使用字典的目的是为了能够使用**扩展运算符,同时整个内容可以作为字典进行JSON序列化。在init中的双重循环是为了在反序列化后立即从字典中重新构建它。
我唯一缺少的就是元组可以进行的多重赋值操作,例如:
>>> thing = (1, 3, ('blargh', 'mooo'))
>>> a, b, (c, d) = thing
>>> a
1
>>> b
3
>>> c
'blargh'
>>> d
'mooo'

我能否用自定义数据类型获得这种行为?有没有可以覆盖的函数或者可以继承的类来实现这种行为?


3
您想要对一个无序类型进行位置扩展吗? - Ignacio Vazquez-Abrams
1
“你可以使用元组进行的多重赋值操作” - 顺便说一下,这被称为“解包”。 - detly
嗯,我想我可以使用有序类型,比如OrderedDict,或者以某种方式定义自己的任意顺序。不过这可行吗? - Li Haoyi
需要记住的一件事是元组维护顺序,而字典则不然——所以如果你真的想要一个元组的替换类,你需要考虑这一点。 - Ethan Furman
1个回答

12

可以。实现__iter__()方法。

class unpackable_dict(dict):
    def __iter__(self):
        return (self[key] for key in sorted(self.keys()))

d = unpackable_dict(a=1, b=2)
a, b = d

通常情况下,你不能像从元组中那样从字典中解包值的原因是字典没有定义的顺序。我使用了一个生成器表达式以按其键的排序顺序获取项目。不过,你可能会考虑改用一个 OrderedDict


你可以解包一个字典:它会以未定义的顺序解开键。但这样做并没有多大意义。 - Peter Graham
按键排序可能更有意义。def __iter__(self): return (value for key, value in sorted(d.items(), key=lambda i: i[0])) 如果按值排序,顺序将根据值的不同而改变。按键排序将为具有相同键的不同t提供相同的顺序。 - Peter Graham
排序需要按照原始添加顺序进行,以保持元组属性。 - Ethan Furman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接