Я могу использовать декоратора для видоизменения локального объема функции в Python?

вы можете сделать это

void getCount(){   
   countDocuments().then((count ) {
           // print(result);
           if (count < 5){
             addDialog(context);
             print(countDocuments());
           }
           else{
             seeSnackBar(context);
           }
      });
}
8
задан kender 26 February 2009 в 18:59
поделиться

7 ответов

Повторение ответа Транзитного участка

  1. Не делайте этого.
  2. Серьезно, не делайте этого. Lisp и Ruby являются более соответствующими языками для записи Вашего собственного синтаксиса. Используйте одного из тех. Или найдите более чистый способ сделать это
  3. Если Вы должны, Вы хотеть динамические ограниченные по объему переменные, не лексически ограниченные по объему.

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

http://codepad.org/6vAY8Leh

def adds_dynamic_z_decorator(f):
  def replacement(*arg,**karg):
    # create a new 'z' binding in globals, saving previous
    if 'z' in globals():
      oldZ = (globals()['z'],)
    else:
      oldZ = None
    try:
      globals()['z'] = None
      #invoke the original function
      res = f(*arg, **karg)
    finally:
      #restore any old bindings
      if oldZ:
        globals()['z'] = oldZ[0]
      else:
        del(globals()['z'])
    return res
  return replacement

@adds_dynamic_z_decorator
def func(x,y):
  print z

def other_recurse(x):
  global z
  print 'x=%s, z=%s' %(x,z)
  recurse(x+1)
  print 'x=%s, z=%s' %(x,z)

@adds_dynamic_z_decorator
def recurse(x=0):
  global z
  z = x
  if x < 3:
    other_recurse(x)

print 'calling func(1,2)'
func(1,2)

print 'calling recurse()'
recurse()

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

Этот код подобен и коду eduffy и John Montgomery, но гарантирует, что 'z' создается и правильно восстанавливается "как" локальная переменная, был бы - например, отметить, как 'other_recurse' может видеть, что привязка для 'z', указанного в теле, 'рекурсивно вызывает'.

11
ответ дан 5 December 2019 в 05:34
поделиться

Я не знаю о локальном объеме, но Вы могли обеспечить альтернативное глобальное пространство имен временно. Что-то как:



import types

def my_decorator(fn):
    def decorated(*args,**kw):
        my_globals={}
        my_globals.update(globals())
        my_globals['z']='value of z'
        call_fn=types.FunctionType(fn.func_code,my_globals)
        return call_fn(*args,**kw)
    return decorated

@my_decorator
def func(x, y):
    print z

func(0,1)


Который должен распечатать "значение z"

8
ответ дан 5 December 2019 в 05:34
поделиться

a) не делайте этого.

b) серьезно, почему Вы сделали бы это?

c) Вы могли объявить z как глобальный в Вашем декораторе, таким образом, z не будет в globals (), пока декоратора не вызвали впервые, таким образом, утверждение не будет лаять.

d) почему???

7
ответ дан 5 December 2019 в 05:34
поделиться

Я сначала отзовусь эхом, "не делайте", но это - Ваш выбор. Вот решение для Вас:

assert 'z' not in globals ()

class my_dec:
    def __init__ (self, f):
        self.f = f
    def __call__ (self,x,y):
        z = x+y
        self.f(x,y,z)

@my_dec
def func (x,y,z):
    print z

func (1,3)

Это действительно требует z в формальных параметрах, но не фактическом.

2
ответ дан 5 December 2019 в 05:34
поделиться

Явный лучше, чем неявный.

Действительно ли это достаточно хорошо?

def provide_value(f):
    f.foo = "Bar"
    return f

@provide_value
def g(x):
    print g.foo

(Если Вы действительно хотите зло, присваивание f.func_globals кажется забавой.)

1
ответ дан 5 December 2019 в 05:34
поделиться

Я мог, вероятно, получить подобный эффект от использования инфраструктуры класса также, но я хотел видеть, было ли это выполнимо с необработанными функциями.

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

1
ответ дан 5 December 2019 в 05:34
поделиться

Другие дали несколько способов сделать рабочего декоратора, многие отговорили от выполнения поэтому, потому что это так стилистически отличается от нормального поведения Python, что это действительно смутит любого пытающегося понять код.

Если бы необходимо повторно вычислить вещи много, имело бы смысл собирать в группу их в объекте? Вычислите z1... цинк в конструкторе, затем функции, которые используют эти значения, могут получить доступ к предварительно вычисленным ответам как к части экземпляра.

0
ответ дан 5 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: