¿Son posibles las variables estáticas de clase?
¿Es posible tener variables de clase estáticas o métodos en python? ¿Qué sintaxis se requiere para hacer esto?
16 answers
Las variables declaradas dentro de la definición de clase, pero no dentro de un método son variables de clase o estáticas:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
Como @ millerdev señala, esto crea una variable de nivel de clase i
, pero esto es distinto de cualquier variable de nivel de instancia i
, por lo que podría tener
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
Esto es diferente de C++ y Java, pero no tan diferente de C#, donde no se puede acceder a un miembro estático usando una referencia a una instancia.
Ver lo que el tutorial de Python tiene que decir sobre el tema de las clases y objetos de clase.
@Steve Johnson ya ha respondido con respecto a métodos estáticos , también documentados bajo "Funciones integradas" en la Referencia de la Biblioteca de Python .
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy recomienda classmethod s sobre staticmethod, ya que el método recibe el tipo de clase como primer argumento, pero todavía estoy un poco confuso sobre las ventajas de este enfoque sobre staticmethod. Si usted también, entonces probablemente no asunto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-06 13:00:27
@Blair Conrad dijo que las variables estáticas declaradas dentro de la definición de clase, pero no dentro de un método son variables de clase o "estáticas":
>>> class Test(object):
... i = 3
...
>>> Test.i
3
Hay algunos gotcha aquí. Continuando con el ejemplo anterior:
>>> t = Test()
>>> t.i # static variable accessed via instance
3
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i # we have not changed the static variable
3
>>> t.i # we have overwritten Test.i on t by creating a new attribute t.i
5
>>> Test.i = 6 # to change the static variable we do it by assigning to the class
>>> t.i
5
>>> Test.i
6
>>> u = Test()
>>> u.i
6 # changes to t do not affect new instances of Test
# Namespaces are one honking great idea -- let's do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__
{}
Observe cómo la variable de instancia t.i
salió de sincronización con la variable de clase "estática" cuando el atributo i
se estableció directamente en t
. Esto se debe a que i
fue re-enlazado dentro del espacio de nombres t
, que es distinto del espacio de nombres Test
. Si si desea cambiar el valor de una variable" estática", debe cambiarlo dentro del ámbito (u objeto) donde se definió originalmente. Pongo "static" entre comillas porque Python no tiene realmente variables estáticas en el sentido que C++ y Java tienen.
Aunque no dice nada específico sobre variables estáticas o métodos, el tutorial de Python tiene alguna información relevante sobre las clases y los objetos de clase.
@ Steve Johnson también respondió respecto a métodos estáticos, también documentados bajo "Funciones integradas" en la Referencia de Biblioteca de Python.
class Test(object):
@staticmethod
def f(arg1, arg2, ...):
...
@beid también mencionó classmethod, que es similar a staticmethod. El primer argumento de un classmethod es el objeto class. Ejemplo:
class Test(object):
i = 3 # class (or static) variable
@classmethod
def g(cls, arg):
# here we can use 'cls' instead of the class name (Test)
if arg > cls.i:
cls.i = arg # would the the same as Test.i = arg1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-28 00:15:27
Métodos estáticos y de Clase
Como las otras respuestas han señalado, los métodos estáticos y de clase se logran fácilmente utilizando los decoradores incorporados:
class Test(object):
# regular instance method:
def MyMethod(self):
pass
# class method:
@classmethod
def MyClassMethod(klass):
pass
# static method:
@staticmethod
def MyStaticMethod():
pass
Como de costumbre, el primer argumento de MyMethod()
está vinculado al objeto de instancia de clase. Por el contrario, el primer argumento de MyClassMethod()
es vinculado al objeto de clase en sí (por ejemplo, en este caso, Test
). Para MyStaticMethod()
, ninguno de los argumentos está vinculado, y tener argumentos en absoluto es opcional.
"Estática Variables "
Sin embargo, implementando "variables estáticas" (bueno, variables estáticas mutables, de todos modos, si eso no es una contradicción en términos...) no es tan sencillo. Como millerdev señaló en su respuesta, el problema es que los atributos de clase de Python no son realmente "variables estáticas". Considere:
class Test(object):
i = 3 # This is a class attribute
x = Test()
x.i = 12 # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i # ERROR
assert Test.i == 3 # Test.i was not affected
assert x.i == 12 # x.i is a different object than Test.i
Esto se debe a que la línea x.i = 12
ha agregado un nuevo atributo de instancia i
a x
en lugar de cambiar el valor de la clase Test
i
atributo.
Partial El comportamiento esperado de la variable estática, es decir, la sincronización del atributo entre varias instancias (pero no con la propia clase; ver "gotcha" a continuación), se puede lograr convirtiendo el atributo de clase en una propiedad:
class Test(object):
_i = 3
@property
def i(self):
return type(self)._i
@i.setter
def i(self,val):
type(self)._i = val
## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##
class Test(object):
_i = 3
def get_i(self):
return type(self)._i
def set_i(self,val):
type(self)._i = val
i = property(get_i, set_i)
Ahora puedes hacer: {[45]]}
x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i # no error
assert x2.i == 50 # the property is synced
La variable estática ahora permanecerá sincronizada entre todas las instancias de clase.
(NOTA: Es decir, a menos que una instancia de clase decida definir su propia versión de _i
! Pero si alguien decide hacer ESO, se merecen lo que reciben, ¿no???)
Tenga en cuenta que técnicamente hablando, i
todavía no es una 'variable estática' en absoluto; es un property
, que es un tipo especial de descriptor. Sin embargo, el comportamiento property
es ahora equivalente a una variable estática (mutable) sincronizada en todas las instancias de clase.
"Variables Estáticas"inmutables
Para el comportamiento inmutable de la variable estática, simplemente omita el property
setter:
class Test(object):
_i = 3
@property
def i(self):
return type(self)._i
## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##
class Test(object):
_i = 3
def get_i(self):
return type(self)._i
i = property(get_i)
Ahora al intentar establecer el atributo instance i
devolverá un AttributeError
:
x = Test()
assert x.i == 3 # success
x.i = 12 # ERROR
One Gotcha to be Aware of {[43]]}
Tenga en cuenta que los métodos anteriores solo funcionan con instancias de su clase - que no trabajar cuando se utiliza la propia clase. Así, por ejemplo:
x = Test()
assert x.i == Test.i # ERROR
# x.i and Test.i are two different objects:
type(Test.i) # class 'property'
type(x.i) # class 'int'
La línea assert Test.i == x.i
produce un error, porque el atributo i
de Test
y x
son dos objetos diferentes.
Mucha gente encontrará esto sorprendente. Sin embargo, no debería serlo. Si volvemos atrás e inspeccionamos nuestra definición de clase Test
(la segunda versión), tomamos nota de esta línea:
i = property(get_i)
Claramente, el miembro i
de Test
debe ser un objeto property
, que es el tipo de objeto devuelto por la función property
.
Si encuentra lo anterior confuso, lo más probable es que aún lo piense desde la perspectiva de otros lenguajes (por ejemplo, Java o c++). Deberías ir a estudiar el objeto property
, sobre el orden en que los atributos de Python se devuelven, el protocolo descriptor y el orden de resolución del método (MRO).
Presento una solución al 'gotcha' anterior a continuación; sin embargo, sugeriría - enérgicamente - que no intentes hacer algo como lo siguiente hasta que - como mínimo - entiendas completamente por qué assert Test.i = x.i
causa un error.
REAL, ACTUAL Variables estáticas - Test.i == x.i
Presento la solución (Python 3) a continuación solo con fines informativos. No lo estoy respaldando como un " buen solución". Tengo mis dudas sobre si emular el comportamiento de variables estáticas de otros lenguajes en Python es realmente necesario. Sin embargo, independientemente de si es realmente útil, lo siguiente debería ayudar a comprender mejor cómo funciona Python.
ACTUALIZACIÓN: este intento es realmente bastante horrible; si insistes en hacer algo como esto (sugerencia: por favor, no lo hagas; Python es un lenguaje muy elegante y hacer que se comporte como otro lenguaje simplemente no es necesario), use el código en La respuesta de Ethan Furman en su lugar.
Emulando el comportamiento de variables estáticas de otros lenguajes usando una metaclase
Una metaclase es la clase de una clase. La metaclase predeterminada para todas las clases en Python (es decir, las clases de "nuevo estilo" posteriores a Python 2.3, creo) es type
. Por ejemplo:
type(int) # class 'type'
type(str) # class 'type'
class Test(): pass
type(Test) # class 'type'
Sin embargo, puedes definir tu propia metaclase así: {[45]]}
class MyMeta(type): pass
Y aplicarlo a su propia clase de esta manera (Python 3 solamente):
class MyClass(metaclass = MyMeta):
pass
type(MyClass) # class MyMeta
A continuación se muestra una metaclase que he creado que intenta emular el comportamiento "variable estática" de otros lenguajes. Básicamente funciona reemplazando el getter, setter y deleter por defecto con versiones que comprueban si el atributo que se solicita es una "variable estática".
Un catálogo de las "variables estáticas" se almacena en el atributo StaticVarMeta.statics
. Todas las solicitudes de atributos se intentan resolver inicialmente utilizando un orden de resolución sustituto. He apodado esta es la "orden de resolución estática", o"SRO". Esto se hace buscando el atributo solicitado en el conjunto de "variables estáticas" para una clase dada (o sus clases padre). Si el atributo no aparece en el "SRO", la clase recurrirá al atributo predeterminado get/set/delete behavior (es decir, "MRO").
from functools import wraps
class StaticVarsMeta(type):
'''A metaclass for creating classes that emulate the "static variable" behavior
of other languages. I do not advise actually using this for anything!!!
Behavior is intended to be similar to classes that use __slots__. However, "normal"
attributes and __statics___ can coexist (unlike with __slots__).
Example usage:
class MyBaseClass(metaclass = StaticVarsMeta):
__statics__ = {'a','b','c'}
i = 0 # regular attribute
a = 1 # static var defined (optional)
class MyParentClass(MyBaseClass):
__statics__ = {'d','e','f'}
j = 2 # regular attribute
d, e, f = 3, 4, 5 # Static vars
a, b, c = 6, 7, 8 # Static vars (inherited from MyBaseClass, defined/re-defined here)
class MyChildClass(MyParentClass):
__statics__ = {'a','b','c'}
j = 2 # regular attribute (redefines j from MyParentClass)
d, e, f = 9, 10, 11 # Static vars (inherited from MyParentClass, redefined here)
a, b, c = 12, 13, 14 # Static vars (overriding previous definition in MyParentClass here)'''
statics = {}
def __new__(mcls, name, bases, namespace):
# Get the class object
cls = super().__new__(mcls, name, bases, namespace)
# Establish the "statics resolution order"
cls.__sro__ = tuple(c for c in cls.__mro__ if isinstance(c,mcls))
# Replace class getter, setter, and deleter for instance attributes
cls.__getattribute__ = StaticVarsMeta.__inst_getattribute__(cls, cls.__getattribute__)
cls.__setattr__ = StaticVarsMeta.__inst_setattr__(cls, cls.__setattr__)
cls.__delattr__ = StaticVarsMeta.__inst_delattr__(cls, cls.__delattr__)
# Store the list of static variables for the class object
# This list is permanent and cannot be changed, similar to __slots__
try:
mcls.statics[cls] = getattr(cls,'__statics__')
except AttributeError:
mcls.statics[cls] = namespace['__statics__'] = set() # No static vars provided
# Check and make sure the statics var names are strings
if any(not isinstance(static,str) for static in mcls.statics[cls]):
typ = dict(zip((not isinstance(static,str) for static in mcls.statics[cls]), map(type,mcls.statics[cls])))[True].__name__
raise TypeError('__statics__ items must be strings, not {0}'.format(typ))
# Move any previously existing, not overridden statics to the static var parent class(es)
if len(cls.__sro__) > 1:
for attr,value in namespace.items():
if attr not in StaticVarsMeta.statics[cls] and attr != ['__statics__']:
for c in cls.__sro__[1:]:
if attr in StaticVarsMeta.statics[c]:
setattr(c,attr,value)
delattr(cls,attr)
return cls
def __inst_getattribute__(self, orig_getattribute):
'''Replaces the class __getattribute__'''
@wraps(orig_getattribute)
def wrapper(self, attr):
if StaticVarsMeta.is_static(type(self),attr):
return StaticVarsMeta.__getstatic__(type(self),attr)
else:
return orig_getattribute(self, attr)
return wrapper
def __inst_setattr__(self, orig_setattribute):
'''Replaces the class __setattr__'''
@wraps(orig_setattribute)
def wrapper(self, attr, value):
if StaticVarsMeta.is_static(type(self),attr):
StaticVarsMeta.__setstatic__(type(self),attr, value)
else:
orig_setattribute(self, attr, value)
return wrapper
def __inst_delattr__(self, orig_delattribute):
'''Replaces the class __delattr__'''
@wraps(orig_delattribute)
def wrapper(self, attr):
if StaticVarsMeta.is_static(type(self),attr):
StaticVarsMeta.__delstatic__(type(self),attr)
else:
orig_delattribute(self, attr)
return wrapper
def __getstatic__(cls,attr):
'''Static variable getter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
try:
return getattr(c,attr)
except AttributeError:
pass
raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
def __setstatic__(cls,attr,value):
'''Static variable setter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
setattr(c,attr,value)
break
def __delstatic__(cls,attr):
'''Static variable deleter'''
for c in cls.__sro__:
if attr in StaticVarsMeta.statics[c]:
try:
delattr(c,attr)
break
except AttributeError:
pass
raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
def __delattr__(cls,attr):
'''Prevent __sro__ attribute from deletion'''
if attr == '__sro__':
raise AttributeError('readonly attribute')
super().__delattr__(attr)
def is_static(cls,attr):
'''Returns True if an attribute is a static variable of any class in the __sro__'''
if any(attr in StaticVarsMeta.statics[c] for c in cls.__sro__):
return True
return False
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-08 16:12:57
También puede agregar variables de clase a las clases sobre la marcha
>>> class X:
... pass
...
>>> X.bar = 0
>>> x = X()
>>> x.bar
0
>>> x.foo
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
>>> X.foo = 1
>>> x.foo
1
Y las instancias de clase pueden cambiar las variables de clase
class X:
l = []
def __init__(self):
self.l.append(1)
print X().l
print X().l
>python test.py
[1]
[1, 1]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-24 17:43:30
Personalmente usaría un método de clase cada vez que necesitara un método estático. Principalmente porque tengo la clase como argumento.
class myObj(object):
def myMethod(cls)
...
myMethod = classmethod(myMethod)
O utilizar un decorador
class myObj(object):
@classmethod
def myMethod(cls)
Para propiedades estáticas.. Es hora de buscar alguna definición de Python.. la variable siempre puede cambiar. Hay dos tipos de ellos mutables e inmutables.. Además, hay atributos de clase y atributos de instancia.. Nada como atributos estáticos en el sentido de java & c++
¿Por qué usar el método estático en sentido pitónico, si no tiene relación alguna con la clase! Si yo fuera tú, usaría classmethod o definiría el método independiente de la clase.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 23:29:49
Los métodos estáticos en python se llaman classmethods. Eche un vistazo al siguiente código
class MyClass:
def myInstanceMethod(self):
print 'output from an instance method'
@classmethod
def myStaticMethod(cls):
print 'output from a static method'
>>> MyClass.myInstanceMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method myInstanceMethod() must be called [...]
>>> MyClass.myStaticMethod()
output from a static method
Observe que cuando llamamos al método myInstanceMethod, obtenemos un error. Esto se debe a que requiere que el método sea llamado en una instancia de esta clase. El método myStaticMethod se establece como un classmethod usando el decorador @classmethod.
Solo por diversión y risitas, podríamos llamar myInstanceMethod en la clase pasando en una instancia de la clase, así:
>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-12 10:23:57
Una cosa especial a tener en cuenta sobre las propiedades estáticas y las propiedades de instancia, que se muestra en el siguiente ejemplo:
class my_cls:
my_prop = 0
#static property
print my_cls.my_prop #--> 0
#assign value to static property
my_cls.my_prop = 1
print my_cls.my_prop #--> 1
#access static property thru' instance
my_inst = my_cls()
print my_inst.my_prop #--> 1
#instance property is different from static property
#after being assigned a value
my_inst.my_prop = 2
print my_cls.my_prop #--> 1
print my_inst.my_prop #--> 2
Esto significa que antes de asignar el valor a la propiedad instance, si intentamos acceder a la propiedad a través de la instancia, se usa el valor estático. Cada propiedad declarada en la clase python siempre tiene una ranura estática en la memoria.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-08 06:06:05
Cuando se define alguna variable miembro fuera de cualquier método miembro, la variable puede ser estática o no estática dependiendo de cómo se expresa la variable.
- CLASSNAME.var es variable estática
- INSTANCENAME.var no es una variable estática.
- auto.var inside class no es una variable estática.
- var dentro de la función miembro de la clase no está definida.
Por ejemplo:
#!/usr/bin/python
class A:
var=1
def printvar(self):
print "self.var is %d" % self.var
print "A.var is %d" % A.var
a = A()
a.var = 2
a.printvar()
A.var = 3
a.printvar()
Los resultados son
self.var is 2
A.var is 1
self.var is 2
A.var is 3
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-03 11:37:36
También podría hacer que una clase sea estática usando metaclase.
class StaticClassError(Exception):
pass
class StaticClass:
__metaclass__ = abc.ABCMeta
def __new__(cls, *args, **kw):
raise StaticClassError("%s is a static class and cannot be initiated."
% cls)
class MyClass(StaticClass):
a = 1
b = 3
@staticmethod
def add(x, y):
return x+y
Entonces cada vez que por accidente intente inicializar MyClass obtendrá un StaticClassError.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-20 12:06:23
Un punto muy interesante sobre la búsqueda de atributos de Python es que se puede usar para crear"variables virtuales":
class A(object):
label="Amazing"
def __init__(self,d):
self.data=d
def say(self):
print("%s %s!"%(self.label,self.data))
class B(A):
label="Bold" # overrides A.label
A(5).say() # Amazing 5!
B(3).say() # Bold 3!
Normalmente no hay asignaciones a estos después de que se crean. Tenga en cuenta que la búsqueda utiliza self
porque, aunque label
es estático en el sentido de no estar asociado con una instancia particular, el valor todavía depende de la (clase de la) instancia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-17 17:19:31
Es posible tener variables de clase static
, pero probablemente no valga la pena el esfuerzo.
Aquí hay una prueba de concepto escrita en Python 3 if si alguno de los detalles exactos es incorrecto, el código se puede ajustar para que coincida con lo que quieras decir con static variable
:
class Static:
def __init__(self, value, doc=None):
self.deleted = False
self.value = value
self.__doc__ = doc
def __get__(self, inst, cls=None):
if self.deleted:
raise AttributeError('Attribute not set')
return self.value
def __set__(self, inst, value):
self.deleted = False
self.value = value
def __delete__(self, inst):
self.deleted = True
class StaticType(type):
def __delattr__(cls, name):
obj = cls.__dict__.get(name)
if isinstance(obj, Static):
obj.__delete__(name)
else:
super(StaticType, cls).__delattr__(name)
def __getattribute__(cls, *args):
obj = super(StaticType, cls).__getattribute__(*args)
if isinstance(obj, Static):
obj = obj.__get__(cls, cls.__class__)
return obj
def __setattr__(cls, name, val):
# check if object already exists
obj = cls.__dict__.get(name)
if isinstance(obj, Static):
obj.__set__(name, val)
else:
super(StaticType, cls).__setattr__(name, val)
Y en uso:
class MyStatic(metaclass=StaticType):
"""
Testing static vars
"""
a = Static(9)
b = Static(12)
c = 3
class YourStatic(MyStatic):
d = Static('woo hoo')
e = Static('doo wop')
Y algunas pruebas:
ms1 = MyStatic()
ms2 = MyStatic()
ms3 = MyStatic()
assert ms1.a == ms2.a == ms3.a == MyStatic.a
assert ms1.b == ms2.b == ms3.b == MyStatic.b
assert ms1.c == ms2.c == ms3.c == MyStatic.c
ms1.a = 77
assert ms1.a == ms2.a == ms3.a == MyStatic.a
ms2.b = 99
assert ms1.b == ms2.b == ms3.b == MyStatic.b
MyStatic.a = 101
assert ms1.a == ms2.a == ms3.a == MyStatic.a
MyStatic.b = 139
assert ms1.b == ms2.b == ms3.b == MyStatic.b
del MyStatic.b
for inst in (ms1, ms2, ms3):
try:
getattr(inst, 'b')
except AttributeError:
pass
else:
print('AttributeError not raised on %r' % attr)
ms1.c = 13
ms2.c = 17
ms3.c = 19
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
MyStatic.c = 43
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
ys1 = YourStatic()
ys2 = YourStatic()
ys3 = YourStatic()
MyStatic.b = 'burgler'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
assert ys1.d == ys2.d == ys3.d == YourStatic.d
assert ys1.e == ys2.e == ys3.e == YourStatic.e
ys1.a = 'blah'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
ys2.b = 'kelp'
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
ys1.d = 'fee'
assert ys1.d == ys2.d == ys3.d == YourStatic.d
ys2.e = 'fie'
assert ys1.e == ys2.e == ys3.e == YourStatic.e
MyStatic.a = 'aargh'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 09:02:25
Para evitar cualquier confusión potencial, me gustaría contrastar variables estáticas y objetos inmutables.
Algunos tipos de objetos primitivos como enteros, flotadores, cadenas y touples son inmutables en Python. Esto significa que el objeto al que se hace referencia por un nombre dado no puede cambiar si es de uno de los tipos de objeto mencionados anteriormente. El nombre se puede reasignar a un objeto diferente, pero el objeto en sí no se puede cambiar.
Hacer una variable estática lleva esto un paso más allá no permitiendo que el nombre de la variable apunte a ningún objeto excepto a aquel al que apunta actualmente. (Nota: este es un concepto de software general y no específico de Python; por favor, consulte las publicaciones de otros para obtener información sobre la implementación de estática en Python).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-17 04:01:08
La mejor manera que encontré es usar otra clase. Puede crear un objeto y luego usarlo en otros objetos.
class staticFlag:
def __init__(self):
self.__success = False
def isSuccess(self):
return self.__success
def succeed(self):
self.__success = True
class tryIt:
def __init__(self, staticFlag):
self.isSuccess = staticFlag.isSuccess
self.succeed = staticFlag.succeed
tryArr = []
flag = staticFlag()
for i in range(10):
tryArr.append(tryIt(flag))
if i == 5:
tryArr[i].succeed()
print tryArr[i].isSuccess()
Con el ejemplo anterior, hice una clase llamada staticFlag
.
Esta clase debe presentar el var estático __success
(Var Estático privado).
tryIt
class representa la clase regular que necesitamos usar.
Ahora hice un objeto para una bandera (staticFlag
). Esta bandera será enviada como referencia a todos los objetos regulares.
Todos estos objetos se están agregando a la lista tryArr
.
Este Script Resulta:
False
False
False
False
False
True
True
True
True
True
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-19 23:42:58
Absolutamente Sí, Python por sí mismo no tiene ningún miembro de datos estáticos explícitamente, pero podemos tener al hacerlo
class A:
counter =0
def callme (self):
A.counter +=1
def getcount (self):
return self.counter
>>> x=A()
>>> y=A()
>>> print(x.getcount())
>>> print(y.getcount())
>>> x.callme()
>>> print(x.getcount())
>>> print(y.getcount())
Salida
0
0
1
1
Explicación
here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 13:01:13
Con respecto a esta respuesta , para una variable estática constante, puede usar un descriptor. He aquí un ejemplo:
class ConstantAttribute(object):
'''You can initialize my value but not change it.'''
def __init__(self, value):
self.value = value
def __get__(self, obj, type=None):
return self.value
def __set__(self, obj, val):
pass
class Demo(object):
x = ConstantAttribute(10)
class SubDemo(Demo):
x = 10
demo = Demo()
subdemo = SubDemo()
# should not change
demo.x = 100
# should change
subdemo.x = 100
print "small demo", demo.x
print "small subdemo", subdemo.x
print "big demo", Demo.x
print "big subdemo", SubDemo.x
, Resultando en ...
small demo 10
small subdemo 100
big demo 10
big subdemo 10
Siempre puede plantear una excepción si ignorar silenciosamente el valor de ajuste (pass
anterior) no es lo suyo. Si está buscando una variable de clase estática de estilo Java en C++:
class StaticAttribute(object):
def __init__(self, value):
self.value = value
def __get__(self, obj, type=None):
return self.value
def __set__(self, obj, val):
self.value = val
Echa un vistazo a esta respuestay a los documentos oficiales HOWTO para obtener más información sobre los descriptores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:14
Variables estáticas en la fábrica de clase python3. 6
Para cualquiera que use una fábrica de clases con python3. 6 y arriba use la palabra clave nonlocal
para agregarla al ámbito / contexto de la clase que se está creando de la siguiente manera:
>>> def SomeFactory(some_var=None):
... class SomeClass(object):
... nonlocal some_var
... def print():
... print(some_var)
... return SomeClass
...
>>> SomeFactory(some_var="hello world").print()
hello world
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-01 02:56:08