Вопрос

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

Это было полезно?

Решение

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

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

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

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

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

Видишь что говорится в руководстве по Python на тему классов и объектов классов.

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

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

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

Другие советы

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

Обратите внимание, как переменная экземпляра t.i вышла из синхронизации со "статической" переменной класса, когда атрибут i был установлен непосредственно на t.Это происходит потому, что i был повторно связан в рамках t пространство имен, которое отличается от Test пространство имен.Если вы хотите изменить значение "статической" переменной, вы должны изменить ее в пределах области видимости (или объекта), где она была первоначально определена.Я заключил "static" в кавычки, потому что в 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

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

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

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

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

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

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 сеттер:

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

Об одном тебе нужно знать

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

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 == x.i выдает ошибку, потому что i атрибут Test и x это два разных объекта.

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

    i = property(get_i) 

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

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

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

РЕАЛЬНЫЙ, ДЕЙСТВИТЕЛЬНЫЙ Статические переменные - Test.i == x.i

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

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

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

Метакласс - это класс класса.Метакласс по умолчанию для всех классов в Python (т. Е., я полагаю, классы "нового стиля" после 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

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

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

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

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

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

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

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

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

Для статических свойств..Пришло время вам поискать какое-нибудь определение python..переменная всегда может измениться.Существует два их типа: изменяемые и неизменяемые..Кроме того, существуют атрибуты класса и атрибуты экземпляра..На самом деле нет ничего похожего на статические атрибуты в смысле java и c ++

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

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

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, всегда имеет статический слот в памяти.

Статические методы в python вызываются метод класса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 Метод myInstanceMethod, мы получаем сообщение об ошибке.Это связано с тем, что для этого требуется, чтобы метод вызывался для экземпляра этого класса.Способ Мистический метод устанавливается как метод класса с использованием декоратор @метод класса.

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

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

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

  • 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

Вы также можете принудительно сделать класс статичным, используя 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

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

Это возможно иметь 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

Один очень интересный момент в поиске атрибутов 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!

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

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

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 выше) - это не ваше дело.Если вы ищете статическую переменную класса в стиле 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

Взгляните на этот ответ и официальные документы КАК ЭТО СДЕЛАТЬ для получения дополнительной информации о дескрипторах.

Абсолютно да, 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"

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

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

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

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

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 (Частный статический Var).

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

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

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


Этот сценарий Приводит К:

False
False
False
False
False
True
True
True
True
True

Да, определенно возможно писать статические переменные и методы на 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

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

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

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

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

Для всех, кто использует фабрику классов с 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

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


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top