Возможны ли статические переменные класса в Python?

Возможно ли иметь статические переменные класса или методы в Python? Какой синтаксис необходим для этого?

Ответы

Ответ 1

Переменные, объявленные внутри определения класса, но не внутри метода, являются классом или статическими переменными:

>>> class MyClass:
...     i = 3
...
>>> MyClass.i
3 

Как указывает @millerdev, это создает переменную уровня класса i, но она отличается от любой переменной уровня экземпляра i, так что вы можете иметь

>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)

Это отличается от C++ и Java, но не так сильно отличается от С#, где к статическому члену нельзя получить доступ, используя ссылку на экземпляр.

Посмотрите, что в учебнике по Python говорится о предметах классов и объектов классов.

@Steve Johnson уже ответил о статических методах, также описанных в разделе "Встроенные функции" в Справочнике по библиотеке Python.

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

@beidy рекомендует использовать classmethod вместо staticmethod, так как метод получает тип класса в качестве первого аргумента, но я все еще не совсем понимаю преимущества этого подхода по сравнению со staticmethod. Если вы тоже, то это, вероятно, не имеет значения.

Ответ 2

@Blair Conrad сказал, что статические переменные, объявленные внутри определения класса, но не внутри метода, являются классом или "статическими" переменными:

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

Здесь есть несколько ошибок. Продолжая из приведенного выше примера:

>>> 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 do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__
{}

Обратите внимание, как переменная экземпляра ti вышла из синхронизации со "статической" переменной класса, когда атрибут i был установлен непосредственно на t. Это связано с тем, что i был повторно связан с пространством имен t, которое отличается от пространства имен Test. Если вы хотите изменить значение "статической" переменной, вы должны изменить его в пределах области (или объекта), где оно было первоначально определено. Я поместил "статический" в кавычки, потому что Python на самом деле не имеет статических переменных в том смысле, как C++ и Java.

Хотя в нем нет ничего конкретного о статических переменных или методах, в руководстве по Python есть некоторая соответствующая информация о классах и объектах классов.

@Steve Johnson также ответил о статических методах, которые также описаны в разделе "Встроенные функции" в Справочнике по библиотеке Python.

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

@beid также упомянул classmethod, который похож на staticmethod. Первым аргументом метода класса является объект класса. Пример:

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

Pictorial Representation Of Above Example

Ответ 3

Статические и классовые методы

Как отмечали другие ответы, статические и классные методы легко выполняются с использованием встроенных декораторов:

class Test(object):

    # regular instance method:
    def MyMethod(self):
        pass

    # class method:
    @classmethod
    def MyClassMethod(klass):
        pass

    # static method:
    @staticmethod
    def MyStaticMethod():
        pass

Как обычно, первый аргумент MyMethod() привязан к объекту экземпляра класса. Напротив, первый аргумент MyClassMethod() привязан к самому объекту класса (например, в данном случае Test). Для MyStaticMethod() ни один из аргументов не связан, и аргументы вообще необязательны.

"Статические переменные"

Однако реализация "статических переменных" (ну, изменяемые статические переменные, во всяком случае, если это не противоречие в терминах...) не так прямолинейно. Как отметил Миллердев в своем ответе, проблема в том, что атрибуты класса Python не являются действительно "статическими переменными". Рассматривать:

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

Это связано с тем, что строка xi = 12 добавила новый атрибут экземпляра от i до x вместо изменения значения атрибута Test class i.

Частичное ожидаемое поведение статической переменной, т.е. Синхронизация атрибута между несколькими экземплярами (но не с самим классом, см. "Gotcha" ниже), может быть достигнута путем превращения атрибута class в свойство:

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)

Теперь вы можете сделать:

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced

Статическая переменная теперь будет синхронизироваться между всеми экземплярами класса.

(ПРИМЕЧАНИЕ. То есть, если экземпляр класса не решает определить свою собственную версию _i ! Но если кто-то решает это сделать, они заслуживают того, что получают, не так ли?)

Обратите внимание, что технически говоря, i по-прежнему не является "статической переменной"; это property, которое является особым типом дескриптора. Однако поведение property теперь эквивалентно (изменяемой) статической переменной, синхронизированной по всем экземплярам класса.

Неизменяемые "статические переменные"

Для неизменного поведения статической переменной просто опустите 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)

Теперь попытка установить атрибут экземпляра i вернет AttributeError:

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

Один Gotcha должен знать

Обратите внимание, что вышеупомянутые методы работают только с экземплярами вашего класса - они не будут работать при использовании самого класса. Так, например:

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'

Строка assert Test.i == xi вызывает ошибку, так как атрибут i Test и x - это два разных объекта.

