Python - одна переменная равна другой переменной, хотя этого не должно быть

Вот мой пример кода. Это задумано как итеративная процедура для гаусс-зейделя (решателя матриц). По сути, когда ошибка достаточно мала, она выходит из цикла while.

i=1
while (i>0):
    x_past = x_present

    j=0
    while(j<3):
        value=0
        k=0
        while(k<3):
            if (k!=j):
                if (i==1):
                    if (k>j):
                        value=value+0
                    else:
                        value=value+x_present[k]*eqn[j][k]    
                else:
                    value=value+x_present[k]*eqn[j][k]
            else:
                value=value+eqn[j][k]
            k=k+1
        x_present[j:j+1]=[value]
        j=j+1
    print "X_PAST"
    print x_past
    print "X_PRESENT"
    print x_present    
    if (error(x_past, x_present)<10**-2):
        break;
    i=i+1

Я сократил код, чтобы он стал более управляемым. если вы не понимаете, что он делает, это не так важно для решения этой проблемы.

Вот в чем проблема. Каждый раз

x_present[j:j+1]=[value]

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

x_past=x_present

предложение, x_past никогда не делается равным x_present. Это заставляет меня думать, что проблема связана с какой-то комбинацией двух утверждений.

Это большая проблема, если x_past = x_present, ошибка = 0 каждый раз и цикл прерывается после первой итерации. Код действительно работает, например, если я приказываю коду выполнять 8 итераций, и в перерыве он дает мне ответ, на который он должен.

Я пытался понять это последние 4 часа и совершенно сбит с толку. Я не так давно работаю с python, так что мои навыки поиска и устранения проблем с синтаксисом не так уж хороши. Любая помощь будет оценена по достоинству!

Это дает мне право просматривать кого-то. при пробуждении. Мои глаза болят!

Ali Afshar 05.11.2008 11:57

Да, это, наверное, самый ужасный фрагмент кода Python, который я когда-либо видел. Python некрасив, если вы слишком далеко его вложили, так что не надо :)

Hannes Ovrén 05.11.2008 12:04

О, мама миа! Ужасный код =)

Rorick 23.09.2009 14:20
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
6
3
20 306
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Что такое x_past и x_present? Я не очень хорошо разбираюсь в Python, но с точки зрения .NET / Java, если они ссылаются на некоторую структуру данных (карту или что-то еще), то создание их ссылок на один и тот же объект (как вы делаете в начале) будет означать что любые изменения, внесенные через одну переменную, будут видны через другую. Похоже, вам нужно сделать копию структуры данных, а не просто выполнять присвоение ссылки. Имеется ли в структуре данных, с которой вы работаете, какие-либо функции «клонирования»?

Как я уже сказал, я не очень хорошо знаю Python, так что это может быть совершенно неправильно ...

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

user3850 05.11.2008 15:59

@hop: Да, это так - он предлагает OP попробовать. Здесь три варианта: 1) Ничего не говорите - это совсем не поможет. 2) Скажите что-нибудь, не объясняя неопределенности. Ложная уверенность - это нехорошо. 3) Объясните неопределенность (как я) - это честно и не дает ложных надежд.

Jon Skeet 05.11.2008 16:37

Как обычно, даже когда Джон Скит не знает конкретного языка программирования, оказывается, что язык программирования делает именно то, что, по его мнению, он делает.

ogerard 08.03.2012 16:49

Похоже, что x_present - это список. Я подозреваю, что это означает, что присвоение x_last = x_present превращает x_last в псевдоним, т.е. они ссылаются на одну и ту же переменную. Может ли это быть так?

в python нет переменных, только имена. и уж точно никаких псевдонимов.

user3850 05.11.2008 15:59

@hop: если вы вводите несколько привязок имен к одному объекту, это можно рассматривать как псевдоним. По крайней мере, термин «свободная переменная» присутствует в Python.

jfs 06.11.2008 14:07
Ответ принят как подходящий

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

