Question or issue on macOS:
Please help me understand how the builtin os.path.join() function works. For example:
import os print os.path.join('cat','dog') # 'cat/dog' no surprise here print os.path.join('cat','dog').join('fish') # 'fcat/dogicat/dogscat/dogh'
On Mac (and i guess linux too) os.name is an alias for posixpath. So looking into the posixpath.py module, the join() function looks like this:
def join(a, *p): """Join two or more pathname components, inserting '/' as needed. If any component is an absolute path, all previous path components will be discarded. An empty last part will result in a path that ends with a separator.""" path = a for b in p: if b.startswith('/'): path = b elif path == '' or path.endswith('/'): path += b else: path += '/' + b return path
So join() returns a string. Why does os.path.join(‘something’).join(‘something else’) even work? Shouldn’t it raise something like ‘str’ object has no attribute ‘join’? I mean if I copy the function some other place and call it like renamed_join(‘foo’,’bar’) it works as expected but if i do renamed_join(‘foo’,’bar’).renamed_join(‘foobar’) will raise an AttributeError as expected. Hopefully this is not a very stupid question. It struck me just when I thought I was starting to understand python…
How to solve this problem?
Solution no. 1:
You can’t chain os.path.join
like that. os.path.join
returns a string; calling the join
method of that calls the regular string join
method, which is entirely unrelated.
Solution no. 2:
Your second join
call is not os.path.join
, it is str.join
. What this one does is that it joins the argument (as an iterable, meaning it can be seen as f, i, s, h
) with self as the separator (in your case, cat/dog
)
So basically, is puts cat/dog
between every letter of fish
.
Because str
has a join attribute.