Область применения «библиотечных» методов - PullRequest
2 голосов
/ 08 апреля 2010

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

Справочная информация:
Я использую

if __name__ == "__main__"

конструкция для выполнения "самопроверки" в моих модулях. Каждый самопроверка вызывает различные публичные методы и выводит их результаты для визуальной проверки по мере разработки модулей.

Чтобы сделать вещи «чистыми» и управляемыми, я создал небольшой метод для упрощения тестирования вызовов методов:

def pprint_vars(var_in):
    print("%s = '%s'" % (var_in, eval(var_in)))

Когда

foo = "bar"

Вызов pprint_vars с помощью:

pprint_vars('foo')

печать:

foo = 'bar'

Все хорошо и хорошо.

Постановка задачи:
Не в восторге от просто KISS, у меня хватило ума переместить мой удобный метод 'pprint_vars' в отдельный файл с именем 'debug_tools.py' и просто импортировать 'debug_tools' всякий раз, когда я хотел получить доступ к 'pprint_vars'.

Здесь все разваливается. Я ожидал бы

import debug_tools

foo = bar
debug_tools.pprint_vars('foo')

для продолжения работы над магией и печати:

foo = 'bar'

Вместо этого он приветствует меня:

NameError: name 'some_var' is not defined

Иррациональное убеждение:
Я полагал (по-видимому, ошибочно), что импорт помещает импортированные методы (более или менее) «в линию» вместе с кодом, и, таким образом, правила области видимости переменной останутся такими же, как если бы метод был определен как встроенный.

Мольба о помощи:
Может кто-нибудь исправить мои (неправильные) представления об объемах импорта?

Спасибо, JS

Ответы [ 5 ]

2 голосов
/ 08 апреля 2010

В python каждый файл является собственным пространством имен. Функция при вызове разрешает свои переменные в следующем порядке:

  1. локальные переменные (включая захваченные переменные или замыкание)
  2. (модуль) глобальные переменные
  3. 1008 * встроенные команды *

Вы можете использовать (специфичный для интерпретатора) модуль inspect для навигации по стеку вызовов в виде списка кадров. Поскольку фрейм знает свои локальные, глобальные, встроенные и родительские фреймы, вы можете «увидеть» интерпретатор глазами вызывающего абонента следующим образом (используйте только для отладки):

import inspect
def log_var(name):
    f = inspect.currentframe().f_back
    if name in f.f_locals:
        print "local `%s` = %r" % (name, f.f_locals[name])
    elif name in f.f_globals:
        print "global `%s` = %r" % (name, f.f_globals[name])
    elif name in f.f_builtins:
        print "builtin `%s` = %r" % (name, f.f_builtins[name])
    else:
        print "`%s` not found" % name
2 голосов
/ 08 апреля 2010

«Глобальная область» фактически не существует в Python. То, что обычно называют «глобальной областью действия», на самом деле является областью действия модуля . То есть имена, определенные на уровне модуля. Помещение функции в другой модуль означает, что область его модуля изменяется.

1 голос
/ 08 апреля 2010

Я бы порекомендовал передать функции localals (), например, так:

def pprint_var(var_name, D):
    print "%s = %r" % (var_name, D[var_name])

...

pprint_var(var_name, locals())

, если вы этого не хотите, выможно использовать модуль inspect или sys._getframe, чтобы сделать то же самое, как предлагали другие.

0 голосов
/ 08 апреля 2010

Основная проблема, с которой я сталкиваюсь, заключается в том, что Python не имеет смысла name для простых объектов.Для методов, классов и т. Д. Да, для простых объектов - нет.

Так что в языках с переменными моя функция ppvar будет выглядеть примерно так (псевдокод):

ppvar( var_name ):
    print("%s = '%s'", var_name, $var_name)

Я мог бы импортировать файл, содержащий 'ppvar', в любой проект и вызывать его, и он, по сути, был бы «встроен» в мой код.для объектно-ориентированных подходов.

Все языки имеют свои плюсы и минусы.У каждого языка есть несколько «простых» вещей, на которые он падает.Способность выполнять что-то вроде:

print("%s = '%s'" % (var.__name__, var)

в Python - это (пока) не то, что будет работать.Ну хорошо.

0 голосов
/ 08 апреля 2010

eval принимает два необязательных параметра - global и local - которые вы можете указать как контекст для оценки вашего источника:

print("%s = '%s'" % (var_in, eval(var_in, globals())))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...