我想做这样的事情:
class Dictable:
def dict(self):
raise NotImplementedError
class Foo(Dictable):
def dict(self):
return {'bar1': self.bar1, 'bar2': self.bar2}
有更多的pythonic方法吗?例如,是否可以重置内置转换dict(...)
?请注意,我不一定要返回Foo
的所有成员变量,我宁愿让每个类决定返回什么。
感谢。
答案 0 :(得分:5)
Pythonic方式取决于你想做什么。如果您的对象本身不应被视为映射,那么dict
方法就完全可以了,但您不应该“重载”dict
来处理dictables。您是否需要基类取决于您是否要isinstance(x, Dictable)
;请注意,hasattr(x, "dict")
的用途几乎相同。
如果类 在概念上映射了值的键,那么实现Mapping
协议似乎是合适的。即,你实施
__getitem__
__iter__
__len__
并从collections.Mapping
继承以获取其他方法。然后你免费获得dict(Foo())
。例如:
class Foo(Mapping):
def __getitem__(self, key):
if key not in ("bar1", "bar2"):
raise KeyError("{} not found".format(repr(key))
return getattr(self, key)
def __iter__(self):
yield "bar1"
yield "bar2"
def __len__(self):
return 2
答案 1 :(得分:1)
首先,看看collections.ABC
,它描述了Python抽象基类协议(相当于静态语言中的接口)。
然后,决定是否要编写自己的ABC或使用现有的ABC;在这种情况下,Mapping可能就是您想要的。
请注意,虽然dict
构造函数(即dict(my_object)
)不可重写,但如果遇到产生一系列键值对的可迭代对象,它将构造一个dict;即(Python 2;用于Python 3用items
替换iteritems
):
def __iter__(self):
return {'bar1': self.bar1, 'bar2': self.bar2}.iteritems()
但是,如果您的类的行为类似于dict
,则不应该执行此操作,因为它与Mapping
实例的预期行为不同,后者将遍历键,而不是键 - 值对。特别是它会导致for .. in
行为不正确。
答案 2 :(得分:0)
你当然可以重载dict(),但你几乎不想!标准库的太多方面取决于可用的字典,您将破坏其大部分功能。你可能会做这样的事情:
class Dictable:
def dict(self):
return self.__dict__
答案 3 :(得分:0)
这里的大多数答案都是关于让你的课堂表现得像个字典,这实际上并不是你所要求的。如果你想表达这个想法,“我是一个可以变成字典的类,”我只需要定义一堆类,并让它们各自实现.dict()。 Python倾向于对对象的内容进行duck-typing(对象可以做什么)。 ABC不会增加太多。文档也有同样的目的。