programacion poo polimorfismo otra orientada objetos metodo llamar instancia importar ejemplos clases clase python methods instance-variables class-attributes

poo - programacion orientada a objetos python pdf



Python: ¿Qué sucede cuando el atributo de clase, el atributo de instancia y el método tienen todos el mismo nombre? (4)

¿Cómo distingue Python un atributo de clase, un atributo de instancia y un método cuando los nombres son los mismos?

class Exam(object): test = "class var" def __init__(self, n): self.test = n def test(self): print "method : ",self.test test_o = Exam("Fine") print dir(test_o) print Exam.test print test_o.test test_o.test()

Salida:

[''__class__'', ''__delattr__'', ''__dict__'', ''__doc__'', ''__format__'', ''__getattribute__'', ''__hash__'', ''__init__'', ''__module__'', ''__new__'', ''__reduce__'', ''__reduce_ex__'', ''__repr__'', ''__setattr__'', ''__sizeof__'', ''__str__'', ''__subclasshook__'', ''__weakref__'', ''test''] <unbound method load.test> Fine Traceback (most recent call last): File "example.py", line 32, in <module> test_o.test() TypeError: ''str'' object is not callable

Como llamar

  1. atributo de clase, Exam.test -> <unbound method load.test> output muestra el método
  2. atributo de instancia test_o.test -> "Fine"
  3. método test_o.test() -> TypeError: ''str'' object is not callable

Como llamar
atributo de clase, Exam.test

No se puede porque al ejecutar def test(self) la test nombre está ligada al método en la clase y la referencia a "class var" se pierde.

atributo de instancia test_o.test -> "Bien"

Ya hiciste eso.

método test_o.test()

No puede llamarlo así porque al ejecutar self.test = n la test del nombre está vinculada a cualquier objeto n referencias en la instancia y se pierde la referencia al método en la instancia.

Pero como se señaló en otras respuestas, puede llamar al método en la clase y pasarle la instancia: Exam.test(test_o)


Los atributos de clase son accesibles a través de la clase:

YourClass.clsattribute

o a través de la instancia (si la instancia no ha sobrescrito el atributo de clase):

instance.clsattribute

Los métodos, tal como lo establece ecatmur en su respuesta , son descriptores y se establecen como atributos de clase.

Si accede a un método a través de la instancia, la instancia se pasa como el parámetro self al descriptor. Si desea llamar a un método de la clase, debe pasar explícitamente una instancia como primer argumento. Entonces estos son equivalentes:

instance.method() MyClass.method(instance)

Usar el mismo nombre para un atributo de instancia y un método hará que el método se oculte a través de la instancia, pero el método todavía está disponible a través de la clase:

#python3 >>> class C: ... def __init__(self): ... self.a = 1 ... def a(self): ... print(''hello'') ... >>> C.a <function a at 0x7f2c46ce3c88> >>> instance = C() >>> instance.a 1 >>> C.a(instance) hello

Conclusión: no den el mismo nombre a los atributos y métodos de la instancia. Evito esto dando nombres significativos. Los métodos son acciones, por lo que usualmente uso verbos u oraciones para ellos. Los atributos son datos, por lo que uso sustantivos / adjetivos para ellos, y esto evita usar los mismos nombres para ambos métodos y atributos.

Tenga en cuenta que simplemente no puede tener un atributo de clase con el mismo nombre que un método, porque el método lo anularía completamente (al final, los métodos son solo atributos de clase que son invocables y que automáticamente reciben una instancia de la clase como primer atributo) .


Puede llamar al método como método de clase y pasar su instancia en él:

Exam.test(test_o)

O bien, si no desea usar el Exam :

type(test_o).test(test_o)


Puedes escribir

Exam.test(test_o)

o

Exam.test.__get__(test_o)()

En este último caso, está utilizando el hecho de que los métodos son descriptors para convertir el <unbound method load.test> a un método vinculado, por lo que puede llamarlo con corchetes individuales.

Cuando escribe test_o.test() , Python no sabe que está intentando llamar a un método; es posible que intente llamar a una función o objeto invocable que se haya instalado en el objeto como un miembro de datos de instancia. En cambio, busca la test atributo, primero en el objeto y luego en su clase, pero como el atributo existe en el objeto, oculta el método en la clase.

El miembro de la clase

test = "class var"

no es accesible (de hecho, no existe en ninguna parte), porque está sobrescrito por la test método; cuando se ejecuta una declaración de class , su espacio de nombre se recopila en un dict antes de pasarlo a su metaclase, y los nombres posteriores anulan los anteriores.