Почему строковые переменные не обновляются при их изменении

#python #string #python-2.7 #string-formatting

#python #строка #python-2.7 #форматирование строки

Вопрос:

Допустим, у нас есть такой код :

 placehold = "6"
string1 = "this is string one and %s" % placehold

print string1

placehold = "7"
print string1
  

При запуске оба оператора печати возвращаются так, как если бы место размещения ВСЕГДА было 6. Однако непосредственно перед выполнением второго оператора место размещения было изменено на 7, так почему же оно динамически не отражается в строке?

Кроме того, не могли бы вы предложить способ вернуть строку с 7?

Спасибо

Комментарии:

1. Строки неизменяемы. Они не меняются. Используйте что-то вроде StringVar или переназначить

2. Вам нужно будет string1 = "this is string one and %s" % placehold повторить это после изменения на значение placehold , чтобы значение string1 изменилось.

Ответ №1:

Когда вы делаете:

 string1 = "this is string one and %s" % placehold
  

Вы создаете строку string1 с %s заменой на значение placehold On позже, изменение ее значения placehold не окажет никакого влияния string1 , поскольку string не содержит динамического свойства переменной. Чтобы отразить строку с измененным значением, вам нужно снова переназначить строку.

В качестве альтернативы вы можете использовать .format() как:

 string1 = "this is string one and {}"
placeholder = 6
print string1.format(placeholder)
# prints: this is string one and 6

placeholder = 7
print string1.format(placeholder)
# prints: this is string one and 7
  

Ответ №2:

Потому что вы уже присвоили значение этой переменной после выполнения инструкции.

Похоже, вам скорее понадобится такая функция, как:

 def f(placehold):
    return "this is string one and %s" % placehold
  

Теперь вы можете print(f("7")) достичь желаемой функциональности.

Ответ №3:

Строки неизменяемы и не могут быть изменены, но то, что вы пытаетесь сделать, также не работает с изменяемыми объектами, поэтому изменчивость (или ее отсутствие) здесь является чем-то вроде отвлекающего маневра.

Настоящая причина в том, что Python работает не так, как Excel. Объекты не запоминают все операции, которые были выполнены над ними, а затем повторно выполняют эти операции, когда вы изменяете какую-либо информацию, которая в них вошла. Чтобы Python работал таким образом, язык должен был бы сохранять либо каждое состояние, в котором когда-либо находился каждый объект, либо все операции, которые когда-либо выполнялись над ними вместе с их параметрами. Любой из них заставил бы ваши программы использовать намного больше памяти и работать намного медленнее. Кроме того, предположим, что вы использовали string1 в другом выражении: это значение тоже нужно будет обновить. В Python 3 print() это функция; должна ли она вызываться снова при изменении переменной printed?

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

На самом деле, то, что вы хотите, даже невозможно в Python. Когда вы выполняете интерполяцию строк ( % операцию), код, который ее выполняет, видит только значение того, что вы интерполируете. Он не знает, что "6" происходит от вызываемой переменной placehold . Поэтому он не смог бы изменить строку позже, даже если бы захотел, потому что у него нет возможности узнать, что между и есть какая-либо связь placehold string1 . (Кроме того, учтите, что вам не нужно интерполировать одну переменную: это может быть такое выражение, как placehold "0" . Поэтому Python должен был бы запомнить все выражение, а не только имя переменной, чтобы повторно оценить его позже.)

Вы можете написать свой собственный подкласс string, чтобы обеспечить конкретное поведение, которое вы хотите:

 class UpdatingString(str):
    def __str__(self):
        return self % placehold

placehold = "6"
string1 = UpdatingString("this is string one and %s")
print(string1)
placehold = "7"
print(string1)
  

Но это чревато проблемами с областью видимости (в основном, класс должен иметь возможность видеть placehold , что означает, что переменная и класс должны быть определены в одной функции или в глобальной области видимости). Кроме того, если вы используете эту специальную строку в операции с другой строкой, скажем, конкатенации, она почти наверняка перестанет быть специальной. Исправить эти проблемы возможно, но … сложно. Я не рекомендую это.

Комментарии:

1. Хорошее объяснение и решение!

Ответ №4:

string1 будет использоваться любое значение placehold , существовавшее на момент string1 объявления. В вашем примере это значение имеет "6" значение . Чтобы перейти string1 к «return with 7», вам нужно будет переназначить его ( string1 = "this is string one and %s" % placehold ) после изменения значения placehold .