ross rogers
Si tengo el siguiente código:
class Foo(object):
bar = 1
def bah(self):
print(bar)
f = Foo()
f.bah()
se queja
NameError: el nombre global ‘bar’ no está definido
¿Cómo puedo acceder a la clase/variable estática? bar
dentro del método bah
?
En vez de bar
usar self.bar
o Foo.bar
. Asignando a Foo.bar
creará una variable estática, y asignando a self.bar
creará una variable de instancia.
-
Foo.bar funcionará, pero self.bar crea una variable de instancia, no una estática.
– camawyr
1 de abril de 2009 a las 21:55
-
bedwyr, “print self.bar” no creará ninguna variable de instancia (aunque la asignación a self.bar sí lo hará).
– Constantino
1 de abril de 2009 a las 22:14
-
@Constantin: no me di cuenta de eso, es una distinción interesante. Gracias por la corrección 🙂
– camawyr
3 de abril de 2009 a las 1:14
-
Pero si no tiene la intención de que haya un ivar, es más claro usar Foo.classmember.
– mk12
13 de septiembre de 2009 a las 20:58
-
cuando se usan variables estáticas, es una buena idea leer las trampas desde aquí: stackoverflow.com/questions/68645/… . @Constantin da una de las muchas trampas.
– Trevor Boyd Smith
21 de marzo de 2017 a las 16:27
vartec
Definir método de clase:
class Foo(object):
bar = 1
@classmethod
def bah(cls):
print cls.bar
Ahora si bah()
tiene que ser un método de instancia (es decir, tener acceso a uno mismo), aún puede acceder directamente a la variable de clase.
class Foo(object):
bar = 1
def bah(self):
print self.bar
-
¿Por qué no solo Foo.bar, en lugar de self.__class__.bar?
– mk12
13 de septiembre de 2009 a las 20:59
-
@Mk12: cuando tiene herencia de clase, una “variable de clase” podría estar en una clase base o una subclase. ¿A cuál quieres referirte? Depende de lo que estés tratando de hacer. Foo.bar siempre se referiría a un atributo de la clase especificada, que podría ser una clase base o una subclase. self.__class__.bar se referiría a cualquier clase de la que sea tipo la instancia.
–Craig McQueen
11 de diciembre de 2009 a las 4:47
-
Ahora hemos llegado a ese desafortunado punto en el que somos tan conscientes de los detalles del lenguaje que podemos discriminar entre dos casos de uso finamente armonizados. De hecho, depende de lo que quieras hacer, pero muchas personas no prestarán atención a tales sutilezas.
– holdenweb
14 de diciembre de 2011 a las 10:19
-
Por cierto, este es un uso RARO de “variable de clase”. Mucho más común tenerlo definido en una clase específica, aquí Foo. Esta es información útil para algunas situaciones de programación avanzada. Pero es casi seguro que no es lo que la pregunta original quería como respuesta (cualquiera que necesite ESTA respuesta ya sabrá cómo hacer Foo.bar). +1 porque aprendí algo de esto.
– El fabricante de herramientas Steve
25 de noviembre de 2013 a las 17:05
-
Estoy aprendiendo sobre cuándo usar variables y métodos de clase (a diferencia de variables y métodos de instancia). Cuando desea acceder a una variable de clase en un método de instancia, ¿es necesario usar self.__class__.bar? Noté que self.bar funciona aunque bar es una variable de clase, no una variable de instancia.
– Factura
29/03/2015 a las 18:30
david berger
Como con todos los buenos ejemplos, ha simplificado lo que realmente está tratando de hacer. Esto es bueno, pero vale la pena señalar que python tiene un lote de flexibilidad cuando se trata de variables de clase versus instancia. Lo mismo puede decirse de los métodos. Para una buena lista de posibilidades, recomiendo leer Introducción a las clases de nuevo estilo de Michael Fötschespecialmente las secciones 2 a 6.
Una cosa que cuesta mucho trabajo recordar al empezar es que pitón no es java. Más que un simple cliché. En java, se compila una clase completa, lo que hace que la resolución del espacio de nombres sea realmente simple: cualquier variable declarada fuera de un método (en cualquier lugar) es una variable de instancia (o, si es estática, de clase) y es accesible implícitamente dentro de los métodos.
Con python, la gran regla general es que hay tres espacios de nombres que se buscan, en orden, para las variables:
- La función/método
- El módulo actual
- Construidos
{begin pedagogy}
Hay excepciones limitadas a esto. El principal que se me ocurre es que, cuando se carga una definición de clase, la definición de clase es su propio espacio de nombres implícito. Pero esto dura solo mientras se carga el módulo, y se omite por completo cuando se encuentra dentro de un método. De este modo:
>>> class A(object):
foo = 'foo'
bar = foo
>>> A.foo
'foo'
>>> A.bar
'foo'
pero:
>>> class B(object):
foo = 'foo'
def get_foo():
return foo
bar = get_foo()
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
class B(object):
File "<pyshell#11>", line 5, in B
bar = get_foo()
File "<pyshell#11>", line 4, in get_foo
return foo
NameError: global name 'foo' is not defined
{end pedagogy}
Al final, lo que hay que recordar es que usted hacer tener acceso a cualquiera de las variables a las que desea acceder, pero probablemente no implícitamente. Si sus objetivos son simples y directos, probablemente sea suficiente optar por Foo.bar o self.bar. Si su ejemplo se está volviendo más complicado, o quiere hacer cosas sofisticadas como la herencia (¡puede heredar métodos estáticos/de clase!), o la idea de referirse al nombre de su clase dentro de la clase en sí le parece incorrecta, consulte la introducción que vinculé.
-
IIRC, técnicamente se han buscado 3 (+) espacios de nombres: función local, módulo/global e incorporados. Ámbitos anidados significa que se pueden buscar varios ámbitos locales, pero ese es uno de los casos excepcionales. (…)
–Jeff Shannon
2 de abril de 2009 a las 8:52
-
Además, tendría cuidado al decir ‘módulo principal’, ya que es el módulo que contiene la función el que se busca, no el principal módulo… Y buscar el atributo de una referencia de instancia es algo diferente, pero esta respuesta explica por qué necesita la referencia de instancia/clase.
–Jeff Shannon
2 de abril de 2009 a las 8:57
Allan Mwesigwa
class Foo(object):
bar = 1
def bah(self):
print Foo.bar
f = Foo()
f.bah()
Parik Chudasma
bar
es su variable estática y puede acceder a ella usando Foo.bar
.
Básicamente, debe calificar su variable estática con el nombre de clase.
-
Considere agregar más información para ampliar su respuesta, o considere editar otras respuestas para agregar este detalle.
– Usuario1010
5 de enero de 2021 a las 18:59
Puedes acceder variables de clase por objeto y directamente por nombre de la clase desde el exterior o el interior de la clase y, básicamente, debe acceder variables de clase directamente por nombre de la clase porque si hay la misma clase de nombre y variables de instancia, variable de instancia del mismo nombre se prioriza mientras variable de instancia del mismo nombre se ignora cuando se accede por objeto. Entonces, usando nombre de la clase es más seguro que usar objeto acceder variables de clase.
Por ejemplo, puede acceder a la variable de clase por objeto y directamente por nombre de clase desde fuera de la clase, como se muestra a continuación:
class Person:
name = "John" # Class variable
obj = Person()
print(obj.name) # By object
print(Person.name) # By class name
Producción:
John
John
Pero, si agrega la misma variable de instancia de nombre que la variable de clase por objeto:
class Person:
name = "John" # Class variable
obj = Person()
obj.name = "Tom" # Adds the same name instance variable as class variable
print(obj.name) # By object
print(Person.name) # By class name
O, si agrega la misma variable de instancia de nombre que la variable de clase por self
en __init__()
:
class Person:
name = "John" # Class variable
def __init__(self, name):
self.name = name # Adds the same name instance variable as class variable
obj = Person("Tom")
print(obj.name) # By object
print(Person.name) # By class name
La misma variable de instancia de nombre tiene prioridad cuando se accede por objeto:
Tom # By object
John # By class name
Y, también puede acceder a la variable de clase por self
y directamente por nombre de clase desde el interior del método de instancia como se muestra a continuación:
class Person:
name = "John" # Class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # By class name
obj = Person()
obj.test()
Producción:
John
John
Pero, si agrega la misma variable de instancia de nombre que la variable de clase por objeto:
class Person:
name = "John" # Class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # By class name
obj = Person()
obj.name = "Tom" # Adds the same name instance variable as the class variable
obj.test()
O, si agrega la misma variable de instancia de nombre que la variable de clase por self
en __init__()
:
class Person:
name = "John" # Class variable
def __init__(self, name):
self.name = name # Adds the same name instance variable as the class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # Directly by class name
obj = Person("Tom")
obj.test()
La misma variable de instancia de nombre tiene prioridad cuando se accede a ella self
:
Tom # By "self"
John # By class name
-
Considere agregar más información para ampliar su respuesta, o considere editar otras respuestas para agregar este detalle.
– Usuario1010
5 de enero de 2021 a las 18:59
Puede encontrar más información sobre Python y la estática aquí: stackoverflow.com/questions/68645/python-static-variable
– camawyr
1 de abril de 2009 a las 21:57