Czy statyczne zmienne klas są możliwe?
Czy możliwe jest posiadanie statycznych zmiennych klas lub metod w Pythonie? Jaka składnia jest wymagana, aby to zrobić?
16 answers
Zmienne zadeklarowane wewnątrz definicji klasy, ale nie wewnątrz metody są zmiennymi klasy lub statycznymi:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
Jak wskazuje @ millerdev , tworzy to zmienną na poziomie klasy i
, ale różni się to od każdej zmiennej na poziomie instancji i
, więc możesz mieć
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
To różni się od C++ i Javy, ale nie tak bardzo od C#, gdzie statyczny członek nie może być dostępny za pomocą odniesienia do instancji.
Zobacz co ma zrobić samouczek Pythona powiedzieć na temat klas i obiektów klas .
@ Steve Johnson już odpowiedział na temat metod statycznych , udokumentowanych również Pod "wbudowane funkcje" w referencji Biblioteki Pythona .
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@ beidy zalecaclassmethod s nad staticmethod, ponieważ metoda otrzymuje typ klasy jako pierwszy argument, ale nadal jestem trochę niejasny co do zalet tego podejścia nad staticmethod. Jeśli ty też, to prawdopodobnie nie Materia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 13:00:27
@Blair Conrad powiedział, że zmienne statyczne zadeklarowane wewnątrz definicji klasy, ale nie wewnątrz metody są zmiennymi klasy lub "statycznymi":
>>> class Test(object):
... i = 3
...
>>> Test.i
3
Jest tu kilka gotcha ' s. Kontynuując z powyższego przykładu:
>>> 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__
{}
Zwróć uwagę, jak zmienna instancji t.i
została zsynchronizowana ze zmienną klasy "static", gdy atrybut i
został ustawiony bezpośrednio na t
. Jest to spowodowane tym, że i
została ponownie powiązana z przestrzenią nazw t
, która różni się od przestrzeni nazw Test
. Jeśli chcesz zmienić wartość zmiennej "statycznej", musisz zmienić ją w zakresie (lub obiekcie), w którym została pierwotnie zdefiniowana. Wstawiam" static " w cudzysłowie, ponieważ Python tak naprawdę nie ma zmiennych statycznych w tym sensie, co robią C++ i Java.
Chociaż nie mówi nic konkretnego o zmiennych statycznych lub metodach, samouczek Pythona zawiera kilka istotnych informacji o klasach i obiektach klas .
@Steve Johnson odpowiedział również w sprawie metody statyczne, udokumentowane również pod "wbudowanymi funkcjami" W referencji Biblioteki Pythona.
class Test(object):
@staticmethod
def f(arg1, arg2, ...):
...
@beid wspomniał również o classmethod, która jest podobna do staticmethod. Pierwszym argumentem classmethod jest obiekt class. Przykład:
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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-28 00:15:27
Metody statyczne i klasowe
Jak zauważyły inne odpowiedzi, metody statyczne i klasowe są łatwo realizowane za pomocą wbudowanych dekoratorów:]}class Test(object):
# regular instance method:
def MyMethod(self):
pass
# class method:
@classmethod
def MyClassMethod(klass):
pass
# static method:
@staticmethod
def MyStaticMethod():
pass
Jak zwykle, pierwszy argument {[12] } jest związany z obiektem instancji klasy. W przeciwieństwie do tego, pierwszy argument MyClassMethod()
jest powiązany z samym obiektem klasy (np. w tym przypadku Test
). Dla MyStaticMethod()
żaden z argumentów nie jest związany, a posiadanie argumentów w ogóle jest opcjonalne.
"Static Zmienne "
Jednak implementowanie "zmiennych statycznych" (cóż, zmiennych statycznych, jeśli nie jest to sprzeczność w kategoriach...) nie jest tak prosta. Jak zauważył millerdev w swojej odpowiedzi , problem polega na tym, że atrybuty klas Pythona nie są naprawdę "zmiennymi statycznymi". Rozważyć:
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
Dzieje się tak dlatego, że linia {[16] } dodała nowy atrybut instancji i
do x
zamiast zmieniać wartość klasy Test
i
atrybut.
częściowe oczekiwane zachowanie zmiennej statycznej, tj. synchronizacja atrybutu między wieloma instancjami (ale Nie z samą klasą; patrz "gotcha" poniżej), może być osiągnięte poprzez przekształcenie atrybutu klasy w właściwość:
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)
Teraz możesz zrobić:
x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i # no error
assert x2.i == 50 # the property is synced
Zmienna statyczna pozostanie zsynchronizowana pomiędzy wszystkimi instancjami klasy .
(uwaga: to znaczy, chyba że instancja klasy zdecyduje się zdefiniować własną wersję _i
! Ale jeśli ktoś zdecyduje się to zrobić, zasługuje na to, co dostanie, prawda???)
Zauważ, że technicznie rzecz biorąc, i
w ogóle nie jest 'zmienną statyczną'; jest to property
, który jest specjalnym typem deskryptora. Jednak zachowanie property
jest teraz równoważne zmiennej statycznej synchronizowanej we wszystkich instancjach klasy.
Niezmienne "Zmienne Statyczne"
Dla niezmiennego zachowania zmiennej statycznej, po prostu pomiń setterproperty
:
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)
Teraz próba ustawienia instancji i
atrybutu zwróci AttributeError
:
x = Test()
assert x.i == 3 # success
x.i = 12 # ERROR
One Gotcha to be Aware of
Zauważ, że powyższe metody działają tylko z instancjami twojej klasy - będą, a nie działaćpodczas używania samej klasy . Tak na przykład:
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'
Linia assert Test.i == x.i
generuje błąd, ponieważ i
atrybut Test
i x
są dwoma różnymi obiektami.
Test
definicję klasy (druga wersja), przyjrzymy się tej linii:
i = property(get_i)
Oczywiście, element i
z Test
musi być obiektem property
, który jest typem obiektu zwracanego z funkcji property
.
Jeśli uważasz powyższe za mylące, najprawdopodobniej nadal myślisz o tym z perspektywy innych języków (np. Java lub c++). Powinieneś przestudiować obiekt property
, o kolejności w jakiej atrybuty Pythona zwracane są, protokół deskryptora oraz metoda resolution order (MRO).
Przedstawiam rozwiązanie powyższego "mam cię" poniżej; jednak sugerowałbym-usilnie - abyś nie próbował robić czegoś takiego jak poniżej, dopóki-przynajmniej-nie zrozumiesz dokładnie, dlaczego {38]} powoduje błąd.
rzeczywiste, rzeczywiste zmienne statyczne - Test.i == x.i
Poniżej przedstawiam rozwiązanie (Python 3) wyłącznie w celach informacyjnych. Nie popieram tego jako " dobrego rozwiązanie". Mam wątpliwości, czy emulowanie zachowania zmiennych statycznych innych języków w Pythonie jest kiedykolwiek konieczne. Jednakże, niezależnie od tego, czy jest on rzeczywiście użyteczny, poniższe informacje powinny pomóc w dalszym zrozumieniu, jak działa Python.
UPDATE: this attempt is really pretty awful ; if you present to do something like this (hint: please don ' t; Python is a very elegant language and shoe-horning it into behind like another language is just not konieczne), zamiast tego użyj kodu w odpowiedzi Ethana Furmana.
Emulowanie zachowania zmiennych statycznych innych języków przy użyciu metaklasy
Metaklasa jest klasą klasy. Domyślną metaklasą dla wszystkich klas w Pythonie (tj. klas" nowego stylu " po Pythonie 2.3, jak sądzę) jest type
. Na przykład:
type(int) # class 'type'
type(str) # class 'type'
class Test(): pass
type(Test) # class 'type'
Możesz jednak zdefiniować swoją metaklasę w następujący sposób:]}
class MyMeta(type): pass
I zastosuj go do własnej klasy w ten sposób (Python 3 tylko):
class MyClass(metaclass = MyMeta):
pass
type(MyClass) # class MyMeta
Poniżej znajduje się metaklasa, którą stworzyłem, która próbuje naśladować zachowanie "zmiennych statycznych" innych języków. Zasadniczo działa poprzez zastąpienie domyślnego gettera, settera i deletera wersjami, które sprawdzają, czy żądany atrybut jest "zmienną statyczną".
Katalog "zmiennych statycznych" jest przechowywany w atrybucie StaticVarMeta.statics
. Wszystkie żądania atrybutów są początkowo próbowane zostać rozwiązane przy użyciu zastępczej kolejności rozstrzygania. Dubbingowałem to "statyczny porządek rozdzielczości" lub "SRO". Odbywa się to poprzez wyszukanie żądanego atrybutu w zbiorze "zmiennych statycznych" dla danej klasy (lub jej klas nadrzędnych). Jeśli atrybut nie pojawi się w "SRO", Klasa powróci do domyślnego atrybutu get/set/delete (tj. "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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-08 16:12:57
Możesz również dodawać zmienne klas do klas w locie
>>> 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
I instancje klasy mogą zmieniać zmienne klasy
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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-24 17:43:30
Osobiście używałem classmethod, gdy potrzebowałem statycznej metody. Głównie dlatego, że traktuję klasę jako argument.
class myObj(object):
def myMethod(cls)
...
myMethod = classmethod(myMethod)
Lub użyć dekoratora
class myObj(object):
@classmethod
def myMethod(cls)
Dla właściwości statycznych.. Czas poszukać definicji Pythona.. zmienna zawsze może się zmieniać. Istnieją dwa ich typy mutowalne i niezmienne.. Istnieją również atrybuty klas i atrybuty instancji.. Nie ma to jak statyczne atrybuty w sensie java & c++
Po co stosować metodę statyczną w zmysł pythoniczny, jeśli nie ma żadnego związku z klasą! Na Twoim miejscu albo użyłbym classmethod, albo zdefiniowałbym metodę niezależną od klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 23:29:49
Statyczne metody w Pythonie nazywane są classmethod s. spójrz na następujący kod
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
Zauważ, że gdy wywołujemy metodę myInstanceMethod , otrzymujemy błąd. Dzieje się tak, ponieważ wymaga, aby metoda była wywoływana na instancji tej klasy. Metoda myStaticMethod {[8] } jest ustawiana jako classmethod za pomocą dekoratora @classmethod .
Po prostu dla zabawy, możemy zadzwonić do myInstanceMethod na zajęcia, przechodząc w przypadku klasy, jak tak:>>> 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 10:23:57
Należy zwrócić szczególną uwagę na właściwości statyczne i właściwości instancji, pokazane w poniższym przykładzie:
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
Oznacza to, że przed przypisaniem wartości do właściwości instance, jeśli spróbujemy uzyskać dostęp do właściwości thru ' instance, zostanie użyta wartość statyczna. Każda właściwość zadeklarowana w klasie Pythona ma zawsze statyczny slot w pamięci .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-08 06:06:05
Gdy zdefiniujemy jakąś zmienną składową poza dowolną metodą składową, zmienna może być statyczna lub niestatyczna w zależności od sposobu wyrażenia zmiennej.
- Nazwa klasy.var jest zmienną statyczną
- INSTANCENAME.var nie jest zmienną statyczną.
- siebie.var wewnątrz klasy nie jest zmienną statyczną.
- var wewnątrz funkcji członka klasy nie jest zdefiniowany.
Na przykład:
#!/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()
Wyniki są
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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 11:37:36
Możesz również wymusić statyczną klasę używając metaclass.
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
Wtedy, gdy przez przypadek spróbujesz zainicjować MyClass , otrzymasz StaticClassError.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-20 12:06:23
Bardzo interesującą kwestią dotyczącą wyszukiwania atrybutów Pythona jest to, że można go użyć do tworzenia"wirtualnych zmiennych":
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!
Normalnie nie ma żadnych przypisań do nich po ich utworzeniu. Zauważ, że wyszukiwanie używa self
, ponieważ chociaż label
jest statyczne w tym sensie, że nie jest powiązane z konkretną instancją, wartość nadal zależy od (klasy) instancji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-17 17:19:31
Możliwe jest posiadanie zmiennych klasy static
, ale prawdopodobnie nie jest to warte wysiłku.
Oto proof-of-concept napisany w Pythonie 3 -- jeśli któreś z dokładnych szczegółów jest błędne, kod można zmodyfikować tak, aby pasował do tego, co masz na myśli przez 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)
I w użyciu:
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')
I kilka testów:
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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-25 09:02:25
Aby uniknąć potencjalnych nieporozumień, chciałbym kontrastować zmienne statyczne i Obiekty niezmienne.
Niektóre prymitywne typy obiektów, takie jak liczby całkowite, pływaki, ciągi i touple, są niezmienne w Pythonie. Oznacza to, że obiekt, do którego odnosi się dana nazwa, nie może się zmienić, jeśli należy do jednego z wyżej wymienionych typów obiektów. Nazwę można przypisać do innego obiektu, ale sam obiekt nie może zostać zmieniony.
Zrobienie zmiennej statycznej prowadzi to o krok dalej poprzez wyłączenie nazwy zmiennej wskazującej na dowolny obiekt poza tym, do którego aktualnie wskazuje. (Uwaga: jest to ogólna koncepcja oprogramowania, a nie specyficzna dla Pythona; Zobacz posty innych, aby uzyskać informacje na temat implementacji statyki w Pythonie).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 04:01:08
Najlepszy sposób, jaki znalazłem, to użycie innej klasy. Obiekt można utworzyć, a następnie użyć go na innych obiektach.
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()
Z powyższego przykładu stworzyłem klasę o nazwie staticFlag
.
Klasa ta powinna prezentować statyczny var __success
(prywatny statyczny Var).
tryIt
klasa reprezentuje zwykłą klasę, której musimy użyć.
Teraz zrobiłem obiekt dla jednej flagi (staticFlag
). Ta flaga zostanie wysłana jako odniesienie do wszystkich zwykłych obiektów.
Wszystkie te obiekty są dodawane do lista tryArr
.
Wyniki Tego Skryptu:
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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-19 23:42:58
Absolutnie Tak., Python sam w sobie nie ma żadnego statycznego członka danych jawnie, ale możemy mieć w ten sposób
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())
Wyjście
0
0
1
1
Wyjaśnienie
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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 13:01:13
W odniesieniu do tej Odpowiedzi, dla stałej zmiennej statycznej, możesz użyć deskryptora. Oto przykład:
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
W wyniku czego ...
small demo 10
small subdemo 100
big demo 10
big subdemo 10
Możesz zawsze wywołać wyjątek, jeśli po cichu ignorujesz ustawienie wartości (pass
powyżej). Jeśli szukasz statycznej zmiennej klasy w stylu 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
Aby uzyskać więcej informacji na temat deskryptorów, zajrzyj do tej odpowiedzi oraz do oficjalnych dokumentów HOWTO.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:14
Zmienne statyczne w klasie factory python3. 6
Dla każdego, kto używa fabryki klasy z python3.6 i w górę, Użyj słowa kluczowego nonlocal
, aby dodać go do zakresu / kontekstu tworzonej klasy w ten sposób:
>>> 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-01 02:56:08