variable resueltos polimorfismo metodos importar ejercicios clases python class static class-variables

python - resueltos - ¿Son posibles las variables de clase estática?



python class variables (16)

Variables estáticas en la clase de fábrica python3.6

Para cualquiera que use una fábrica de clases con python3.6 y más, use la palabra clave nonlocal para agregarla al ámbito / contexto de la clase que se está creando así:

>>> 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

¿Es posible tener variables de clase estáticas o métodos en python? ¿Qué sintaxis se requiere para hacer esto?


Métodos estáticos y de clase

Como han señalado las otras respuestas, los métodos estáticos y de clase se logran fácilmente utilizando los 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 de costumbre, el primer argumento de MyMethod() está vinculado al objeto de instancia de clase. En contraste, el primer argumento de MyClassMethod() está vinculado al objeto de clase en sí (por ejemplo, en este caso, Test ). Para MyStaticMethod() , ninguno de los argumentos está enlazado, y tener argumentos es opcional.

"Variables Estáticas"

Sin embargo, implementar "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 señaló Millerdev en su respuesta , el problema es que los atributos de clase de Python no son realmente "variables 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

Esto se debe a que la línea xi = 12 ha agregado un nuevo atributo de instancia i a x lugar de cambiar el valor del atributo de clase de Test i .

El comportamiento parcial esperado de la variable estática, es decir, la sincronización del atributo entre varias instancias (pero no con la clase en sí; consulte "gotcha" a continuación), se puede lograr al convertir 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:

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, merece lo que obtiene, ¿no?)

Tenga en cuenta que técnicamente hablando, i todavía no es una "variable estática" en absoluto; Es una property , que es un tipo especial de descriptor. Sin embargo, el comportamiento de la property ahora es equivalente a una variable estática (mutable) sincronizada en todas las instancias de clase.

"Variables estáticas" inmutables

Para un comportamiento de variable estática inmutable, simplemente omita el property :

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, intentar establecer el atributo de instancia i devolverá un AttributeError :

x = Test() assert x.i == 3 # success x.i = 12 # ERROR

Uno tiene que ser consciente de

Tenga en cuenta que los métodos anteriores solo funcionan con instancias de su clase; no funcionarán cuando se use la clase en sí . 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 que assert Test.i == xi produce un error, porque el atributo i de Test x son dos objetos diferentes.

Muchas personas encontrarán esto sorprendente. Sin embargo, no debería ser. Si regresamos e inspeccionamos nuestra definición de clase de 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 de property , que es el tipo de objeto devuelto por la función de property .

Si encuentra confuso lo anterior, lo más probable es que todavía esté pensando en ello desde la perspectiva de otros idiomas (por ejemplo, Java o c ++). Debe estudiar el objeto de property , sobre el orden en que se devuelven los atributos de Python, el protocolo del descriptor y el orden de resolución del método (MRO).

A continuación presento una solución al ''gotcha'' anterior; sin embargo, sugeriría, enérgicamente, que no intente hacer algo como lo siguiente hasta que, como mínimo, entienda completamente por qué assert Test.i = xi causa un error.

Variables estáticas REALES, REALES - Test.i == xi

Presento la solución (Python 3) a continuación solo con fines informativos. No lo estoy respaldando como una "buena solución". Tengo mis dudas sobre si es realmente necesario emular el comportamiento variable estático de otros lenguajes en Python. Sin embargo, independientemente de si es realmente útil, lo siguiente debe ayudar a comprender mejor cómo funciona Python.

ACTUALIZACIÓN: este intento es realmente horrible ; si insiste en hacer algo como esto (consejo: por favor, no; Python es un lenguaje muy elegante y no es necesario que se comporte como si fuera otro idioma), use el código de la respuesta de Ethan Furman .

Emulando el comportamiento variable variable 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" después de Python 2.3, creo) es de 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 como esta:

class MyMeta(type): pass

Y aplícalo a tu propia clase como esta (solo Python 3):

class MyClass(metaclass = MyMeta): pass type(MyClass) # class MyMeta

A continuación se muestra una metaclase que he creado que intenta emular el comportamiento de "variable estática" de otros idiomas. Básicamente, funciona al reemplazar el getter, setter y deleter predeterminados con versiones que verifican 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 una orden de resolución sustituta. He llamado a esto el "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 primarias). Si el atributo no aparece en el "SRO", la clase recurrirá al comportamiento predeterminado de obtención / ajuste / eliminación del atributo (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


@Blair Conrad dijo que las variables estáticas declaradas dentro de la definición de la clase, pero no dentro de un método son variables de clase o "estáticas":

>>> class Test(object): ... i = 3 ... >>> Test.i 3

