Pull to refresh

Локальные статические переменные и константы в функциях 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: '<Storage %s>' % 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)
    ...

Благодарю за внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.