Reputation: 203
Say we have some code like so :
placehold = "6"
string1 = "this is string one and %s" % placehold
print string1
placehold = "7"
print string1
When run, both of the print statements return as if placehold were ALWAYS 6. However, just before the second statement ran, placehold was changed to 7, so why does it not dynamically reflect in the string?
Also, would you be able to suggest a way to make the string return with 7?
Thank you
Upvotes: 3
Views: 3968
Reputation: 184260
Strings are immutable and can't be changed, but what you're trying to do doesn't work with mutable objects either, so mutability (or lack of it) is something of a red herring here.
The real reason is that Python does not work like Excel. Objects do not remember all the operations that have been performed on them, and then re-do those operations when you change any of the information that went into them. For Python to work that way, the language would need to retain either every state that every object had ever been in, or all the operations that had ever been performed on them along with their parameters. Either would make your programs use a lot more memory and run much more slowly. On top of that, suppose you used string1
in another expression: that value, too, would need to be updated. In Python 3, print()
is a function; should it be called again when the variable printed is changed?
There are languages that work like that, to some extent, but Python isn't one of them. Unless you explicitly arrange things otherwise (by writing and calling a function), Python evaluates an expression once and uses that exact result going forward.
In fact, what you want isn't even possible in Python. When you do string interpolation (the %
operation), the code that does it sees only the value of what you're interpolating. It doesn't know that the "6"
is coming from a variable called placehold
. Therefore it couldn't change the string later even if it wanted to, because there's no way for it to know that there's any relationship between placehold
and string1
. (Also, consider that you needn't be interpolating a single variable: it could be an expression such as placehold + "0"
. So Python would need to remember the entire expression, not just the variable name, to re-evaluate it later.)
You can write your own string subclass to provide the specific behavior you want:
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)
But this is fraught with scoping issues (basically, the class needs to be able to see placehold
, which means that variable and the class need to be defined in the same function or in the global scope). Also, if you use this special string in an operation with another string, say concatenation, it will almost certainly cease being special. To fix these issues is possible, but... hairy. I don't recommend it.
Upvotes: 2
Reputation: 48090
When you do:
string1 = "this is string one and %s" % placehold
You are creating a string string1
with %s
replaced by the value of placehold
On later changing the value of placehold
it won't have any impact on string1
as string does not hold the dynamic property of variable. In order to reflect the string with changed value, you have to again re-assign the string.
Alternatively, you may use .format()
as:
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
Upvotes: 7
Reputation: 627
Because you have already assigned a value to that variable once you execute the statement.
It sounds like you'd rather need a function such as:
def f(placehold):
return "this is string one and %s" % placehold
Now you can print(f("7"))
to achieve the desired functionality.
Upvotes: 4
Reputation: 6607
string1
will use whatever value of placehold
existed at the time string1
was declared. In your example, that value happens to be "6"
. To get string1
to "return with 7" you would need to reassign it (string1 = "this is string one and %s" % placehold
) after changing the value of placehold
.
Upvotes: 1