Вы ссылаетесь на список, поэтому при изменении списка любая ссылка на этот список отразит это изменение. Показывать:

>>> x_present = [4,5,6]
>>>
>>> x_past = x_present
>>>
>>> x_past
[4, 5, 6]
>>>
>>> x_present.append(7)
>>>
>>> x_past
[4, 5, 6, 7]
>>>

Если вам нужна копия списка, вы должны это сделать, listcopy = mylist [:]. (или import copy;listcopy = copy.copy(mylist)

>>> x_past = x_present[:]
>>> x_past
[4, 5, 6, 7]
>>>
>>> x_present.append(8)
>>>
>>> x_past
[4, 5, 6, 7]

Хотя это действительно делает копию, это далеко не самый разборчивый способ сделать это. Рассмотрите альтернативы, такие как listcopy = list(mylist) или даже listcopy = copy.copy(mylist) после import copy

Joost 02.11.2015 12:39

попробуйте изменить строку x_past = x_present на x_past = [x for x in x_present] и посмотрите, поможет ли это.

Сокращение для копирования списка - моя любимая функция Python, поскольку я могу делать однострочные строки, которые невозможны на других языках:

greaterthan100 = [x for x in number if x > 100]

notinblacklist = [x for x in mylist if x not in blacklist]

firstchildofbigfamily = [x.child[0] for x in familylist if len(x.child) > 10]

В Python все является объектом. Таким образом, выражение x_past = x_present указывает на ту же ссылку.

Совсем неправда. >> x = 5 >> y = x >> x = 8 >> вывести x, y 8 5

Hannes Ovrén 05.11.2008 12:00

@kigural: Вы запутались. Переназначение x, конечно, не влияет на y. Эдди считает, что если вы измените объект, на который указывает x, видимое значение y также изменится, что правильно.

Deestan 05.11.2008 12:59

Как указывали другие, ответ заключается в замене: x_past = x_present на x_past = x_present[:]. В общем, вы можете использовать модуль copy для копирования объекта в Python.

>>> import copy
>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = a
>>> a += 10, 11
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> c = copy.copy(a) # shallow copy
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> del a[3:]
>>> a
[0, 1, 2]
>>> b
[0, 1, 2]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Ваш код, мягко говоря, непифоничен.

Его можно заменить чем-то вроде следующего кода:

import copy
# assert(len(x_present) >= len(eqn))

first = True
while True:
    x_past = copy.copy(x_present) # copy

    for j, eqj in enumerate(eqn):
        x_present[j] = sum(x_present[k] * eqj[k] 
                           for k in range(j if first else len(eqj)) 
                           if k != j)
        x_present[j] += eqj[j] 

    print "X_PAST\n%s\nX_PRESENT\n%s" % (x_past, x_present)
    if allequal(x_past, x_present, tolerance=10**-2):
        break
    first = False

Вот определение allequal() (с использованием абсолютной ошибки. Это может быть, а может и не быть хорошей идеей в вашем случае (вместо этого вы можете использовать относительную ошибку)):

def allequal(x, y, tolerance):
    return (len(x) == len(y) and 
            all(-tolerance < (xx - yy) < tolerance
                for xx, yy in zip(x, y)))

спасибо за предыдущий сол за копирование списков. Однако код, который вы дали мне для замены кода, который у меня есть, не работает. Проблема, похоже, заключается в x_present [j] = sum (x_present [k] ...

darudude 05.11.2008 18:37

@darudude: Для кода sum(.. требуется версия Python> = 2.5 Какую версию вы используете?

jfs 06.11.2008 03:14

@darudude: Я проверил, нет ли синтаксических ошибок на Python 2.5.2 в приведенном выше коде. Не знаю, верна ли семантика. Приведенный выше код является простой иллюстрацией того, как код Python отличается от кода в стиле C, Fortran.

jfs 06.11.2008 13:34

Другие вопросы по теме