Вопрос:

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

python class static class-variables

1074642 просмотра

18 ответа

21034 Репутация автора

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

Автор: Andrew Walker Источник Размещён: 16.09.2008 01:46

Ответы (18)


1677 плюса

159955 Репутация автора

Решение

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

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

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

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

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

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

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

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

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

Автор: Blair Conrad Размещён: 16.09.2008 01:51

15 плюса

494 Репутация автора

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

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

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

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

For static properties.. Its time you look up some python definition.. variable can always change. There are two types of them mutable and immutable.. Also, there are class attributes and instance attributes.. Nothing really like static attributes in the sense of java & c++

Why use static method in pythonic sense, if it has no relation whatever to the class! If I were you, I'd either use classmethod or define the method independent from the class.

Автор: emb Размещён: 16.09.2008 02:02

13 плюса

5500 Репутация автора

Static methods in python are called classmethods. Take a look at the following code

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

Notice that when we call the method myInstanceMethod, we get an error. This is because it requires that method be called on an instance of this class. The method myStaticMethod is set as a classmethod using the decorator @classmethod.

Just for kicks and giggles, we could call myInstanceMethod on the class by passing in an instance of the class, like so:

>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
Автор: willurd Размещён: 16.09.2008 02:05

559 плюса

7225 Репутация автора

@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пространства имен. Если вы хотите изменить значение «статической» переменной, вы должны изменить его в пределах области (или объекта), где оно было первоначально определено. Я поместил «статический» в кавычки, потому что 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

Наглядное представление вышеприведенного примера

Автор: millerdev Размещён: 16.09.2008 03:04

3 плюса

1348 Репутация автора

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

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

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

Автор: Ross Размещён: 17.09.2008 04:01

24 плюса

1027 Репутация автора

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

>>> 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]
Автор: Gregory Размещён: 17.09.2008 08:06

6 плюса

551 Репутация автора

You could also enforce a class to be static using 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

Then whenever by accident you try to initialize MyClass you'll get an StaticClassError.

Автор: Bartosz Ptaszynski Размещён: 20.11.2011 12:06

13 плюса

4877 Репутация автора

One special thing to note about static properties & instance properties, shown in the example below:

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

This means before assigning the value to instance property, if we try to access the property thru' instance, the static value is used. Each property declared in python class always has a static slot in memory.

Автор: jondinham Размещён: 08.03.2012 06:06

3 плюса

917 Репутация автора

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

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.

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

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

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

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


Результаты этого скрипта:

False
False
False
False
False
True
True
True
True
True
Автор: Tomer Zait Размещён: 27.02.2013 05:00

8 плюса

89 Репутация автора

When define some member variable outside any member method, the variable can be either static or non-static depending on how the variable is expressed.

  • CLASSNAME.var is static variable
  • INSTANCENAME.var is not static variable.
  • self.var inside class is not static variable.
  • var inside the class member function is not defined.

For example:

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

The results are

self.var is 2
A.var is 1
self.var is 2
A.var is 3
Автор: user2209576 Размещён: 26.03.2013 05:56

4 плюса

20047 Репутация автора

In regards to this answer, for a constant static variable, you can use a descriptor. Here's an example:

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

resulting in ...

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

You can always raise an exception if quietly ignoring setting value (pass above) is not your thing. If you're looking for a C++, Java style static class variable:

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

Have a look at this answer and the official docs HOWTO for more information about descriptors.

Автор: Yann Размещён: 03.07.2014 12:14

165 плюса

16175 Репутация автора

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

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

class Test(object):

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

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

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

Как обычно, первый аргумент to 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атрибута.

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

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

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

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

    i = property(get_i) 

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

Если вы находите вышеупомянутое недоразумением, скорее всего, вы все еще думаете об этом с точки зрения других языков (например, Java или c ++). Вам следует изучить propertyобъект, порядок, в котором возвращаются атрибуты 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», класс будет использовать атрибут 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
Автор: Rick Teachey Размещён: 19.12.2014 03:16

6 плюса

37720 Репутация автора

It is possible to have static class variables, but probably not worth the effort.

Here's a proof-of-concept written in Python 3 -- if any of the exact details are wrong the code can be tweaked to match just about whatever you mean by a 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)

and in use:

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

and some tests:

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
Автор: Ethan Furman Размещён: 25.03.2016 09:02

1 плюс

9594 Репутация автора

Статические переменные в фабрике классов 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
Автор: jmunsch Размещён: 01.01.2017 02:56

4 плюса

76 Репутация автора

Абсолютно да, 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"
Автор: Mari Selvan Размещён: 22.02.2017 01:01

5 плюса

10214 Репутация автора

One very interesting point about Python's attribute lookup is that it can be used to create "virtual variables":

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!

Normally there aren't any assignments to these after they are created. Note that the lookup uses self because, although label is static in the sense of not being associated with a particular instance, the value still depends on the (class of the) instance.

Автор: Davis Herring Размещён: 21.09.2017 04:04

2 плюса

383 Репутация автора

Да, безусловно, можно писать статические переменные и методы в 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!!
Автор: Shagun Pruthi Размещён: 14.12.2018 08:01

0 плюса

16 Репутация автора

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


    class StaticVariable:
        myvar1 = 1
        myvar2 = 2


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

Автор: JustinC Размещён: 23.05.2019 06:21
Вопросы из категории :
32x32