кросс-модульная переменная - PullRequest
1 голос
/ 07 января 2010

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

import foo as bar

Но я не хочу импортировать мои модули как "бар". Я хочу использовать его без префиксов, таких как

from foo import *

Используя это, невозможно изменять переменные из других модулей. чтение будет работать! любая идея? предложения?

Ответы [ 4 ]

3 голосов
/ 07 января 2010

Краткий ответ: нет, это невозможно, и вам придется использовать префикс.

Важно понимать, что from foo import x, y - это копирование x в ваше пространство имен. Это эквивалентно:

import foo
# COPY TO YOUR NAMESPACE
x = foo.x
y = foo.y
# `from foo import` does NOT leave `foo` in your namespace
def foo

Таким образом, каждый модуль получит локальную копию x и y. Изменение x не будет видно в других модулях, и вы не увидите изменений, которые делают другие модули: - (

Чтобы изменить центральную копию переменной, вы должны импортировать сам модуль: import foo и изменить foo.x. Таким образом, существует только одна копия, и все получают к ней доступ: -)

[В связанных вопросах также упоминается возможность поместить переменную общего доступа в модуль встроенный . DO NOT! Это исключило бы префикс для чтения, но не для записи, и это очень плохой стиль.]

Записка в защиту Python

Если вы не согласны с необходимостью использовать префикс foo. здесь, вы, вероятно, также не согласитесь с необходимостью использования префикса self. для доступа к переменным объекта. Суть в том, как работает Python - поскольку вы не объявляете переменные, нет другого выбора, кроме как использовать префиксы.

Но есть и плюс: читая код на Python, вы легко видите, где находится каждая переменная. ИМХО, это очень хорошо.

Подтверждающие доказательства: в других языках, таких как C ++ / Java, многие люди соблюдают соглашения, такие как префикс m_ для всех имен переменных объекта, для достижения аналогичного эффекта ...

Замечания по стилю

  1. Вам не нужно import foo as bar, просто используйте import foo.
    Форма as не делает ничего нового, она просто переименовывает ее, что просто сбивает с толку.
    Это полезно, только если «foo» очень длинное имя; особенно принят случай, когда «foo» живет глубоко в некотором пакете, поэтому вы можете сделать import long.package.foo as foo.

  2. from foo import * считается очень плохим стилем в программах, потому что:

    • Человек, читающий ваш код, не будет знать, откуда пришли имена.

    • Он загрязняет ваше пространство имен, что может привести к незначительным ошибкам, когда имена из столкновение разных модулей.

    Явная форма from foo import x, y в порядке, но начинает страдать от тех же проблем, если вы используете много имен из модуля.
    В таких случаях лучше всего import foo и явно написать foo.x, foo.y.

Итог: в случае сомнений лучше всего просто import foo.

Исключение: очень удобно использовать import * при экспериментах с интерактивным переводчиком. Однако обратите внимание, что он не очень хорошо работает с reload(), поэтому не используйте его при отладке изменяющегося кода. (Для отладки модуля, который вы пишете, лучше всего запустить новый интерпретатор внутри пространства имен модуля - python -i mymodule.py / F5 в IDLE.)

2 голосов
/ 07 января 2010

Насколько я знаю, нет способа импортировать значение из модуля и сделать его читаемым и доступным для записи в области импорта. Когда вы просто import foo в Python, он создает объект модуля с именем foo. Получение и установка атрибутов на объекте модуля изменит их в области видимости модуля. Но когда вы from foo import something, foo импортируется и объект модуля создается, но не возвращается. Вместо этого Python копирует указанные вами значения из foo и помещает их в локальную область. Если то, что вы импортируете, является неизменным типом типа int или str, то изменить его и отразить изменения в модуле foo невозможно. Это похоже на это:

>>> class N(object):
...   def __init__(self, value):
...     self.value = value
>>> n = N(3)
>>> value = n.value
>>> print value, n.value
3 3
>>> value = 4
>>> print value, n.value
4 3

За исключением грубых хаков, если вы действительно хотите иметь возможность изменять переменную модуля, вам нужно будет импортировать сам модуль и изменить переменную в модуле. Но, как правило, необходимость сделать это свидетельствует о плохом дизайне. Если вы являетесь автором рассматриваемого модуля foo, возможно, вы захотите взглянуть на некоторые другие, более Pythonic способы решения вашей проблемы.

0 голосов
/ 07 января 2010

from foo import * осуждается (я руководство по стилю Google , руководство по стилю OLPC - которое вы должны увидеть, так как оно имеет лучшие объяснения того, почему плохо - но не по PEP-8 , к сожалению). это делает для нечитаемого кода.

Рассмотрим:

from foo import *
from bar import *
from baz import *

dostuff()

Если у вас возникла ошибка при запуске dostuff(), где вы найдете проблему? Это могло произойти из любого такого импорта.

Для читабельного, поддерживаемого кода придерживайтесь from foo import bar. Для читаемого, модульного, обслуживаемого кода не взламывайте глобальные переменные - расширьте bar (путем подклассов, если вы не можете изменить исходный код), чтобы предоставить методы для изменения значений, к которым вам нужен доступ.

0 голосов
/ 07 января 2010

Используя import foo from bar, вы импортируете bar не как переменную, а как константу.

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