2011-01-15 17 views
47

Na przykład — powiedz, że chcę dodać metodę helloWorld() do typu Dict Pythona. Mogę to zrobić?Czy mogę dodać niestandardowe metody/atrybuty do wbudowanych typów Pythona?

JavaScript ma prototypowy obiekt, który zachowuje się w ten sposób. Może to zły projekt i powinienem podklasować obiekt dict, ale wtedy działa on tylko na podklasach i chcę, żeby działał na wszystkich przyszłych słownikach.

Oto jak byłoby to w JavaScript:

String.prototype.hello = function() { 
    alert("Hello, " + this + "!"); 
} 
"Jed".hello() //alerts "Hello, Jed!" 

Oto przydatny związek z większą liczbą przykładów — http://www.javascriptkit.com/javatutors/proto3.shtml

+0

Możesz to zrobić również w ruby, po prostu otwierając klasę ponownie, np .: class String; def new_method() ...; end; Jestem prawie pewien, że Python ma coś takiego. –

+0

@Abdullah Wierzę, że odnosisz się do łatania małp, które są głównie mile widziane. –

+0

Tak, dokładnie. Wszystko odbywa się w Railsach. –

Odpowiedz

53

Nie można bezpośrednio dodać metody do oryginalnego typu. Można jednak podklasować typ, a następnie zastąpić go we wbudowanej/globalnej przestrzeni nazw, która osiąga większość pożądanego efektu. Niestety, obiekty utworzone przez literalną składnię będą nadal typu waniliowego i nie będą miały twoich nowych metod/atrybutów.

Oto jak to wygląda

# Built-in namespace 
import __builtin__ 

# Extended subclass 
class mystr(str): 
    def first_last(self): 
     if self: 
      return self[0] + self[-1] 
     else: 
      return '' 

# Substitute the original str with the subclass on the built-in namespace  
__builtin__.str = mystr 

print str(1234).first_last() 
print str(0).first_last() 
print str('').first_last() 
print '0'.first_last() 

output = """ 
14 
00 

Traceback (most recent call last): 
    File "strp.py", line 16, in <module> 
    print '0'.first_last() 
AttributeError: 'str' object has no attribute 'first_last' 
""" 
+0

Chyba będę musiał użyć preferowanej metody podklasy. Może dojdę do tego, żeby to pokochać. – jedmao

+11

Uwaga: Nazwa modułu "__builtin__" została zmieniona na 'builtins' w Python3. – changokun

+0

Cóż, napotkałem problem w python 2. Po tym nie mogę już sprawdzić typu> typ ('') == str false <. Kiedy piszę ("") otrzymuję , ale jakoś porównanie już nie działa. Przed uruchomieniem 'line __builtin __. Str = mystr' sprawdzanie typu działa. – Nadu

1

Tak, przez instacji te typy. Zobacz unifying types and classes in Python.

Nie, to nie znaczy, że rzeczywiste dyktety będą miały ten typ, ponieważ byłoby to mylące. Podklasy typu wbudowanego są preferowanym sposobem dodawania funkcjonalności.

+5

To byłoby mylące i bardzo przydatne. –

+0

@EvgeniSergeev Dlaczego uważasz, że byłoby to bardzo przydatne? Nigdy naprawdę nie rozumiałem tych ludzi, którzy tego pragną. Czy uważasz, że 5 nie powinno być typu int, czy uważasz, że typ int powinien być zmienny (podczas gdy 5 samo w sobie jest niezmienne)? – Veky

+0

@Veky Chcę 'any_dictionary_instance.len()' lub '.size()', oprócz dostępnych 'any_dictionary_instance .__ len __()' i 'len (any_dictionary_instance)' które wywołują to. Rozmiar jest semantycznie właściwością kontenerów, więc wygodniej jest pisać, gdy mówisz np. "iteracja od 0 do rozmiaru obiektu" ... oops, nie mogę tego wyrazić, język zmusza mnie do przeformułowania go jako "iteracja od 0 do rozmiaru obiektu". Nie mam nic lepszego niż względy historyczne. –

-1

podklasy to droga w Pythonie. Wielobarwni programiści uczą się korzystać z właściwego narzędzia w odpowiedniej sytuacji - w granicach rozsądku. Coś tak pomysłowo skonstruowanego jak Rails (DSL używający Ruby) jest boleśnie trudne do implementacji w języku o bardziej sztywnej składni jak Python. Ludzie często porównują tę dwójkę mówiąc, że są podobni. Porównanie jest nieco niesprawiedliwe. Python świeci na swój sposób. totochto.

Powiązane problemy