Hay unos cuantos 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 ti se desincronizó con la variable de clase "estática" cuando el atributo i se estableció directamente en t . Esto se debe a que i volví a enlazar dentro del espacio de nombres t , que es distinto del espacio de nombres de Test . Si desea cambiar el valor de una variable "estática", debe cambiarlo dentro del alcance (u objeto) donde se definió originalmente. Pongo "estático" entre comillas porque Python realmente no tiene variables estáticas en el sentido en que C ++ y Java sí.

Aunque no dice nada específico sobre variables o métodos estáticos, el tutorial de Python tiene información relevante sobre las clases y los objetos de clase .

@Steve Johnson también respondió con respecto a los métodos estáticos, también documentados en "Funciones incorporadas" en la Referencia de la biblioteca de Python.

class Test(object): @staticmethod def f(arg1, arg2, ...): ...

@beid también mencionó el método de clase, que es similar al método estático. El primer argumento de un método de clase es el objeto de clase. 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


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"


Con respecto a esta answer , para una variable estática constante , puedes usar un descriptor. Aquí hay 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 generar una excepción si ignorar el valor de configuración ( pass arriba) no es lo suyo. Si está buscando una variable de clase estática de estilo C ++, 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

Eche un vistazo a esta respuesta y al HOWTO documentos oficiales para obtener más información sobre los descriptores.


Cuando se define una variable miembro fuera de cualquier método miembro, la variable puede ser estática o no estática, dependiendo de cómo se exprese la variable.

  • CLASSNAME.var es una variable estática
  • INSTANCENAME.var no es una variable estática.
  • self.var dentro de la clase no es variable estática.
  • var dentro de la función miembro de clase no está definido.

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


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: si alguno de los detalles exactos es incorrecto, se puede modificar el código para que coincida con lo que quiere decir con una 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


La mejor manera que encontré es usar otra clase. Puedes 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 la var estática __success (Var. Estática privada).

tryIt clase tryIt representó 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 .

Los resultados de este script:

False False False False False True True True True True


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 señala @ millerdev , esto crea una variable i nivel de clase, pero esto es distinto de cualquier variable i nivel de instancia, por lo que podría haber

>>> 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.

Vea lo que el tutorial de Python tiene que decir sobre el tema de las clases y los objetos de clase .

@Steve Johnson ya ha respondido con respecto a los métodos estáticos , también documentados en "Funciones integradas " en la Referencia de la biblioteca de Python .

class C: @staticmethod def f(arg1, arg2, ...): ...

@beidy recomienda classmethod s over staticmethod, ya que el método recibe el tipo de clase como el primer argumento, pero todavía estoy un poco confuso sobre las ventajas de este enfoque sobre el método static. Si usted también lo es, entonces probablemente no importa.


Los métodos estáticos en python se denominan classmethod s. Echa 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 se llame a un método en una instancia de esta clase. El método myStaticMethod se establece como un método de clase utilizando el decorator @classmethod .

Sólo para dar patadas y risitas, podríamos llamar a myInstanceMethod en la clase pasando una instancia de la clase, de esta manera:

>>> MyClass.myInstanceMethod(MyClass()) output from an instance method


Para evitar posibles confusiones, me gustaría contrastar variables estáticas y objetos inmutables.

Algunos tipos de objetos primitivos como enteros, flotantes, cadenas y touples son inmutables en Python. Esto significa que el objeto al que hace referencia 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á al impedir que el nombre de la variable apunte a cualquier objeto que no sea el que señala actualmente. (Nota: este es un concepto general de software y no es específico de Python; consulte las publicaciones de otros para obtener información sobre la implementación de estáticas en Python).


Personalmente usaría un método de clase siempre que necesitara un método estático. Principalmente porque entiendo la clase como argumento.

class myObj(object): def myMethod(cls) ... myMethod = classmethod(myMethod)

o usa 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 que son mutables e inmutables ... Además, hay atributos de clase y atributos de instancia ... Nada me gustan los atributos estáticos en el sentido de java & c ++

¿Por qué usar el método estático en sentido pitón, si no tiene relación alguna con la clase? Si yo fuera usted, usaría el método de clase o definiría el método independiente de la clase.


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]


También puede 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

Luego, cuando intente iniciar MyClass por accidente, obtendrá un StaticClassError.


Un punto muy interesante sobre la búsqueda de atributos de Python es que se puede usar para crear "variables virtual ":

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 ninguna asignación a estos después de que se crean. Tenga en cuenta que la búsqueda utiliza self porque, aunque la label es estática en el sentido de no estar asociada con una instancia en particular , el valor aún depende de la instancia (clase de).


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 de instancia, 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 .