¿Cómo accedo a las variables de miembro de clase?

7 minutos de lectura

Avatar de usuario de Adam
Adán

class Example(object):
    def the_example(self):
        itsProblem = "problem"

theExample = Example()
print(theExample.itsProblem)

¿Cómo accedo a la variable de una clase? He intentado agregar esta definición:

def return_itsProblem(self):
    return itsProblem

Sin embargo, eso también falla.

  • Título editado, pregunta en realidad sobre variables “estáticas” de clase: stackoverflow.com/questions/707380/…

    – Ciro Santilli OurBigBook.com

    28 de marzo de 2017 a las 13:49

avatar de usuario de e-satis
e-satis

La respuesta, en pocas palabras.

En tu ejemplo, itsProblem es una variable local.

Tu debes usar self para establecer y obtener variables de instancia. Puedes configurarlo en el __init__ método. Entonces tu código sería:

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Pero si desea una variable de clase verdadera, use el nombre de la clase directamente:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)

Pero ten cuidado con este, ya que theExample.itsProblem se establece automáticamente para ser igual a Example.itsProblempero no es la misma variable en absoluto y se puede cambiar de forma independiente.

Algunas explicaciones

En Python, las variables se pueden crear dinámicamente. Por lo tanto, puede hacer lo siguiente:

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 

huellas dactilares

Verdadero

Por lo tanto, eso es exactamente lo que haces con los ejemplos anteriores.

De hecho, en Python usamos self como thispero es un poco más que eso. self es el primer argumento de cualquier método de objeto porque el primer argumento es siempre la referencia del objeto. Esto es automático, ya sea que lo llames self O no.

Lo que significa que puedes hacer:

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

o:

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Es exactamente lo mismo. El primer argumento de CUALQUIER método de objeto es el objeto actual, solo lo llamamos self como convención. Y agrega solo una variable a este objeto, de la misma manera que lo haría desde afuera.

Ahora, sobre las variables de clase.

Cuando tu lo hagas:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Notarás que primero establecer una variable de claseluego accedemos una variable de objeto (instancia). Nunca configuramos esta variable de objeto pero funciona, ¿cómo es eso posible?

Bueno, Python intenta obtener primero la variable del objeto, pero si no puede encontrarla, le dará la variable de clase. Advertencia: la variable de clase se comparte entre instancias y la variable de objeto no.

Como conclusión, nunca use variables de clase para establecer valores predeterminados para variables de objeto. Usar __init__ para eso.

Eventualmente, aprenderá que las clases de Python son instancias y, por lo tanto, objetos en sí mismos, lo que brinda una nueva perspectiva para comprender lo anterior. Vuelve y lee esto de nuevo más tarde, una vez que te des cuenta.

  • usted dice: “theExample.itsProblem se configura automáticamente para que sea igual a Example.itsProblem, pero no es la misma variable en absoluto y se puede cambiar de forma independiente”, pero eso no es del todo correcto, y su frase es engañosa. Confío en que sabe lo que está pasando allí, así que sugiero reformular eso: “es es la misma variable, pero se puede volver a vincular de forma independiente para cada objeto”.

    – jsbueno

    8 de agosto de 2010 a las 14:39

  • Sí, pero el enlace es un concepto de alguien para otro lenguaje de programación como Java o C (como sospecho que es el OP) que es completamente desconocido. Luego me gustaría explicar qué es el enlace, luego el enlace tardío, luego el problema con las referencias en objetos mutables. Sería demasiado largo. Creo que en algún momento debes sacrificar la precisión en el altar de la comprensión.

    – e-satis

    9 de agosto de 2010 a las 12:57

  • También está (creo que esto puede ser 2.7+) el decorador @classmethod, que vale la pena investigar. discusión interesante aquí – stackoverflow.com/questions/12179271/…

    – jsh

    8 de marzo de 2013 a las 16:55

  • vinculación de nombres: creo que es una mala idea dar declaraciones falsas, sin importar el nivel. Sugiero esta ligera edición: pero tenga cuidado con este, ya que theExample.itsProblem se establece automáticamente para ser igual a Example.itsProblem, pero, desde una perspectiva práctica*, no es la misma variable en absoluto y se puede cambiar de forma independiente. *: en realidad comienza como el mismo objeto, pero es muy fácil cambiarlo accidentalmente si no entiendes Python enlace de nombre

    – n611x007

    22/04/2014 a las 20:45


