programacion poo otra orientada objetos metodo llamar lista importar ejemplos clases clase python class member-variables

otra - poo python 3



Miembros de la clase Python (6)

En python, es posible tener variables de clase y variables de instancia del mismo nombre. Se ubican por separado en la memoria y se accede de forma bastante diferente.

En tu código:

class Node(object): element, left, right = None def __init__(self, element): self.element = element self.left = self.right = None

El primer conjunto de variables (fuera de la función __init__ ) se llaman variables de clase. A continuación, se puede acceder a ellos utilizando Node.element , etc. Estos son equivalentes a las variables de miembros estáticos en C ++, y todas las instancias de la clase los comparten.

El segundo conjunto de variables (dentro de la función __init__ ) se denominan variables de instancia. A estos se accede a través del objeto self , por ejemplo, self.element , o por el nombre de instancia, por ejemplo, myNode.element fuera de la clase.

Es importante tener en cuenta que debe usar la forma self.variable o Node.variable para acceder a cualquiera de estos dentro de una función miembro. El solo hecho de acceder a la variable intentará acceder a una variable local llamada variable .

Acabo de aprender Python y vengo de C, así que avíseme si tengo confusión / confusión entre ambos.

Supongamos que tengo la siguiente clase:

class Node(object): def __init__(self, element): self.element = element self.left = self.right = None @classmethod def tree(cls, element, left, right): node = cls(element) node.left = left node.right = right return node

Esta es una clase llamada Node , que sobrecarga el constructor, para poder manejar diferentes argumentos si es necesario.

¿Cuál es la diferencia entre definir self.element en __init__ solamente (como se muestra arriba) en lugar de hacer lo siguiente?

class Node(object): element, left, right = None def __init__(self, element): self.element = element self.left = self.right = None

¿El elemento propio no self.element en __init__ igual que la variable de element la clase definida? ¿No sobrescribiría ese element de None al valor del element pasado a __init__ ?


La parte importante es el self argumento para __init__ . De hecho, en cualquier método de instancia, este será el primer argumento. Esto se hace por diseño; en Python, el único momento en que realmente tiene acceso a la instancia es durante las llamadas al método, y se muestra explícitamente con el self argumento.

Cuando estás dentro de una definición de class , todavía no tienes instancias, entonces lo que realmente estás modificando es la clase misma. Por lo tanto, si defines atributos en el nivel de clase, entonces realmente se convierten en atributos de clase, y no instancia.

Si lo comparas con un C (++), probablemente puedas decir que las "clases" en esos idiomas son básicamente planos para los objetos que representan. "Estos objetos tendrán atributos foo y bar , y, además, los siguientes métodos". En Python, sin embargo, las clases son objetos en sí mismos, y su principal fortaleza es que pueden crear copias (instancias) de ellos mismos, que también usan los métodos de la clase. Por lo tanto, es más como "Tendrás foo y bar como atributos de clase y, además, el siguiente método que deberás usar para crear instancias".

Entonces, en lugar de un plan, es más un paso a paso.


Uno es un atributo de clase, mientras que el otro es un atributo de instancia. Son diferentes, pero están estrechamente relacionados entre sí de manera que a veces se ven iguales.

Tiene que ver con la forma en que python busca los atributos. Hay una jerarquía. En casos simples, podría verse así:

instance -> Subclass -> Superclass -> object (built-in type)

Cuando busca un atributo en una instance como esta ...

`instance.val`

... lo que realmente sucede es que primero , Python busca val en la instancia misma. Entonces, si no encuentra val , se ve en su clase, Subclass . Entonces, si no encuentra val allí, se ve en el padre de Subclass , Superclass . Esto significa que cuando haces esto ...

>>> class Foo(): foovar = 10 def __init__(self, val): self.selfvar = val

... todas las instancias de Foo comparten foovar , pero tienen sus propios selfvar distintivos. Aquí hay un ejemplo simple y concreto de cómo funciona eso:

>>> f = Foo(5) >>> f.foovar 10 >>> Foo.foovar 10

Si no tocamos foovar , es igual para f y para Foo . Pero si cambiamos f.foovar ...

>>> f.foovar = 5 >>> f.foovar 5 >>> Foo.foovar 10

... agregamos un atributo de instancia que enmascara efectivamente el valor de Foo.foovar . Ahora si cambiamos Foo.foovar directamente, no afecta nuestra instancia foo :

>>> Foo.foovar = 7 >>> f.foovar 5

Pero sí afecta una nueva instancia de foo :

>>> Foo(5).foovar 7

También tenga en cuenta que los objetos mutables añaden otra capa de indirección (como mgilson me recordó). Aquí, f.foovar refiere al mismo objeto que Foo.foovar , por lo que cuando modifica el objeto, los cambios se propagan por la jerarquía:

>>> Foo.foovar = [1] >>> f = Foo(5) >>> f.foovar[0] = 99 >>> Foo.foovar [99]


cuando intenta acceder a la variable con una clase, solo busca en ella

cls.__dict__

pero cuando intenta acceder a la variable con instancia se ve primero

self.__dict__

si lo encuentra, luego regresa o si no puede encontrarlo, entonces también busca

cls.__dict__

aquí cls es la clase

class Test: temp_1=10 temp_2=20 def __init__(self): self.test_1=10 self.test_2=20 @classmethod def c_test(cls): pass def t_method(self): pass print Test.__dict__ print Test().__dict__

Salida :

{''c_test'': <classmethod object at 0x7fede8f35a60>, ''__module__'': ''__main__'', ''t_method'': <function t_method at 0x7fede8f336e0>, ''temp_1'': 10, ''__doc__'': None, ''__init__'': <function __init__ at 0x7fede8f335f0>, ''temp_2'': 20} {''test_2'': 20, ''test_1'': 10}

Para atributo especial clase de detalle


self.element dentro del constructor es una variable de instancia (si un objeto nodo modifica su valor solo cambia para este objeto) donde el de la segunda versión es una variable de clase (por lo que si un objeto nodo modifica su valor, cambiará para todos objetos nodo).

La analogía en C ++ sería no estática frente a variables de miembros estáticos en su clase.


self.element en el init es una variable de instancia, puede obtener / configurarlo en cualquier otra función de miembro escribiendo self.element. El elemento declarado en la clase es la variable de clase, puede obtenerlo / configurar escribiendo Node.element.