[Tutor] str.replace error
Steven D'Aprano
steve at pearwood.info
Fri Apr 26 00:29:01 EDT 2019
On Thu, Apr 25, 2019 at 10:46:31AM -0700, Roger Lea Scherer wrote:
> with open('somefile') as csvDataFile:
> csvReader = csv.reader(csvDataFile)
> for row in range(100):
> a = "Basic P1"
> str.replace(a, "")
> print(next(csvReader))
I'm not quite sure what you expected this to do, but you've
(deliberately? accidently?) run into one of the slightly advanced
corners of Python: unbound methods. Apologies in advance, but this may
be a bit technical. For a suggestion on how to fix the problem, see
right at the end.
Normally when you call a string method, you do something like this:
mystring = "Something here"
newstring = mystring.replace("here", "there")
The technical name for the mystring.replace call is a "bound method", as
the method is "bound" to a string instance (mystring). The method
actually takes *three* arguments: the string to operate on, the
substring to be replaced, and the replacement string:
(string to operate on) . replace ( substring to be replaced, replacement )
But under the hood, what that turns into is an "unbound method" that
calls the method attached to the *class* "str":
str.replace(string to operate on, substring to replace, replacement)
Alas, when you call an *unbound* method like this:
str.replace(a, "")
the interpreter may get a bit confused and report a slightly inaccurate
error message:
> TypeError: replace() takes at least 2 arguments (1 given)
For technical reasons, all the counts are off by one. The error message
should say:
TypeError: replace() takes at least 3 arguments (2 given)
but because the same error message gets used for both bound and unbound
methods, the counts are off for unbound methods. This is an annoyance,
but given that unbound methods are relatively rare, not a large one.
So how do you fix your code?
(1) First of all, you need a string to operate on. I'm not sure which
string that should be -- do you want to check *every* cell? Just the
first cell in each row? Every second row? That's up to you to decide.
(2) Secondly, strings in Python are "immutable" -- that is to say, they
cannot be changed in place. Unlike languages like (say) Pascal, if you
want to change the value of a string, you need to re-assign a new
string:
a = "Hello World!"
a.upper() # Doesn't work!!!
print(a) # Still gives "Hello World!"
Instead you need to say a = a.upper().
(3) Unbound methods are a slightly advanced technique which you don't
need here, so you should just use normal method call.
Putting those three changes together gives something like this:
with open('somefile') as csvDataFile:
csvReader = csv.reader(csvDataFile)
for row in range(100): # How do you know there are only 100 rows?
mystring = "Something here? ~Basic P1~ but I don't know what"
print("Before:", mystring)
mystring = mystring.replace("Basic P1", "")
print("After:", mystring)
print(next(csvReader))
Hopefully that's enough to set you on the right track. If not, please
feel free to write back to the list and ask more questions!
--
Steven
More information about the Tutor
mailing list