avatar de usuario de kennytm
kennytm

Está declarando una variable local, no una variable de clase. Para establecer una variable de instancia (atributo), utilice

class Example(object):
    def the_example(self):
        self.itsProblem = "problem"  # <-- remember the 'self.'

theExample = Example()
theExample.the_example()
print(theExample.itsProblem)

Para establecer un variable de clase (también conocido como miembro estático), uso

class Example(object):
    def the_example(self):
        Example.itsProblem = "problem"
        # or, type(self).itsProblem = "problem"
        # depending what you want to do when the class is derived.

  • Excepto que las variables de clase se declaran una vez a nivel de clase. Tu camino lo restablecerá en cada instanciación, esto realmente no es lo que quieres. Consulte también stackoverflow.com/questions/2709821/python-self-explained para conocer la lógica detrás del yo explícito.

    usuario395760

    8 de agosto de 2010 a las 14:07


avatar de usuario de andrew pate
paté andrés

Si tiene una función de instancia (es decir, una que se pasa a sí misma), puede usarla para obtener una referencia a la clase usando self.__class__

Por ejemplo, en el siguiente código, tornado crea una instancia para manejar las solicitudes de obtención, pero podemos obtener el get_handler class y utilícelo para mantener un cliente riak para que no necesitemos crear uno para cada solicitud.

import tornado.web
import riak

class get_handler(tornado.web.requestHandler):
    riak_client = None

    def post(self):
        cls = self.__class__
        if cls.riak_client is None:
            cls.riak_client = riak.RiakClient(pb_port=8087, protocol="pbc")
        # Additional code to send response to the request ...
    

  • Este es un muy buen ejemplo para demostrar la pregunta del título original de OP. En realidad, el ejemplo de OP no coincide con el título y otras respuestas se refieren al ejemplo. De todos modos, esta es la mejor manera de acceder a una variable de nivel de clase porque no viola el principio DRY. Como lo hacen algunos de los otros ejemplos. Es mejor usar self.__class__ en lugar de repetir el nombre de la clase. Hace que el código esté preparado para el futuro, facilita la refactorización y, si se atreve a usar subclases, esto también puede tener ventajas.

    – mit

    26 de septiembre de 2020 a las 10:43

  • Se debe advertir a los lectores que el uso de un controlador como el anterior puede generar problemas no solo en aplicaciones que no son de un solo subproceso. Múltiples instancias de la clase podrían, en teoría, usar el mismo controlador en paralelo, y si el controlador no está diseñado para hacer esto, lo que depende de su estructura interna, es posible que no funcione. ‘En paralelo’ en una aplicación de un solo subproceso significa que la instancia de primera clase no ha terminado de usar el controlador y luego una segunda instancia comienza a usar el controlador. En tales casos, se podría recomendar utilizar una variable de instancia en su lugar.

    – mit

    26 de septiembre de 2020 a las 10:43


  • cls = self.__class__ era exactamente lo que necesitaba.

    – khaz

    7 abr a las 8:23

avatar de usuario del alcalde
alcalde

¡Implemente la declaración de retorno como el ejemplo a continuación! Deberías ser bueno. Espero que esto ayude a alguien..

class Example(object):
    def the_example(self):
        itsProblem = "problem"
        return itsProblem 


theExample = Example()
print theExample.the_example()

Si tienes un @classmethod método estáticosiempre tienes la clase como primer parámetro:

class Example(object):
    itsProblem = "problem"

    @classmethod
    def printProblem(cls):
        print(cls.itsProblem)

Example.printProblem()

¿Ha sido útil esta solución?