Вопрос по python, local, namespaces – Как изменить локальное пространство имен в Python

6

Как я могу изменить локальное пространство имен функции в Python? Я знаю, что locals () возвращает локальное пространство имен функции при вызове внутри нее, но я хочу сделать что-то вроде этого (у меня есть причина, почему я хочу сделать это, когда g недоступна для f, но это быстрее. дать тривиальный, глупый пример для иллюстрации проблемы):

def g():
   pass

def f():
    g()

f.add_to_locals({'g':g})
Какова ваша конечная цель, используя эту странную технику? Почему вы не можете просто определить g () перед f ()? Mikhail Churbanov
что за хреньadd_to_locals ? Кажется, он не существует для меня.AttributeError: 'function' object has no attribute 'add_to_locals' Charlie Parker
@CharlieParker его не существует. Это то, что он пытается реализовать / спрашивать, есть ли решение для этого. JeromeJ
Я пытался связываться с пространством имен функции во время выполнения ранее (для тестирования / насмешки) и потерпел неудачу ... просто к вашему сведению. Mike Mazur
Вам удалось заставить это работать? Charlie Parker

Ваш Ответ

7   ответов
2

что вы хотите сделать это, потому что функция f определяется не вами, а каким-то другим модулем. Итак, вы хотите изменить работу f (). В частности, вы хотите изменить то, что вызывается, когда вызывается g.

Поэтому я предлагаю это:

import thirdpartypackage

def mynewg():
   pass

thirdpartypackage.g = mynewg

Это изменит глобальный g для модуля thirdpartypackage. Поэтому, когда теперь вызывается thirdpartypackage.f (), она будет вызывать mynewg () вместо g ().

Если это не решает проблему, возможно, g () фактически импортируется из функции f () или что-то в этом роде. Тогда решение таково:

import thirdpartypackage

def mynewg():
   pass

deg mynewf():
   mynewg()

thirdpartypackage.f = mynewf

То есть вы полностью переопределяете f () с помощью модифицированной версии, которая делает то, что вам нужно.

3

f() и передать ссылку наg()?

def g():
    pass

def f(func):
    func()

f(g)
0

def add_to_locals(l):
    l['newlocal'] = 1

add_to_locals(locals())
assert newlocal
Это не работает внутри функции. Это не добавляет значение в пространство имен.
3

она не имеет «локальной» функции. кадр стека, пока. Самое простое решение - использовать глобальный контекст:

handler = None
def f():
    handler()

def g(): pass

handler = g

Или вы можете установить g для объекта функции:

f.g = g

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

что, еслиf такое метод класса / экземпляра?
если тыreally Если вы хотите использовать объект функции внутри функции, вы можете использовать inspect: import inspect import pprint def fn (): frame = inspect.currentframe () print frame.f_globals [frame.f_code.co_name] .g fn.g = & apos; Привет & APOS; п ()
Это нарушается для функций класса, вложенных функций / замыканий и лямбда-выражений и всего, что украшено, - это будет возвращать функцию обертывания декоратора, а не фактическую функцию.
9

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

Один из вариантов состоит в том, чтобы просто внедрить вашу функцию в пространство имен модуля функции. Это будет работать, но повлияет на каждую функцию в этом модуле, которая обращается к переменной, а не только на одну функцию.

Чтобы повлиять только на одну функцию, вам нужно вместо этого указать, что func_globals где-то еще. К сожалению, это свойство только для чтения, но вы можете делать все, что хотите, воссоздав функцию с тем же телом, но с другим глобальным пространством имен:

import new
f = new.function(f.func_code, {'g': my_g_function}, f.func_name, f.func_defaults, f.func_closure)

Теперь f будет идентичным, за исключением того, что он будет искать глобальные переменные в предоставленном dict. Обратите внимание, что это связывает все глобальное пространство имен - если есть переменные, которые fdoes посмотрите вверх, убедитесь, что вы предоставляете их тоже. Это также довольно забавно и может не работать на версиях python, отличных от cpython.

Что случилось сexec или жеlocals().update(d)?
что этоnew библиотека?
Я не знаю, является ли это "хорошо" код, но это было именно то, что я хотел. Я преобразовываю одну кодовую базу в другую, и я хотел иметь возможность имитировать языковые конструкции из другого языка. Другой язык может упаковать код и добавить или удалить этот код из пространства имен. Это полезно при переопределении различных функций. Таким образом, он манипулирует пространством имен в стеке, как мода. Это самая близкая вещь, которую я могу найти, которая позволила бы мне сделать это эффективно. Спасибо
2

что вы могли бы решить проблему, решив ее с совершенно другой точки зрения.
Функции объектные, со своими словарями; следовательно, вы можете добавить g к f и использовать его:

def g():
   print "g"

def f():
    f.g()

f.g = g
что, еслиf такое метод класса / экземпляра?
Очень элегантное решение. +1
Не могли бы вы расширить это? Python-функции являются объектами, и нет различий, локальных или глобальных - если вы не имеете в видуmethods но это совсем другая история, а не то, о чем просил ОП.
Это работает только для глобальных функций; нет способа надежного доступа к f изнутри f.
1

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

Вы можете сделать что-то вроде этого, хотя:

def f():
    g = [1]
    def func():
        print g[0]
    return func, g

f, val = f()
f()
val[0] = 2
f()

Это использует массив для имитации ссылки.

Этот сайт должен действительно требовать объяснений для -1 голоса, поэтому люди не могут анонимно голосовать без правильных ответов.

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