Python ABC:注册与子类化 [英] Python ABCs: registering vs. subclassing
问题描述
(我正在使用python 2.7)python文档指示您可以将映射传递给内置的dict,它将将该映射复制到新的dict中:
(I am using python 2.7) The python documentation indicates that you can pass a mapping to the dict builtin and it will copy that mapping into the new dict:
http://docs.python.org/library/stdtypes. html#mapping-types-dict
我有一个实现Mapping ABC的类,但是失败了:
I have a class that implements the Mapping ABC, but it fails:
import collections
class Mapping(object):
def __init__(self, dict={}): self.dict=dict
def __iter__(self): return iter(self.dict)
def __iter__(self): return iter(self.dict)
def __len__(self): return len(self.dict)
def __contains__(self, value): return value in self.dict
def __getitem__(self, name): return self.dict[name]
m=Mapping({5:5})
dict(m)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: cannot convert dictionary update sequence element #0 to a sequence
collections.Mapping.register(Mapping)
dict(m)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: cannot convert dictionary update sequence element #0 to a sequence
但是,如果我的班级将集合归为一类,则可以正常工作:
However, if my class subclasses collections.Mapping then it works fine:
import collections
class Mapping(collections.Mapping):
def __init__(self, dict={}): self.dict=dict
def __iter__(self): return iter(self.dict)
def __iter__(self): return iter(self.dict)
def __len__(self): return len(self.dict)
def __contains__(self, value): return value in self.dict
def __getitem__(self, name): return self.dict[name]
m=Mapping({5:5})
dict(m)
# {5: 5}
我认为ABC的全部目的是允许注册的工作与子类化相同(无论如何,对于isinstance和issubclass).那么这是怎么回事?
I thought the whole point of the ABCs was to allow registration to work the same as subclassing (for isinstance and issubclass anyway). So what's up here?
推荐答案
注册并不能为您提供定义之外的缺失方法":实际上,注册是非侵入性关于您正在注册的类型-不会添加任何内容,不会删除任何内容,不会更改任何内容.它仅会影响isinstance
和issubclass
检查:仅此而已.
Registration does not give you the "missing methods" implemented on top of those you define: in fact, registration is non-invasive with respect to the type you're registering -- nothing gets added to it, nothing gets removed, nothing gets altered. It only affects isinstance
and issubclass
checks: nothing more, nothing less.
在必须定义自己的基础上,对ABC进行子类化可以并且确实为您提供了许多由ABC免费"实现的方法.
Subclassing an ABC can and does give you plenty of methods implemented "for free" by the ABC on top of those you're having to define yourself.
与打算来丰富类的操作(如子类化)相比,完全非侵入式(如注册)操作的语义显然不能完全相同;因此,您对"ABC的整个要点"的理解是不完善的-ABC有 2 个要点,一个是通过分类(侵入性")获得的,一个是通过注册(非侵入性的)获得的.
The semantics of an operation that's totally non-invasive like registering, compared to those of an operation that's intended to enrich a class, like subclassing, obviously cannot be identical; so your understanding of "the whole point of the ABCs" is imperfect -- ABCs have two points, one obtained by subclassing ("invasive"), one by registering (non-invasive).
请注意,如果您已经拥有像原始Mapping
这样的类,则可以始终进行乘法继承:class GoogMapping(Mapping, collections.Mapping): ...
与直接从collections.Mapping
继承Mapping
的结果相同-一种新的类型使用 collections.Mapping
添加的所有辅助方法.
Note that you can always multiply-inherit if you already have a class like your original Mapping
: class GoogMapping(Mapping, collections.Mapping): ...
will give you the same results as inheriting Mapping
directly from collections.Mapping
-- a new type with all the auxiliary methods added by collections.Mapping
.
这篇关于Python ABC:注册与子类化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!