Variáveis de classe estática são possíveis?
-
09-06-2019 - |
Pergunta
É possível ter variáveis ou métodos de classe estáticos em python?Qual sintaxe é necessária para fazer isso?
Solução
Variáveis declaradas dentro da definição de classe, mas não dentro de um método, são variáveis de classe ou estáticas:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
Como @millerdev aponta, isso cria um nível de classe i
variável, mas isso é distinto de qualquer nível de instância i
variável, então você poderia ter
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
Isso é diferente de C++ e Java, mas não tão diferente de C#, onde um membro estático não pode ser acessado usando uma referência a uma instância.
Ver o que o tutorial Python tem a dizer sobre classes e objetos de classe.
@Steve Johnson já respondeu sobre métodos estáticos, também documentado em "Funções integradas" na referência da biblioteca Python.
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy recomenda método de classes sobre o método estático, já que o método recebe o tipo de classe como o primeiro argumento, mas ainda estou um pouco confuso sobre as vantagens dessa abordagem sobre o método estático.Se você também estiver, provavelmente não importa.
Outras dicas
@Blair Conrad disse que variáveis estáticas declaradas dentro da definição de classe, mas não dentro de um método, são variáveis de classe ou "estáticas":
>>> class Test(object):
... i = 3
...
>>> Test.i
3
Existem algumas pegadinhas aqui.Continuando com o exemplo acima:
>>> 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 como a variável de instância t.i
saiu de sincronia com a variável de classe "estática" quando o atributo i
foi definido diretamente em t
.Isto é porque i
foi religado dentro do t
namespace, que é distinto do Test
espaço para nome.Se você quiser alterar o valor de uma variável "estática", deverá alterá-la dentro do escopo (ou objeto) onde ela foi originalmente definida.Coloquei "estático" entre aspas porque Python realmente não possui variáveis estáticas no sentido que C++ e Java possuem.
Embora não diga nada específico sobre variáveis ou métodos estáticos, o Tutorial de Python tem algumas informações relevantes sobre classes e objetos de classe.
@Steve Johnson também respondeu sobre métodos estáticos, também documentados em "Funções integradas" na referência da biblioteca Python.
class Test(object):
@staticmethod
def f(arg1, arg2, ...):
...
@beid também mencionou classmethod, que é semelhante ao staticmethod.O primeiro argumento de um método de classe é o objeto de classe.Exemplo:
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
Métodos estáticos e de classe
Como as outras respostas observaram, os métodos estáticos e de classe são facilmente realizados usando os decoradores integrados:
class Test(object):
# regular instance method:
def MyMethod(self):
pass
# class method:
@classmethod
def MyClassMethod(klass):
pass
# static method:
@staticmethod
def MyStaticMethod():
pass
Como sempre, o primeiro argumento a MyMethod()
está vinculado ao objeto de instância de classe.Em contrapartida, o primeiro argumento MyClassMethod()
é vinculado ao próprio objeto de classe (por exemplo, neste caso, Test
).Para MyStaticMethod()
, nenhum dos argumentos é vinculado e ter argumentos é opcional.
"Variáveis Estáticas"
No entanto, implementar "variáveis estáticas" (bem, mutável variáveis estáticas, de qualquer maneira, se isso não for uma contradição em termos...) não é tão simples.Como millerdev apontou em sua resposta, o problema é que os atributos de classe do Python não são verdadeiramente "variáveis estáticas".Considerar:
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
Isso ocorre porque a linha x.i = 12
adicionou um novo atributo de instância i
para x
em vez de alterar o valor do Test
aula i
atributo.
Parcial comportamento esperado da variável estática, ou seja, sincronização do atributo entre múltiplas instâncias (mas não com a própria aula;veja "pegadinha" abaixo), pode ser alcançado transformando o atributo de classe em uma propriedade:
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)
Agora você pode fazer:
x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i # no error
assert x2.i == 50 # the property is synced
A variável estática agora permanecerá sincronizada entre todas as instâncias de classe.
(OBSERVAÇÃO:Isto é, a menos que uma instância de classe decida definir sua própria versão do _i
!Mas se alguém decide fazer ISSO, merece o que recebe, não é???)
Observe que tecnicamente falando, i
ainda não é uma 'variável estática';é um property
, que é um tipo especial de descritor.No entanto, o property
o comportamento agora é equivalente a uma variável estática (mutável) sincronizada em todas as instâncias de classe.
"Variáveis estáticas" imutáveis
Para comportamento de variável estática imutável, simplesmente omita o property
normatizador:
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)
Agora tentando definir a instância i
atributo retornará um AttributeError
:
x = Test()
assert x.i == 3 # success
x.i = 12 # ERROR
Uma pegadinha para você estar ciente
Observe que os métodos acima funcionam apenas com instâncias da sua turma - eles vão não trabalhar ao usar a própria classe.Então, por exemplo:
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'
A linha assert Test.i == x.i
produz um erro, porque o i
atributo de Test
e x
são dois objetos diferentes.
Muitas pessoas acharão isso surpreendente.No entanto, não deveria ser.Se voltarmos e inspecionarmos nossos Test
definição de classe (a segunda versão), tomamos nota desta linha:
i = property(get_i)
Claramente, o membro i
de Test
deve ser um property
object, que é o tipo de objeto retornado do property
função.
Se você acha o que foi dito acima confuso, provavelmente ainda está pensando nisso da perspectiva de outras línguas (por exemplo,Java ou c++).Você deveria ir estudar o property
objeto, sobre a ordem em que os atributos Python são retornados, o protocolo descritor e a ordem de resolução do método (MRO).
Apresento abaixo uma solução para a 'pegadinha' acima;no entanto, eu sugeriria - vigorosamente - que você não tente fazer algo como o seguinte até que - no mínimo - você entenda completamente o porquê assert Test.i = x.i
causa um erro.
REAL, REAL Variáveis Estáticas - Test.i == x.i
Apresento a solução (Python 3) abaixo apenas para fins informativos.Não estou endossando isso como uma "boa solução".Tenho dúvidas se emular o comportamento da variável estática de outras linguagens em Python é realmente necessário.No entanto, independentemente de ser realmente útil, o que segue deve ajudar a compreender melhor como o Python funciona.
ATUALIZAR:esta tentativa é realmente horrível;se você insistir em fazer algo assim (dica:por favor, não;Python é uma linguagem muito elegante e simplesmente não é necessário forçá-lo a se comportar como outra linguagem), use o código em A resposta de Ethan Furman em vez de.
Emulando comportamento de variável estática de outras linguagens usando uma metaclasse
Uma metaclasse é a classe de uma classe.A metaclasse padrão para todas as classes em Python (ou seja, as classes de "novo estilo" pós-Python 2.3, acredito) é type
.Por exemplo:
type(int) # class 'type'
type(str) # class 'type'
class Test(): pass
type(Test) # class 'type'
No entanto, você pode definir sua própria metaclasse assim:
class MyMeta(type): pass
E aplique-o à sua própria classe assim (somente Python 3):
class MyClass(metaclass = MyMeta):
pass
type(MyClass) # class MyMeta
Abaixo está uma metaclasse que criei que tenta emular o comportamento de "variável estática" de outras linguagens.Basicamente funciona substituindo o getter, setter e deleter padrão por versões que verificam se o atributo solicitado é uma "variável estática".
Um catálogo das "variáveis estáticas" é armazenado no StaticVarMeta.statics
atributo.Todas as solicitações de atributos são inicialmente tentadas para serem resolvidas usando uma ordem de resolução substituta.Eu apelidei isso de "ordem de resolução estática" ou "SRO".Isto é feito procurando o atributo solicitado no conjunto de "variáveis estáticas" para uma determinada classe (ou suas classes pai).Se o atributo não aparecer no "SRO", a classe recorrerá ao comportamento padrão de obtenção/definição/exclusão do atributo (ou seja, "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
Você também pode adicionar variáveis de classe às classes dinamicamente
>>> 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
E as instâncias de classe podem alterar variáveis de classe
class X:
l = []
def __init__(self):
self.l.append(1)
print X().l
print X().l
>python test.py
[1]
[1, 1]
Pessoalmente, eu usaria um método de classe sempre que precisasse de um método estático.Principalmente porque recebo a aula como argumento.
class myObj(object):
def myMethod(cls)
...
myMethod = classmethod(myMethod)
ou use um decorador
class myObj(object):
@classmethod
def myMethod(cls)
Para propriedades estáticas..É hora de você procurar alguma definição de python.variável sempre pode mudar.Existem dois tipos deles, mutáveis e imutáveis.Além disso, existem atributos de classe e atributos de instância.Nada realmente como atributos estáticos no sentido de java e c++
Por que usar o método estático no sentido pitônico, se ele não tem nenhuma relação com a classe!Se eu fosse você, usaria classmethod ou definiria o método independente da classe.
Uma coisa especial a ser observada sobre propriedades estáticas e propriedades de instância, mostradas no exemplo abaixo:
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
Isso significa que antes de atribuir o valor à propriedade da instância, se tentarmos acessar a propriedade através da instância, o valor estático será usado. Cada propriedade declarada na classe python sempre possui um slot estático na memória.
Métodos estáticos em python são chamados método de classeS.Dê uma olhada no código a seguir
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 quando chamamos o método meuInstanceMethod, obtemos um erro.Isso ocorre porque exige que o método seja chamado em uma instância desta classe.O método meu método estático é definido como um método de classe usando o decorador @classmethod.
Só por diversão e risadas, poderíamos ligar meuInstanceMethod na classe passando uma instância da classe, assim:
>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
Ao definir alguma variável de membro fora de qualquer método de membro, a variável pode ser estática ou não estática, dependendo de como a variável é expressa.
- CLASSNAME.var é uma variável estática
- INSTANCENAME.var não é uma variável estática.
- self.var dentro da classe não é uma variável estática.
- var dentro da função de membro da classe não está definida.
Por exemplo:
#!/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()
Os resultados são
self.var is 2
A.var is 1
self.var is 2
A.var is 3
Você também pode impor que uma classe seja estática usando metaclasse.
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
Então sempre que por acidente você tentar inicializar Minha classe você receberá um StaticClassError.
É possível ter static
variáveis de classe, mas provavelmente não vale o esforço.
Aqui está uma prova de conceito escrita em Python 3 - se algum dos detalhes exatos estiver errado, o código pode ser ajustado para corresponder ao que você entende por 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)
e em 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')
e alguns testes:
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
Um ponto muito interessante sobre a pesquisa de atributos do Python é que ela pode ser usada para criar "virtual variáveis":
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 não há atribuições para eles depois de criados.Observe que a pesquisa usa self
porque, embora label
é estático no sentido de não estar associado a um especial instância, o valor ainda depende da (classe da) instância.
Em relação a isso responder, para constante variável estática, você pode usar um descritor.Aqui está um exemplo:
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 em ...
small demo 10
small subdemo 100
big demo 10
big subdemo 10
Você sempre pode gerar uma exceção se ignorar silenciosamente o valor da configuração (pass
acima) não é sua praia.Se você estiver procurando por uma variável de classe estática no estilo C++ e Java:
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
Dê uma olhada em esta resposta e os documentos oficiais COMO para obter mais informações sobre descritores.
Absolutamente sim, python por si só não tem nenhum membro estático de dados explicitamente, mas podemos ter fazendo isso
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())
saída
0
0
1
1
explicação
here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"
Para evitar qualquer confusão potencial, gostaria de contrastar variáveis estáticas e objetos imutáveis.
Alguns tipos de objetos primitivos, como inteiros, flutuantes, strings e tuplas, são imutáveis em Python.Isso significa que o objeto referido por um determinado nome não pode mudar se for de um dos tipos de objeto mencionados acima.O nome pode ser reatribuído a um objeto diferente, mas o objeto em si não pode ser alterado.
Tornar uma variável estática vai um passo além, impedindo que o nome da variável aponte para qualquer objeto, exceto aquele para o qual ela aponta atualmente.(Observação:este é um conceito geral de software e não específico do Python;consulte as postagens de outras pessoas para obter informações sobre a implementação de estática em Python).
A melhor maneira que encontrei é usar outra classe.Você pode criar um objeto e usá-lo em outros 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()
Com o exemplo acima, criei uma classe chamada staticFlag
.
Esta classe deve apresentar a var estática __success
(Var estática privada).
tryIt
class representou a classe regular que precisamos usar.
Agora fiz um objeto para uma bandeira (staticFlag
).Este flag será enviado como referência para todos os objetos regulares.
Todos esses objetos estão sendo adicionados à lista tryArr
.
Este script resulta:
False
False
False
False
False
True
True
True
True
True
Sim, definitivamente é possível escrever variáveis e métodos estáticos em python.
Variáveis estáticas:Variáveis declaradas em nível de classe são chamadas de variáveis estáticas que podem ser acessadas diretamente usando o nome da classe.
>>> class A:
...my_var = "shagun"
>>> print(A.my_var)
shagun
Variáveis de instância: Variáveis relacionadas e acessadas pela instância de uma classe são variáveis de instância.
>>> a = A()
>>> a.my_var = "pruthi"
>>> print(A.my_var,a.my_var)
shagun pruthi
Métodos estáticos: Semelhante às variáveis, os métodos estáticos podem ser acessados diretamente usando a classe Name.Não há necessidade de criar uma instância.
Mas lembre-se de que um método estático não pode chamar um método não estático em python.
>>> class A:
... @staticmethod
... def my_static_method():
... print("Yippey!!")
...
>>> A.my_static_method()
Yippey!!
Variáveis estáticas na classe factory python3.6
Para qualquer pessoa que use uma fábrica de classes com python3.6 e para cima use o nonlocal
palavra-chave para adicioná-la ao escopo/contexto da classe que está sendo criada assim:
>>> 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
Simplesmente crie uma classe que contenha quaisquer tipos de variável ou objetos.Acesse variáveis usando o nome da classe como abaixo:
class StaticVariable:
myvar1 = 1
myvar2 = 2
StaticVariable.myvar1 = StaticVariable.myvar1 +1
StaticVariable.myvar2 = StaticVariable.myvar2 +1