Могу ли я получить значение нелокальной переменной без использования нелокального оператора? - PullRequest
1 голос
/ 23 марта 2020

У меня есть локальная переменная x = "local", которая, к сожалению, имеет общее имя с глобальной и нелокальной переменной. Могу ли я получить доступ ко всем трем значениям, не меняя ни одного из имен? Для x = "global" есть globals(), но как насчет нелокальной переменной?

Минимальный пример, иллюстрирующий проблему:

x = "global"
def f(x="nonlocal"):
    def g():
        x = "local"
        print(x)  # same as locals()["x"]
        print(globals()["x"])
        # here I want to print the non-local x
    return g

f()()

Ответы [ 3 ]

2 голосов
/ 23 марта 2020

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

x = "global"


def f(x="nonlocal"):
    nonlocals = locals()

    def g():
        x = "local"
        print(x)
        print(nonlocals['x'])
        print(globals()["x"])

    return g


f()()

вывод:

local
nonlocal
global
1 голос
/ 29 марта 2020

Хотя вы не могли сделать это с кодом, написанным точно так, как указано, вы можете использовать inspect для получения нелокальных переменных. Обратите внимание на изменения звонка и возврата. Если вызывающая сторона является внешней областью вместо глобальной области видимости, предыдущий кадр будет f.

import inspect

x = "global"
def f(x="nonlocal"):
    def g():
        x = "local"
        print(x)
        print(globals()["x"])
        print(inspect.currentframe().f_back.f_locals["x"])

    return g()


f()

Вывод

локальный
глобальный
нелокальный

Это может не помочь в данной конкретной ситуации c, это действительно зависит от того, насколько вы контролируете содержимое f. Если у вас нет контроля над этим, вы также можете сделать обезьяну-патч f. Многое зависит от контекста.

0 голосов
/ 23 марта 2020

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


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

x = "global"
def f(x="nonlocal"):
    def g():
        nonlocal x
        y = x
        x = "local"
        print(x)  # same as locals()["x"]
        print(globals()["x"])
        print(y)
    return g


f()()

Вывод

local
global
nonlocal
...