По правилам Python вы не можете изменить locals
вашего абонента; в текущих реализациях, если вы попытаетесь (например, с помощью черной магии, которую предлагает Anurag), вы не получите исключение (хотя я бы хотел добавить эту проверку ошибок в какую-то будущую версию), но это будет по существу неработоспособно, если ваш вызывающий функция (не если ваш вызывающий является кодом верхнего уровня модуля) - фактические локальные переменные вызывающего фактически не будут затронуты. Это верно, независимо от того, переданы ли locals
вызывающего в явном виде или извлечены с помощью черной магии: они все равно должны рассматриваться как диктовка только для чтения, если ваш код должен иметь какой-либо здравый смысл.
Скорее, вы могли бы передать вызывающей стороне явный, настоящий, нормальный dict (который можно инициализировать с locals()
, если хотите), и все изменения, которые ваш код делает в этом dict, все еще будут доступны для использования вызывающей стороной. - конечно, не как «новые имена» в локальной области вызова, но функциональность остается той же, независимо от того, нужно ли вызывающему использовать x['foo']
или x.foo
или (как вы предпочитаете) просто имя foo
.
Кстати, чтобы использовать синтаксис доступа к атрибутам вместо синтаксиса индексации dict, вы можете сделать:
class Bunch(object): pass
...
# caller code
b = Bunch()
thefun(b)
print b.foo
...
# called function
def thefun(b):
b.foo = 23
Это также с небольшим изменением охватывает случай, когда thefun
хочет работать с синтаксисом индексации dict (скажем, его тело b['foo'] = 23
вместо b.foo = 23
): в этом случае вызывающему просто нужно используйте thefun(vars(b))
вместо простого thefun(b)
, но он может продолжать работать с синтаксисом доступа b.foo
.