Многие люди посчитают это удивительным. Однако этого не должно быть. Если мы вернемся и проверим наше определение класса Test (вторая версия), мы обратим внимание на эту строку:

    i = property(get_i) 

Очевидно, что член i Test должен быть объектом property, который является типом объекта, возвращаемого функцией property.

Если вы считаете, что это запутанное, вы, скорее всего, все еще думаете об этом с точки зрения других языков (например, Java или c++). Вы должны изучить объект property, порядок, в котором возвращаются атрибуты Python, протокол дескриптора и порядок разрешения метода (MRO).

Я представляю решение вышеприведенного "gotcha" ниже; однако я бы предложил - усиленно - чтобы вы не пытались сделать что-то вроде следующего, пока, как минимум, вы не поймете, почему assert Test.i = xi вызывает ошибку.

REAL, ACTUAL Статические переменные - Test.i == xi

Я представляю решение (Python 3) ниже только для информационных целей. Я не одобряю это как "хорошее решение". У меня есть сомнения относительно того, действительно ли необходимо использовать эмуляцию поведения статических переменных для других языков в Python. Однако, независимо от того, действительно ли это полезно, нижеследующее должно помочь в дальнейшем понимании того, как работает Python.

ОБНОВЛЕНИЕ: эта попытка действительно очень ужасна; если вы настаиваете на том, чтобы делать что-то вроде этого (подсказка: пожалуйста, не делайте этого: Python - очень элегантный язык, а обувь - это то, что он ведет себя как другой язык, просто не нужен), вместо этого используйте код в ответе Этана Фурмана.

Эмулирование поведения статических переменных других языков с использованием метакласса

Метакласс - это класс класса. Метакласс по умолчанию для всех классов в Python (т.е. Классы "нового стиля" post Python 2.3, на которые я верю) является type. Например:

type(int)  # class 'type'
type(str)  # class 'type'
class Test(): pass
type(Test) # class 'type'

Однако вы можете определить свой собственный метакласс следующим образом:

class MyMeta(type): pass

И примените его к вашему собственному классу, как это (только для Python 3):

class MyClass(metaclass = MyMeta):
    pass

type(MyClass)  # class MyMeta

Ниже представлен метакласс, который я попытался подражать "статической переменной" поведения других языков. Он в основном работает, заменяя по умолчанию getter, setter и deleter версиями, которые проверяют, является ли запрашиваемый атрибут "статической переменной".

Каталог "статических переменных" хранится в StaticVarMeta.statics. Все запросы атрибутов изначально пытались разрешить с использованием альтернативного порядка разрешения. Я назвал это "порядком статического разрешения" или "SRO". Это делается путем поиска запрашиваемого атрибута в наборе "статических переменных" для данного класса (или его родительских классов). Если атрибут не отображается в "SRO", класс вернется к положению атрибута get/set/delete по умолчанию (т.е. "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

Ответ 4

Вы также можете добавлять переменные класса в классы на лету

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

И экземпляры экземпляров могут изменять переменные класса

class X:
  l = []
  def __init__(self):
    self.l.append(1)

print X().l
print X().l

>python test.py
[1]
[1, 1]

Ответ 5

Лично я бы использовал метод класса, когда мне нужен статический метод. В основном потому, что я получаю класс как аргумент.

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

или используйте декоратор

class myObj(object):
   @classmethod
   def myMethod(cls)

Для статических свойств. Его время вы можете найти определение python.. переменная всегда может измениться. Есть два типа их изменяемых и неизменных. Также существуют атрибуты класса и атрибуты экземпляра. Ничто не похоже на статические атрибуты в смысле java и С++

Зачем использовать статический метод в питоническом смысле, если он не имеет никакого отношения к классу! Если бы я был вами, я бы использовал метод класса или определял метод, независимый от класса.

Ответ 6

Статические методы в python называются classmethod s. Посмотрите на следующий код

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

Обратите внимание, что когда мы вызываем метод myInstanceMethod, мы получаем ошибку. Это потому, что он требует, чтобы метод вызывался для экземпляра этого класса. Метод myStaticMethod устанавливается как метод класса с использованием декоратора @classmethod.

Просто для удовольствия мы можем вызвать myInstanceMethod для класса, передав экземпляр класса следующим образом:

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

Ответ 7

Одно замечание о статических свойствах и свойствах экземпляра, показанных в примере ниже:

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

Это означает, что перед назначением значения для свойства экземпляра, если мы попытаемся получить доступ к свойству через экземпляр, используется статическое значение. Каждое свойство, объявленное в классе python, всегда имеет статический слот в памяти.

Ответ 8

При определении некоторой переменной-члена за пределами любого метода-члена переменная может быть как статической, так и нестатической в ​​зависимости от того, как выражается переменная.

  • CLASSNAME.var - статическая переменная
  • INSTANCENAME.var не является статической переменной.
  • self.var внутри класса не является статической переменной.
  • var внутри функции члена класса не определен.

Например:

#!/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()

Результаты

self.var is 2
A.var is 1
self.var is 2
A.var is 3

Ответ 9

Вы также можете применить класс к статическому с использованием метакласса.

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

Затем всякий раз, когда вы пытаетесь инициализировать MyClass, вы получите StaticClassError.

Ответ 10

Можно иметь переменные класса static, но, вероятно, не стоит усилий.

Здесь доказательство концепции, написанное на Python 3 - если какая-либо из точных деталей неверна, код может быть изменен так, чтобы он соответствовал тому, что вы имеете в виду под 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)

