2010-08-02 2 views
5

(Я использую Python 2.7) Документация питон означает, что вы можете передать отображение в Словаре и встроенной команды скопирует, что отображение в новом Dict:ABCs Python: регистрация против подклассов

http://docs.python.org/library/stdtypes.html#mapping-types-dict

у меня есть класс, который реализует Mapping ABC, но он не:

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 

Однако, если мой класс подклассы collections.Mapping то он работает отлично:

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 в любом случае). Так что здесь?

ответ

7

Регистрация не дает вам «недостающих методов», реализованных поверх тех, которые вы определяете: на самом деле регистрация неинвазивная в отношении типа, который вы регистрируете, - ничего не добавляется к нему, ничего удаляется, ничего не изменяется. Это только влияет на isinstance и issubclass чеков: ничего больше, не меньше.

Подкласс ABC может и дает вам множество методов, реализованных «бесплатно» ABC поверх тех, которые вам нужно определить самостоятельно.

Семантика операции, которая является абсолютно неинвазивной, как регистрация, по сравнению с операцией , предназначенной для для обогащения класса, например, для подкласса, очевидно, не может быть идентичной; поэтому ваше понимание «всей точки Азбуки» несовершенно - у ABC есть две точки, одна из которых получена путем подкласса («инвазивная»), одна - путем регистрации (неинвазивного).

Обратите внимание, что вы всегда можете умножить-наследовать, если у вас уже есть класс, как оригинал Mapping: class GoogMapping(Mapping, collections.Mapping): ... даст вам те же результаты, наследуя Mapping непосредственно из collections.Mapping - новый тип с всех вспомогательных методов, добавленных collections.Mapping.

+0

Спасибо! Это было информативно. Я не хотел подкласса, потому что мне не нужны специальные «бесплатные» методы, которые вы получаете при подклассе. Я думал, что я достаточно охватил свой класс, чтобы я мог передать его диктову, но я ошибся. Еще раз спасибо. –

+0

@ Эрик, пожалуйста! Конкретный метод, который вы пропустили для цели (или обновления) dict с экземпляром вашего класса, - это 'keys' - cfr строка 1411 из http://svn.python.org/view/python/trunk/Objects /dictobject.c?annotate=81029 - 'if (PyObject_HasAttrString (arg,« keys »))' - вот как 'dict' обнаруживает, если ему передается сопоставление или итерабельность пар (в первом случае строка 1567 , он затем будет использовать 'PyMapping_Keys' и c). BTW, безобидный, но лишний, вы дважды определили '__iter__'. –

+0

Что касается класса Mapping, означает ли это, что для правильного отображения Mapping должны быть все методы Mapping, даже для бесплатных? Я думаю, да, так как для диктата ожидались ключи. Или это то, что dict мог использовать iter, чтобы получить ключи? –

0

Ах, похоже, что dict() ищет метод ключей ... Он не использует ABC.

+0

Это действительно ('PyMapping_Keys' специально), но тогда и только тогда, когда присутствует метод' keys', см. Мой комментарий выше (в моей ветке комментариев A) о более подробной информации. –