Неожиданное поведение при импорте, обработка целых чисел и списков по-разному - PullRequest
2 голосов
/ 12 мая 2011

У меня проблема с моей программой, и я смог воспроизвести это неожиданное (по крайней мере, неожиданное для меня) поведение в небольшом масштабе, так что теперь я уверен, что это не другая ошибка.

Допустим, у меня есть 3 модуля Python: one, two и three.

В three имеем:

var = 0
list = []

Итак, у нас есть целое число, равное нулю, и пустой список.

В two имеем:

from three import var, list

def funct():
    print var*2
    print list
    return

Итак, мы импортируем var и list и просто определяем функцию, которая будет печатать оба и возвращать.

Вместо того, чтобы вызывать funct() в two, я вызывал его в one, но не раньше, чем совершал с ними «операции».

from three import var, list
from two import funct

if 2 < 4:
    var += 1
    list.append("x")

print funct()

Итак, вот и мой вопрос.

Я никогда не ожидал такого результата:

0
['x']
None

Почему x был добавлен в список с append(), а 1 НЕ добавлено к var, чтобы быть понятным. Я ожидал:

2
['x']
None

Если вам очень странно, что они получают разные виды лечения при одинаковых обстоятельствах.

  • Я что-то здесь упускаю?
  • Что-то не так с импортом?

Если нет:

  • Почему он так себя ведет?
  • Как решить / решить эту проблему?

Спасибо заранее.

Ответы [ 3 ]

2 голосов
/ 12 мая 2011

Это не имеет ничего общего с импортом, и все, что связано с различными типами.

list является изменяемым типом.list.append изменяет объект на месте и возвращает None.

int - неизменный тип.Его оператор += возвращает новый объект.

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

2 голосов
/ 12 мая 2011

Чтобы "исправить" вашу программу, вы должны добавить "global var", как в:

if 2 < 4:
     global var
     var += 1
     list.append("x")

Но это незаконно согласно http://docs.python.org/reference/simple_stmts.html#global:

Имена, перечисленные в глобальном операторе, не должны определяться как формальные параметры или в целевом элементе управления цикла for, определении класса, определении функции или операторе импорта.

Опять же, перейдя по ссылке выше:

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

Редактировать:

Решение состоит в том, чтобы изменить:

from three import var, list

до:

from three import list
import three

тогда не используйте глобальное пространство имен, но явно укажите пространство имен трех (вы импортировали символ)

код:

three.var += 1

Убедитесь, что two.py и one.py изменены в их операторах import / from

http://docs.python.org/tutorial/modules.html#more-on-modules

Каждый модуль имеет свою собственную таблицу частных символов, которая используется в качестве глобальной таблицы символов всеми функциями, определенными в модуле. Таким образом, автор модуля может использовать глобальные переменные в модуле, не беспокоясь о случайных столкновениях с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, вы можете прикоснуться к глобальным переменным модуля с той же нотацией, что и для ссылки на его функции, modname.itemname.

0 голосов
/ 12 мая 2011

Импорт имени копирует ссылку, содержащуюся в имени, на ваш модуль.В вашем коде целое число восстанавливается, но список видоизменяется.Поскольку ссылка на список никогда не изменяется, исходный объект видоизменяется.Отсюда и другое целое число, тот же список.

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