Consider the following code:
class A(object):
def __init__(self):
self.a = '123'
def __len__(self):
print('len')
return 2
def __getitem__(self, pos):
print('get pos', pos)
return self.a[pos]
a = A()
print(''.join(a))
My expected output:
> len
> get pos 0
> get pos 1
> 12
The real output:
> len
> get pos 0
> get pos 1
> get pos 2
> get pos 3
> 123
Try it your self. I cannot believe what happens here.
As I understand the behavior correctly, str.join() calls __len__ but ignores the value and calls __getItem__ until the index out of range exception.
I must overlook something because the implementation of join seems different:
https://github.com/python/cpython/blob/3.6/Objects/stringlib/join.h
My current workaround is:
def __getitem__(self, pos):
if pos >= len(self):
raise IndexError()
return self.a[pos]
This is ridiculous.
I tested it under with Python 3.6 and 3.7 (CPython).