I am studying duck typing in Python,I know that if you implement some special methods for a class, you can happily use the built-in class methods
for example:
class A:
def __init__(self,l):
self._l = l
def __iter__(self):
return iter(self._l)
If I do this ,I can use for...in..,zip
, and some other methods that is built in and also can do some other stuffs, like implement __setitem__()
,so I can use random.choice,random.shuffle,and I feel python is so cool,but then I find this problem,I want to use join to print some objects that I implemented their __str__
methods,but it won't work
I find that this is because when we use join,we write it like ';'.join(l)
,so the duck typing trick won't work for it,because it use str's methods rather than the objects will be joined
@SethMMorton is point my doubts,thank you
I know I can use ';'.join([str(i) for i in l])
to solve my problem,but I don't know why python don't do it itself?
Answering the "why": Everything in Python is convertible to str
, as even without __str__
, the repr
of the object is used when a str
form is requested. Python may be flexible, but what you're describing is weak typing (which Python doesn't do in general), not duck typing. The presence of __str__
means you can coerce to a string, but it doesn't mean "is a string".
Allowing arbitrary iterables to be iterated with for
loops, zip
, etc. isn't weak typing, because it's a common interface with no ambiguity; iterables iterate the same way, even if they might produce different types.
Actual weak typing is dangerous, because it can allow errors to pass silently. It's particularly noticeable in Python 3. If automatic coercion to str
was allowed, and you did:
iterable_of_bytes_objects = b'123', b'456'
','.join(iterable_of_bytes_objects)
You'd silently produce "b'123',b'456'"
, when odds are, you just forgot the leading b
on the join string, and meant:
b','.join(iterable_of_bytes_objects)
Or maybe you meant to produce a string but forgot to decode
the bytes
. Or maybe you wanted the repr
of each object, or the str
, or whatever. Python has no idea, and per the Zen of Python (import this
):
In the face of ambiguity, refuse the temptation to guess.
as well as:
Explicit is better than implicit.
Coercing automatically hides errors and involves heuristic guesswork about what people "probably want". If you want to coerce, that's what ','.join(map(str, iterable))
is for, but it means you opted in to a specific form of coercion, and it's assumed you know what you're doing, which matches the other Zen requirements:
Errors should never pass silently.
Unless explicitly silenced.
This isn't a problem with duck-typing. It's a problem with the items contained in your custom series class. You will get the same error if you try to join a numeric range()
. Instead do this:
';'.join(str(i) for i in l)
This is explained clearly in the documentation for string.join(iterable)
: "Return a string which is the concatenation of the strings in the iterable iterable."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With