2010-08-02 19 views
5

(używam Pythona 2.7) Dokumentacja pyton oznacza, że ​​można przekazać mapowanie do dict wbudowanego i skopiuje że mapowanie do nowego dict:Python ABC: rejestracji w porównaniu z podklasy

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

mam klasy, która implementuje mapowanie ABC, ale to się nie powiedzie:

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 

Jednakże, jeśli moja klasa podklasy collections.Mapping to działa dobrze:

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} 

Pomyślałem, że cały punkt ABC polega na umożliwieniu rejestracji tak samo, jak jej podklasowanie (i tak dla isinstance i issubclass). Co tu jest?

Odpowiedz

7

Rejestracja nie daje "brakujących metod" zaimplementowanych w stosunku do zdefiniowanych przez użytkownika: w rzeczywistości rejestracja to nieinwazyjna w odniesieniu do typu, który rejestrujesz - nic do niego nie dodaje, nic zostaje usunięty, nic się nie zmienia. To sprawdza tylko: nie więcej, nic mniej.

Podklasy ABC może i daje wiele metod wdrożonych "za darmo" przez ABC, oprócz tych, które trzeba zdefiniować samodzielnie.

Semantyka operacji, która jest całkowicie nieinwazyjna, jak rejestracja, w porównaniu do operacji o nazwie zamierzonej w celu wzbogacenia klasy, podobnie jak podklasy, oczywiście nie może być identyczna; więc twoje zrozumienie "całego punktu ABC" jest niedoskonałe - ABC mają dwa punkty, jeden uzyskany przez podklasę ("inwazyjny"), jeden przez rejestrację (nieinwazyjny).

Pamiętaj, że zawsze możesz pomnożyć-dziedziczyć jeśli masz już klasę jak oryginał Mapping: class GoogMapping(Mapping, collections.Mapping): ... daje takie same wyniki jak dziedziczenie Mapping bezpośrednio od collections.Mapping - nowy typ z wszystkich metod pomocniczych dodawanych przez collections.Mapping.

+0

Dzięki! To było pouczające. Nie chciałem podklasy, ponieważ nie chcę konkretnych "darmowych" metod, które otrzymujesz, gdy jesteś podklasą. Pomyślałem, że zakryłem swoją klasę na tyle, że mogłem ją rzucić na dyktando, ale myliłem się. Dzięki jeszcze raz. –

+0

@Eric, nie ma za co! Specyficzna metoda, którą pominąłeś w celu wywołania (lub aktualizacji) dicta w instancji twojej klasy to 'keys' - cfr linia 1411 z http://svn.python.org/view/python/trunk/Objects /dictobject.c?annotate=81029 - 'if (PyObject_HasAttrString (arg," keys "))) - tak właśnie" dict "odkrywa, czy jest przekazywana mapowanie lub iteracja par (w pierwszym przypadku linia 1567 , następnie użyje 'PyMapping_Keys' i c). BTW, niewinny, ale zbyteczny, dwukrotnie zdefiniowałeś '__iter__'. –

+0

Jeśli chodzi o klasę mapowania, czy oznacza to, że prawidłowe mapowanie musi zawierać wszystkie metody mapowania, nawet te niewolne? Myślę, że tak, ponieważ klucze były oczekiwane dla dyktatora. A może to dykt mógł użyć go do zdobycia kluczy? –

0

Ah, wygląda na to, że dict() szuka metody kluczy ... Nie używa ABC.

+0

Robi to ('PyMapping_Keys') ale jeśli i tylko wtedy, gdy jest obecna metoda' keys', zobacz mój komentarz powyżej (w wątku komentarzy A) o więcej szczegółów. –