gpt4 book ai didi

python - 编写一个在调用 list(c) 和 dict(c) 时返回不同值的类

转载 作者:太空宇宙 更新时间:2023-11-03 13:33:32 25 4
gpt4 key购买 nike

我正在尝试实现一个自定义类,它在调用 list(c)dict(c) 时返回不同的值。但是,我的印象是 list(c)dict(c) 都使用了 c.__iter__() 吗?如果是这样,我怎样才能在调用 list(c)dict(c) 时获得不同的行为?我知道这是可能的,因为 Python 字典和 pandas DataFrames 有不同的 hevariours。

例如:

class Foo:    def __init__(self):        self._keys = ['a', 'b', 'd', 'd', 'e']        self._data = [10, 20, 30, 40, 50]    def __iter__(self):        for key, value in zip(self._keys, self._data):            yield key, value

调用 dict(c) 我得到了我想要的:

>>> f = Foo()>>> dict(f){'a': 10, 'b': 20, 'd': 40, 'e': 50}

但是,我无法让 list(c) 打印出键(或值)列表,而是同时获得两者:

>>> f = Foo()>>> list(f)[('a', 10), ('b', 20), ('d', 30), ('d', 40), ('e', 50)]

字典的等效代码更简洁:

>>> f = {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': 50}>>> dict(f){'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': 50}>>> list(f)['a', 'b', 'c', 'd', 'e']

最佳答案

显然 __iter__ 必须只返回 keys,否则 list(f) 将无法工作。

Python 文档说明了 dict constructor 的以下内容:

If a positional argument is given and it is a mapping object, a dictionary is created with the same key-value pairs as the mapping object.

现在,问题是对于 dict 构造函数来说,什么是足够的“映射”? DataFrame 没有继承自任何映射类,也没有注册到抽象基类。事实证明我们只需要支持keys方法:如果传递给dict构造函数的对象有一个名为keys的方法,调用它提供可迭代的键 [CPython source] .对于每个键,通过索引获取值。

dict 构造函数执行以下逻辑等价操作:

if hasattr(source, 'keys'):
for k in source.keys():
self[k] = source[k]
else:
self.update(iter(source))

使用这个我们得到

class Foo:
def __init__(self):
self._keys = ['a', 'b', 'd', 'd', 'e']
self._data = [10, 20, 30, 40, 50]

def __iter__(self):
return iter(self.keys)

def __getitem__(self, key):
idx = self._keys.index(key)
return self._data[idx]

def keys(self):
return self._keys

测试:

>>> f = Foo()
>>> list(f)
['a', 'b', 'd', 'd', 'e']

>>> dict(f)
{'d': 30, 'e': 50, 'a': 10, 'b': 20}

(从上面的代码可以看出,实际上不需要继承任何东西)

但是,不能保证所有 映射构造函数都以相同的方式运行 - 其他一些可能会调用 items - 因此最兼容的方法是实现所有collections.abc.Mapping 所需的方法并从中继承。 IE。这样做就足够了

class Foo(collections.abc.Mapping):
...
def __getitem__(self, key):
idx = self._keys.index(key)
return self._data[idx]

def __iter__(self):
return iter(self._keys)

def __len__(self):
return len(self._keys)

关于python - 编写一个在调用 list(c) 和 dict(c) 时返回不同值的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42772223/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com