Добавление в локальное пространство имен в Python? - PullRequest
4 голосов
/ 11 октября 2009

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

Например, что-то вроде следующего (что, конечно, не работает, потому что localals () возвращает копию локального пространства имен), где оператор print вывел бы '1'.

def A():
  B(locals())
  print x

def B(d):
  d['x'] = 1

Ответы [ 2 ]

4 голосов
/ 11 октября 2009

В Python 2.* вы можете отключить обычные оптимизации, выполняемые компилятором Python в отношении доступа к локальным переменным, запустив вашу функцию с exec ''; это сделает функцию намного медленнее (я только что опубликовал ранее сегодня ответ, показывающий, как оптимизация локальной переменной может легко ускорить код в 3 или 4 раза), но это заставит ваш желаемый хак работать. Т.е. в Python 2. *:

def A():
  exec ''
  B(locals())
  print x

def B(d):
  d['x'] = 1

A()

будет излучать 1, по вашему желанию.

Этот взлом был отключен в Python 3.* (где exec - это просто функция, а не оператор или ключевое слово) - теперь компилятор выполняет оптимизацию локальной переменной безоговорочно, так что больше нет никакого способа обойти это и заставить такие хаки работать.

1 голос
/ 11 октября 2009

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

>>> def outer():
...   global x
...   b()
...   print x
... 
>>> def b():
...   global x
...   x = 2
... 
>>> outer()
2

Вместо этого вы можете создать пространство имен для ваших переменных:

class Namespace(object):
    pass

def A():
  names = Namespace()
  B(names)
  print names.x

def B(d):
  d.x = 1

Затем используйте names.x или getattr(names, "x") для доступа к атрибутам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...