- Локальные статические переменные и константы в функциях Python
- Использование статических переменных в функциях в Python
- Реализация статических переменных в Python
- Использование атрибутов функции
- Использование генераторов
- Использование замыканий
- Python static variable in a function | Example code
- Python static variable in a function examples
- Add attributes to a function
- Initialization code at the top using decorator
- Use hasattr()
Локальные статические переменные и константы в функциях Python
Если в функциях необходимы константы или значения, неизменяющиеся между вызовами, то их можно определить в глобальной области видимости (например, в начале модуля), а также не забыть упомянуть в директиве global этой функции переменные, которым будут присваиваться значения. Но они не будут защищены от изменений кодом, находящимся вне функции. А также, при разросшемся коде, может возникать некоторое неудобство при перемещении по тексту между переменными/константами и собственно функцией.
Для констант напрашивается простое решение — сделать их параметрами функции с требуемыми значениями по умолчанию. Их можно даже изменять в теле функции, но при следующем вызове значение будет восстанавливаться.
Для переменных типа списков, словарей и т.п. можно поступить также, их содержимое будет сохраняться между вызовами. Но если необходимо сохранять значения простых (int, str и т.п.) переменных между вызовами — то их придётся разместить в списке или словаре, являющемся значением по умолчанию определённого параметра функции. Но конечно удобству доступа к ним теперь не позавидуешь. Однако, облегчить его может доступ к элементам словаря в стиле Javascript. Возможные варианты реализации таких словарей есть здесь, здесь, здесь. Для себя ограничился следующим кодом:
class Storage(dict): __slots__ = () __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ __getitem__ = dict.get __getattr__ = dict.get __getnewargs__ = lambda self: getattr(dict,self).__getnewargs__(self) __repr__ = lambda self: '' % dict.__repr__(self) __getstate__ = lambda self: None __copy__ = lambda self: Storage(self)
Понимаю, что для данной цели он тоже избыточный, но из осторожности больше ничего выбрасывать не стал.
И примерно так им пользовался (в примере особого смысла не искать):
def read_serial(prorej=round(per_ind / per_ser), imp_s_l_m=60 / imp_na_l, imp_queue=[(0, 0)] * 7, # time.time() o=Storage(imp_cntr_glob=0, ser_cntr=0, i=0)): . o.ser_cntr += 1 # o["ser_cntr"] += 1 . o.imp_cntr_glob += imp # o["imp_cntr_glob"] += imp . if o.ser_cntr % prorej: # if o["ser_cntr"] % prorej: . imp_cur = o.imp_cntr_glob, time.time() . dimp, dt = map(lambda a, b: a - b, imp_cur, imp_queue.pop(0)) imp_queue.append(imp_cur) . dimp, dt = map(lambda a, b: a - b, imp_cur, imp_queue[o.i]) imp_queue[o.i] = imp_cur o.i = (o.i + 1) % len(imp_queue) . v = int(dimp / dt * imp_s_l_m) .
Использование статических переменных в функциях в Python
Часто разработчики, привыкшие к таким языкам программирования как C/C++, сталкиваются с необходимостью использовать статические переменные внутри функций при переходе на Python. В C/C++ статическая переменная внутри функции сохраняет свое значение между вызовами функции, что может быть очень полезно.
Возьмем в качестве примера следующий код на C++:
В этом коде переменная counter увеличивается на 1 при каждом вызове функции foo() , и значение counter сохраняется между вызовами.
Реализация статических переменных в Python
В Python нет прямого аналога статическим переменным в функциях, как в C/C++. Однако, есть несколько способов реализовать подобное поведение.
Использование атрибутов функции
Один из способов — использовать атрибуты функции. В Python функции — это объекты, и у них могут быть атрибуты. Вот пример кода, который демонстрирует это:
def foo(): if not hasattr(foo, "counter"): foo.counter = 0 foo.counter += 1 print("counter is", foo.counter)
В этом коде foo.counter является атрибутом функции foo . При первом вызове функции атрибут counter инициализируется значением 0, а затем при каждом вызове функции foo значение counter увеличивается на 1.
Использование генераторов
Другой способ — использовать генераторы. Генераторы в Python — это специальный тип функций, которые сохраняют свое состояние между вызовами. Вот пример кода, который демонстрирует это:
def foo(): counter = 0 while True: yield counter counter += 1 f = foo() for _ in range(5): print("counter is", next(f))
В этом коде foo — это генератор, который при каждом вызове функции next возвращает значение counter и затем увеличивает его на 1.
Использование замыканий
Третий способ — использовать замыкания. Замыкание в Python — это функция, которая имеет доступ к переменным из своей области видимости, даже после того, как эта область видимости исчезла. Вот пример кода, который демонстрирует это:
def foo(): counter = [0] def inner(): counter[0] += 1 print("counter is", counter[0]) return inner f = foo() for _ in range(5): f()
В этом коде foo возвращает функцию inner , которая имеет доступ к переменной counter из области видимости функции foo . При каждом вызове функции f (которая теперь ссылается на inner ) значение counter увеличивается на 1.
Python static variable in a function | Example code
You can make static variables inside a function in many ways in Python. If declaring a static variable in a function means variable throughout the lifetime of the program.
Python static variable in a function examples
Simple 3 example code for it:-
Add attributes to a function
You can add attributes to a function, and use it as a static variable. Count how many times functions have been called using a static variable.
def foo(): foo.counter += 1 print("Counter is %d" % foo.counter) foo.counter = 0 foo() foo()
Initialization code at the top using decorator
If you want the counter initialization code at the top instead of the bottom, you can create a decorator:
def static_vars(**kwargs): def decorate(func): for k in kwargs: setattr(func, k, kwargs[k]) return func return decorate # Then use the code like this: @static_vars(counter=0) def foo(): foo.counter += 1 print("Counter is %d" % foo.counter) foo()
Output: Counter is 1
Use hasattr()
Alternatively, if you don’t want to set up the variable outside the function, you can use hasattr() to avoid an AttributeError exception:
def myfunc(): if not hasattr(myfunc, "counter"): myfunc.counter = 0 # it doesn't exist yet, so initialize it myfunc.counter += 1 return myfunc.counter print(myfunc()) print(myfunc())
Do comment if you have any doubts or suggestions on this Python variable topic.
Note: IDE: PyCharm 2021.3.3 (Community Edition)
Windows 10
Python 3.10.1
All Python Examples are in Python 3, so Maybe its different from python 2 or upgraded versions.