2009-10-28 11 views
5

Given jest następujący przykład:Python klasy z całkowitej emulacji

class Foo(object): 
    def __init__(self, value=0): 
     self.value=value 

    def __int__(self): 
     return self.value 

chcę mieć klasę Foo, który działa jako liczba całkowita (lub float). Więc chcę zrobić następujące rzeczy:

f=Foo(3) 
print int(f)+5 # is working 
print f+5 # TypeError: unsupported operand type(s) for +: 'Foo' and 'int' 

Pierwsze oświadczenie print int(f)+5 pracuje, bo są dwie liczby całkowite. Druga nie działa, ponieważ muszę wykonać __add__, aby wykonać tę operację z moją klasą.

Aby zaimplementować zachowanie liczby całkowitej, muszę zaimplementować wszystkie metody emulacji liczb całkowitych. Jak mogę to obejść. Próbowałem odziedziczyć po int, ale ta próba zakończyła się niepowodzeniem.

Aktualizacja

Dziedziczenie z int nie powiedzie się, jeśli chcesz używać __init__:

class Foo(int): 
    def __init__(self, some_argument=None, value=0): 
     self.value=value 
     # do some stuff 

    def __int__(self): 
     return int(self.value) 

Jeśli następnie zadzwonić:

f=Foo(some_argument=3) 

otrzymasz:

TypeError: 'some_argument' is an invalid keyword argument for this function 

Testowane z Python 2.5 i 2.6

+1

Nie rozumiem twojego pytania. Jak możesz obejść jedną rzecz, którą musisz zrobić, aby nie zrobić jedynej rzeczy, którą musisz zrobić? Fishslap! –

+0

Chcę, aby klasa działała jak liczba całkowita. Implementacje rzeczywistych liczb całkowitych są zawsze takie same, więc po co je wdrażać za każdym razem, gdy z niego korzystasz. Metoda __add__ ma sens, gdy używasz operatora "+" dla wszystkiego innego niż prawdziwy dodatek. –

Odpowiedz

5

Trzeba zastąpić __new__, nie __init__:

class Foo(int): 
    def __new__(cls, some_argument=None, value=0): 
     i = int.__new__(cls, value) 
     i._some_argument = some_argument 
     return i 

    def print_some_argument(self): 
     print self._some_argument 

Teraz praca klasy zgodnie z oczekiwaniami:

>>> f = Foo(some_argument="I am a customized int", value=10) 
>>> f 
10 
>>> f + 8 
18 
>>> f * 0.25 
2.5 
>>> f.print_some_argument() 
I am a customized int 

Więcej informacji o przesłanianie new można znaleźć w Unifying types and classes in Python 2.2.

7

W Pythonie 2.4+ dziedziczenie z int działa:

class MyInt(int):pass 
f=MyInt(3) 
assert f + 5 == 8 
+0

Miałem problemy, gdy używałem nazwanych argumentów dla konstruktora (__init__). Kiedy dzwonię do f = MyInt (other_argument = True) to się nie udało (TypeError: 'other_argument' jest nieprawidłowym argumentem słowa kluczowego dla tej funkcji) –

+1

@ Günther Jehle: Dodaj to do swojego pytania. Ten komentarz nie pasuje do twojego pytania i nie ma większego sensu w kontekście tego pytania. Zaktualizuj pytanie, aby uwzględnić wszystkie fakty. –

+0

dodał wynik dziedziczenia z int –

2

Spróbuj skorzystać z up-to-date wersję Pythona. Twój kod działa w wersji 2.6.1.

+0

Dam to spróbować –

+0

Moja wersja python jest obecnie 2.5.1 –

+0

Czekaj, dlaczego dziedziczycie z 'obiektu' ?? Kod działa, jeśli dziedziczysz z 'int'. – jdb

Powiązane problemy