如果要转换为序列或映射,该类将进行不同的转换

时间:2019-07-04 07:39:19

标签: python class dictionary tuples

考虑以下玩具类:

class Something(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        yield ('a', self.a)
        yield ('b', self.b)

x = Something(1, 2)

print(tuple(x))
# (('a', 1), ('b', 2))
print(dict(x))
# {'a': 1, 'b': 2}

但是,我希望它的行为如下:

print(tuple(x))
# (1, 2)
print(dict(x))
# {'a': 1, 'b': 2}

我该怎么办?


编辑

我很清楚这可以明确实现,例如(遵循dict()命名约定):

class Something(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def items(self):
        yield ('a', self.a)
        yield ('b', self.b)

    def values(self):
        yield self.a
        yield self.b

但是很明显,某些对象分别转换为dict()tuple()时的行为确实有所不同。例如,dict()本身的行为(例如collections.OrderedDictcollections模块中的其他映射)的行为也类似(使用 keys 我想获得 values )很好:

import collections

dd = collections.OrderedDict((('a', 1), ('b', 2)))

print(dict(dd))
{'a': 1, 'b': 2}

print(tuple(dd))
('a', 'b')

print([x for x in dd])
['a', 'b']

编辑2:

另一种看待这种情况的方式是,当某事物通过dict()时,其行为根据type的{​​{1}}而有所不同,或者看起来有时它依赖于__iter__并且有时它依赖于其他。问题是还有什么(或者在此级别上发生了哪种__iter__检查),如何获得这种替代行为并最终讨论了潜在的局限性。

我很可能在一天结束时无法像我描述的那样构建自定义类type,因为它例如是Something必须返回映射的键。

2 个答案:

答案 0 :(得分:2)

要么声明专用方法,要么:

class Something(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def to_dict(self):
        return dict(self)

    def to_tuple(self):
        return tuple((y for _, y in self))

    def __iter__(self):
        yield ('a', self.a)
        yield ('b', self.b)

x = Something(1, 2)

print(x.to_tuple())
# (1, 2)
print(x.to_dict())
# {'a': 1, 'b': 2}

或者您将类转换为元组的方式进行一些修改:

print(tuple((y for _, y in x)))
# (1, 2)
print(dict(x))
# {'a': 1, 'b': 2}
  

但是您希望您的类具有的行为会导致一个非常棘手的情况,其中__iter__方法的输出将与随后转换此输出的类型不同……

答案 1 :(得分:0)

一种方法可以是这种方法,但是需要显式更改属性。

class Something(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def s(self, boolean):
        self.y = boolean
        return self
    def __iter__(self):
        if self.y:
            yield ('a', self.a)
            yield ('b', self.b)
        else:
            yield (self.a)
            yield (self.b)


x = Something(1, 2)

输出:-

print(tuple(x.s(0)))
# (1, 2)

print(dict(x.s(1)))
# {'a': 1, 'b': 2}