method - python static class
¿Es cierto que "el conjunto de métodos, sin embargo, está fijo cuando la clase se define por primera vez"? (2)
A nivel de instancia, uno puede modificar campos directamente como se menciona.
A nivel de clase / módulo, hay una mecánica no oficial llamada monkey patching
. Básicamente obtendría una referencia (?) A la clase / módulo y anularía la función.
Sin embargo, no me queda claro si los métodos estáticos pueden anularse. Y la modificación solo es válida en el ámbito local, donde los parches de mono están hechos, creo. Por lo tanto, no debe esperar que otros scripts que importan la misma clase / módulo compartan los parches de mono, a menos que también apliquen los parches explícitamente. Por supuesto, también puedes crear un módulo envoltorio.
No creo que esto sea muy defendido por la comunidad de Python. Es bastante difícil mantener los parches en pista durante mucho tiempo.
Más información: ¿Qué es un parche de mono?
De Programming Language Pragmatics, por Scott
Tanto Python como Ruby son más fl exibles que PHP o más lenguajes orientados a objetos tradicionales con respecto a los contenidos (miembros) de una clase. Se pueden agregar nuevos campos a un objeto de Python simplemente asignándolos: my_object.new_field = value. El conjunto de métodos, sin embargo, se fija cuando la clase se define por primera vez. En Ruby, solo los métodos son visibles fuera de una clase (los métodos "poner" y "obtener" deben usarse para acceder a los campos), y todos los métodos deben declararse explícitamente. Sin embargo, es posible modificar una declaración de clase existente, añadiendo o reemplazando métodos. Incluso se puede hacer esto objeto por objeto. Como resultado, dos objetos de la misma clase pueden no mostrar el mismo comportamiento.
¿Qué significa "El conjunto de métodos, sin embargo, está fijo cuando la clase se define por primera vez" significa?
Parece que encontré un contraejemplo:
>>> class E:
... pass
...
>>> E.__dict__
mappingproxy({''__module__'': ''__main__'', ''__dict__'': <attribute ''__dict__'' of ''E'' objects>, ''__doc__'': None, ''__weakref__'': <attribute ''__weakref__'' of ''E'' objects>})
>>> def myfun():
... pass
...
>>> E.mf=myfun
>>> E.__dict__
mappingproxy({''__module__'': ''__main__'', ''__dict__'': <attribute ''__dict__'' of ''E'' objects>, ''__doc__'': None, ''__weakref__'': <attribute ''__weakref__'' of ''E'' objects>, ''mf'': <function myfun at 0x7f6561daba60>})
Como se muestra en la pregunta: es trivial agregar una función a un objeto de clase que se comporta como cualquier otro método:
def fake_method(self,idx):
print(self, idx)
class MyClass(object):
pass
MyClass.new_method = fake_method
n = MyClass()
n.new_method(10)
# <__main__.MyClass object at 0x000001BBA6E90860> 10
También puede agregar "métodos" como "atributos invocables" a una instancia:
import types
def fake_method(self,idx):
print(self, idx)
class MyClass(object):
pass
n = MyClass()
n.new_method = types.MethodType(fake_method, n)
n.new_method(10)
# <__main__.MyClass object at 0x000001BBA6E9C2E8> 10
El types.MethodType
es necesario aquí porque de lo contrario se comportaría como un staticmethod
.
Mi resumen: o me falta algún punto crucial de la cita o está mal.