и при использовании:

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

и некоторые тесты:

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

Ответ 11

Один очень интересный момент в поиске атрибутов Python заключается в том, что его можно использовать для создания " виртуальных переменных":

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!

Обычно после их создания нет назначений. Обратите внимание, что lookup использует self потому что, хотя label статична в смысле не связанного с конкретным экземпляром, значение все еще зависит от экземпляра (класса).

Ответ 12

Что касается этого answer, для постоянной статической переменной вы можете использовать дескриптор. Вот пример:

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

в результате чего...

small demo 10
small subdemo 100
big demo 10
big subdemo 10

Вы всегда можете возбуждать исключение, если спокойно игнорировать значение настройки (pass выше) не ваша вещь. Если вы ищете переменную статического класса в стиле С++, 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

Посмотрите этот ответ и официальные документы HOWTO для получения дополнительной информации о дескрипторах.

Ответ 13

Абсолютно Да, Python сам по себе не имеет никакого статического элемента данных явно, но мы можем это сделать

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

Выход

0
0
1
1

объяснение

here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"

Ответ 14

Чтобы избежать какой-либо потенциальной путаницы, я хотел бы противопоставить статические переменные и неизменные объекты.

Некоторые примитивные типы объектов, такие как целые числа, поплавки, строки и кортежи, неизменяемы в Python. Это означает, что объект, на который ссылается данное имя, не может измениться, если он относится к одному из вышеупомянутых типов объектов. Имя может быть переназначено другому объекту, но сам объект не может быть изменен.

Создание переменной static делает это еще дальше, запретив имя переменной указывать на любой объект, кроме того, на который он указывает сейчас. (Примечание: это общая концепция программного обеспечения и не относится к Python, см. Сообщения других пользователей для получения информации об использовании статики в Python).

Ответ 15

Лучший способ найти другой класс. Вы можете создать объект, а затем использовать его на других объектах.

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

В приведенном выше примере я создал класс с именем staticFlag.

Этот класс должен представить статический var __success (Private Static Var).

tryIt класс представляет собой обычный класс, который нам нужно использовать.

Теперь я создал объект для одного флага (staticFlag). Этот флаг будет отправлен как ссылка на все обычные объекты.

Все эти объекты добавляются в список tryArr.


Этот Script Результат:

False
False
False
False
False
True
True
True
True
True

Ответ 16

Да, безусловно, можно писать статические переменные и методы в Python.

Статические переменные: переменные, объявленные на уровне класса, называются статическими переменными, к которым можно обращаться напрямую, используя имя класса.

    >>> class A:
        ...my_var = "shagun"

    >>> print(A.my_var)
        shagun

Переменные экземпляра: переменные, которые связаны и доступны экземпляру класса, являются переменными экземпляра.

   >>> a = A()
   >>> a.my_var = "pruthi"
   >>> print(A.my_var,a.my_var)
       shagun pruthi

Статические методы: Подобно переменным, статические методы могут быть доступны напрямую с помощью класса Name. Не нужно создавать экземпляр.

Но имейте в виду, что статический метод не может вызывать нестатический метод в Python.

    >>> class A:
   ...     @staticmethod
   ...     def my_static_method():
   ...             print("Yippey!!")
   ... 
   >>> A.my_static_method()
   Yippey!!

Ответ 17

Статические переменные в классе factory python3.6

Для всех, кто использует класс factory с python3.6, и используйте ключевое слово nonlocal, чтобы добавить его в область/контекст создаваемого класса следующим образом:

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

Ответ 18

Просто создайте класс, который содержит переменные или типы объектов. Получите доступ к этим переменным, используя имя класса, как показано ниже:


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


    StaticVariable.myvar1 = StaticVariable.myvar1 +1
    StaticVariable.myvar2 = StaticVariable.myvar2 +1