2011-01-15 12 views
47

Por ejemplo — dicen que quiero agregar un método helloWorld() al tipo dict de Python. ¿Puedo hacer esto?¿Puedo agregar métodos/atributos personalizados a los tipos de Python incorporados?

JavaScript tiene un objeto prototipo que se comporta de esta manera. Tal vez es un mal diseño y debería subclasificar el objeto dict, pero solo funciona en las subclases y quiero que funcione en todos los diccionarios futuros.

Así es como se reduciría en JavaScript:

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

Aquí hay un enlace útil con más ejemplos — http://www.javascriptkit.com/javatutors/proto3.shtml

+0

También puede hacerlo en ruby ​​simplemente abriendo nuevamente la clase, es decir: clase String; def new_method() ...; end; Estoy bastante seguro de que Python tiene algo así también. –

+0

@ Abdullah Creo que te estás refiriendo al parche de monos, que en su mayoría es desaprobado. –

+0

Sí exactamente. Está hecho todo en Rails. –

Respuesta

53

No puede agregar directamente el método al tipo original. Sin embargo, puede subclase el tipo y luego sustituirlo en el espacio de nombres integrado/global, que logra la mayor parte del efecto deseado. Desafortunadamente, los objetos creados por sintaxis literal continuarán siendo de tipo vainilla y no tendrán sus nuevos métodos/atributos.

Esto es lo que parece

# 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

Supongo que tendré que usar el método preferido para crear subclases. Tal vez voy a llegar a amarlo. – jedmao

+11

Nota: El módulo '__builtin__' fue renombrado como' builtins' en Python3. – changokun

+0

Bueno, me encontré con un problema en Python 2. Después de eso, ya no puedo verificar el tipo> type ('') == str false <. Cuando escribo ("") obtengo , pero de alguna manera la comparación ya no funciona. Antes de ejecutar la 'línea __builtin __. Str = mystr' funciona la comprobación del tipo. – Nadu

1

Sí, subclasificando esos tipos. Ver unifying types and classes in Python.

No, esto no significa que predice reales tienen este tipo, porque eso sería confuso. La subclase de un tipo integrado es la forma preferida de agregar funcionalidad.

+5

Eso sería confuso y muy, muy útil. –

+0

@EvgeniSergeev ¿Por qué crees que sería muy útil? Nunca he entendido realmente a las personas que desean esto. ¿Crees que 5 no debería ser de tipo int, o crees que type int debería ser mutable (mientras que 5 es inmutable)? – Veky

+0

@Veky quiero 'any_dictionary_instance.len()' 'o .size()', además del 'any_dictionary_instance disponibles .__ len __()' y 'len (any_dictionary_instance)' que lo llama. El tamaño es semánticamente una propiedad de los contenedores, por lo que es más conveniente escribir como dices, por ejemplo. "iterar de 0 al tamaño del objeto" ... oops, no puedo expresar eso, el lenguaje me obliga a reformularlo como "iterar de 0 al tamaño del objeto". Por nada mejor que razones históricas, deduzco. –

-1

subclases es el camino a seguir en Python. Los programadores de Polyglot aprenden a usar la herramienta correcta para la situación correcta, dentro de lo razonable. Algo tan hábilmente construido como Rails (un DSL que usa Ruby) es muy difícil de implementar en un lenguaje con una sintaxis más rígida como Python. La gente a menudo compara los dos diciendo lo similares que son. La comparación es algo injusta. Python brilla a su manera. totochto.

Cuestiones relacionadas