简体   繁体   中英

Python join method inserting string rather than concatenating

I'm trying to write a method that takes in a file and then convert its file name into a string of random characters without changing the extension. However, somehow the .join() method is acting a bit unexpectedly by inserting the new string into the original string.

Minimal reproducible example:

import string
import random

random_string = "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10))
extension = "IMG_4078.JPG".rsplit(".", 1)[1]
filename = random_string.join([".", extension])
print(f"Random string: {random_string}")
print(f"Extension: {extension}")
print(f"File name: {filename}")

Result:

Random string: BgjnFKrLvc
Extension: JPG
File name: .BgjnFKrLvcJPG

I was expecting it to be BgjnFKrLvc.JPG and I wonder where am I doing it wrong.

Edit: Out of curiosity, I ran the timeit module to compare the two solutions filename = f"{random_string}.{extension}" versus filename = ".".join([random_string, extension]) . The former one ended up being slightly faster after I ran each 1M times (62.87387199999648s versus 63.04620390000491s respectively).

You are generating the random string right, you are getting the extension right, now simply concat them as:

filename = f"{random_string}.{extension}"

Alternative to f-string:

filename = "{}.{}".format(random_string, extension)

join() method returns a string by joining all the elements of an iterable separated by a string separator. In random_string.join(extension) , your string separator is random_string . That's why you get something weird like

import string
import random

random_string = "".join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10))
extension = "IMG_4078.JPG".rsplit(".", 1)[1]
filename = random_string.join(extension)

print(f"Random string: {random_string}")
print(f"Extension: {extension}")
print(f"File name: {filename}")
# Random string: Q1ZZbHEIdC
# Extension: JPG
# File name: JQ1ZZbHEIdCPQ1ZZbHEIdCG

For the correct implementation, use

filename = '.'.join([random_string, extension])

The grammar of the join method is counter-intuitive. From the docs :

str.join(iterable)¶ Return a string which is the concatenation of the strings in iterable. A TypeError will be raised if there are any non-string values in iterable, including bytes objects. The separator between elements is the string providing this method.

It's useful if you need the same separator several times or if you already have the things you want to concatenate in a list like when creating your random_string .

For just concatenating arbitrary strings there are two clearer ways to write it:

  • Use the concatenation operator ( + ): filename = random_string + "." + extension filename = random_string + "." + extension
  • Or use an f-string: filename = f"{random_string}.{extension}"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM