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.
self
palabra claveself
es en términos de nombre puede ser cambiado a algo más? Pero me pregunto sicls
está 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. -
self
palabra claveself
es en términos de nombre puede ser cambiado a algo más? Pero me pregunto sicls
está 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: