español - python import class
__new__ y__init__ en Python (1)
cómo debería estructurar la clase usando
__init__y__new__ya que son diferentes y ambos aceptan argumentos arbitrarios además del primer argumento predeterminado.
Solo en raras ocasiones tendrás que preocuparte por __new__ . Por lo general, usted simplemente definirá __init__ y dejará que __new__ predeterminado __new__ pase los argumentos del constructor.
selfpalabra claveselfes en términos de nombre puede ser cambiado a algo más? Pero me pregunto siclsestá en términos de nombre está sujeto a cambiar a otra cosa, ya que es solo un nombre de parámetro.
Ambos son solo nombres de parámetros sin significado especial en el idioma. Pero su uso es una convención muy fuerte en la comunidad de Python; la mayoría de los Pythonistas nunca cambiarán los nombres de self y los cls en estos contextos y se confundirán cuando alguien más lo haga.
Tenga en cuenta que el uso de def __new__(tuple) vuelve a def __new__(tuple) el nombre tuple dentro de la función constructora. Cuando realmente implemente __new__ , querrá hacerlo como
def __new__(cls, *args, **kwargs):
# do allocation to get an object, say, obj
return obj
Aunque dije que quería devolver la
tuple, este código funciona bien y me devolvió[1,2,3].
MyClass() tendrá el valor que devuelve __new__ . No hay verificación de tipos implícita en Python; es responsabilidad del programador devolver el tipo correcto ("todos consentimos adultos aquí"). Ser capaz de devolver un tipo diferente al solicitado puede ser útil para implementar fábricas: puede devolver una subclase del tipo solicitado.
Esto también explica el comportamiento issubclass / isinstance que observa: la relación de subclase se desprende de su uso de la class MyClass(tuple) , la isinstance refleja que usted devuelve el tipo "incorrecto" de __new__ .
Como referencia, consulte los requisitos para __new__ en la Referencia del lenguaje Python .
Editar : bien, aquí hay un ejemplo del uso potencialmente útil de __new__ . La clase Eel realiza un seguimiento de cuántas anguilas están vivas en el proceso y se rehúsa a asignar si excede un máximo.
class Eel(object):
MAX_EELS = 20
n_eels = 0
def __new__(cls, *args, **kwargs):
if cls.n_eels == cls.MAX_EELS:
raise HovercraftFull()
obj = super(Eel, cls).__new__(cls)
cls.n_eels += 1
return obj
def __init__(self, voltage):
self.voltage = voltage
def __del__(self):
type(self).n_eels -= 1
def electric(self):
"""Is this an electric eel?"""
return self.voltage > 0
Eso sí, hay formas más inteligentes de lograr este comportamiento.
Estoy aprendiendo Python y hasta ahora puedo decir lo siguiente sobre __new__ y __init__ :
-
__new__es para creación de objetos -
__init__es para la inicialización de objetos -
__new__se invoca antes de__init__como__new__devuelve una nueva instancia y__init__invoca después para inicializar el estado interno. -
__new__es bueno para objetos inmutables ya que no se pueden cambiar una vez que se asignan. Entonces podemos devolver una nueva instancia que tiene un nuevo estado. - Podemos usar
__new__y__init__para ambos objetos mutables ya que su estado interno puede ser cambiado.
Pero tengo otra pregunta ahora.
- Cuando creo una nueva instancia como
a = MyClass("hello","world"), ¿cómo se pasan estos argumentos? Quiero decir cómo debería estructurar la clase usando__init__y__new__ya que son diferentes y ambos aceptan argumentos arbitrarios además del primer argumento predeterminado. -
selfpalabra claveselfes en términos de nombre puede ser cambiado a algo más? Pero me pregunto siclsestá en términos de nombre está sujeto a cambiar a otra cosa, ya que es solo un nombre de parámetro.
Hice algunos pequeños experimentos como tales a continuación:
>>> class MyClass(tuple):
def __new__(tuple):
return [1,2,3]
y lo hice a continuación:
>>> a = MyClass()
>>> a
[1, 2, 3]
Aunque dije que quería devolver la tuple , este código funciona bien y me devolvió [1,2,3] . Sabía que estábamos pasando los primeros parámetros como el tipo que queríamos recibir una vez que se invoca la función __new__ . Estamos hablando de una New función, ¿verdad? No sé otro tipo de devolución de idiomas que no sea el tipo vinculado
Y también hice otras cosas:
>>> issubclass(MyClass,list)
False
>>> issubclass(MyClass,tuple)
True
>>> isinstance(a,MyClass)
False
>>> isinstance(a,tuple)
False
>>> isinstance(a,list)
True
No hice más experimento porque el más allá no era brillante y decidí parar allí y decidí pedir StackOverflow.
Los mensajes SO que leo: