Skip to content

PERF: Use list comprehension to join strings (#41753) #42173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from Jul 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions asv_bench/benchmarks/io/csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ class ReadCSVFloatPrecision(StringIORewind):

def setup(self, sep, decimal, float_precision):
floats = [
"".join(random.choice(string.digits) for _ in range(28)) for _ in range(15)
"".join([random.choice(string.digits) for _ in range(28)])
for _ in range(15)
]
rows = sep.join([f"0{decimal}" + "{}"] * 3) + "\n"
data = rows * 5
Expand Down Expand Up @@ -395,7 +396,7 @@ class ReadCSVCachedParseDates(StringIORewind):
param_names = ["do_cache", "engine"]

def setup(self, do_cache, engine):
data = ("\n".join(f"10/{year}" for year in range(2000, 2100)) + "\n") * 10
data = ("\n".join([f"10/{year}" for year in range(2000, 2100)]) + "\n") * 10
self.StringIO_input = StringIO(data)

def time_read_csv_cached(self, do_cache, engine):
Expand Down
2 changes: 1 addition & 1 deletion doc/source/user_guide/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5699,7 +5699,7 @@ Example of a callable using PostgreSQL `COPY clause
writer.writerows(data_iter)
s_buf.seek(0)

columns = ', '.join('"{}"'.format(k) for k in keys)
columns = ', '.join(['"{}"'.format(k) for k in keys])
if table.schema:
table_name = '{}.{}'.format(table.schema, table.name)
else:
Expand Down
2 changes: 1 addition & 1 deletion pandas/_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def _describe_option(pat: str = "", _print_desc: bool = True):
if len(keys) == 0:
raise OptionError("No such keys(s)")

s = "\n".join(_build_option_description(k) for k in keys)
s = "\n".join([_build_option_description(k) for k in keys])

if _print_desc:
print(s)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/computation/engines.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def _check_ne_builtin_clash(expr: Expr) -> None:
overlap = names & _ne_builtins

if overlap:
s = ", ".join(repr(x) for x in overlap)
s = ", ".join([repr(x) for x in overlap])
raise NumExprClobberingError(
f'Variables in expression "{expr}" overlap with builtins: ({s})'
)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/computation/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def create_valid_python_identifier(name: str) -> str:
}
)

name = "".join(special_characters_replacements.get(char, char) for char in name)
name = "".join([special_characters_replacements.get(char, char) for char in name])
name = "BACKTICK_QUOTED_STRING_" + name

if not name.isidentifier():
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/computation/pytables.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ def __init__(
else:
w = _validate_where(w)
where[idx] = w
_where = " & ".join(f"({w})" for w in com.flatten(where))
_where = " & ".join([f"({w})" for w in com.flatten(where)])
else:
# _validate_where ensures we otherwise have a string
_where = where
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/computation/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _raw_hex_id(obj) -> str:
"""Return the padded hexadecimal id of ``obj``."""
# interpret as a pointer since that's what really what id returns
packed = struct.pack("@P", id(obj))
return "".join(_replacer(x) for x in packed)
return "".join([_replacer(x) for x in packed])


DEFAULT_GLOBALS = {
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10980,7 +10980,7 @@ def last_valid_index(self) -> Hashable | None:
def _doc_params(cls):
"""Return a tuple of the doc params."""
axis_descr = (
f"{{{', '.join(f'{a} ({i})' for i, a in enumerate(cls._AXIS_ORDERS))}}}"
f"{{{', '.join([f'{a} ({i})' for i, a in enumerate(cls._AXIS_ORDERS)])}}}"
)
name = cls._constructor_sliced.__name__ if cls._AXIS_LEN > 1 else "scalar"
name2 = cls.__name__
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def __repr__(self) -> str:
result = f"{name}: {len(self)} dtype: {self.dtype}"
else:

shape = " x ".join(str(s) for s in self.shape)
shape = " x ".join([str(s) for s in self.shape])
result = f"{name}: {self.mgr_locs.indexer}, {shape}, dtype: {self.dtype}"

return result
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/formats/excel.py
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ def _generate_body(self, coloffset: int) -> Iterable[ExcelCell]:
series = self.df.iloc[:, colidx]
for i, val in enumerate(series):
if styles is not None:
css = ";".join(a + ":" + str(v) for (a, v) in styles[i, colidx])
css = ";".join([a + ":" + str(v) for (a, v) in styles[i, colidx]])
xlstyle = self.style_converter(css)
yield ExcelCell(self.rowcounter + i, colidx + coloffset, val, xlstyle)

Expand Down
8 changes: 4 additions & 4 deletions pandas/io/formats/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def get_result(self) -> str:
self.bottom_separator,
self.env_end,
]
result = "\n".join(item for item in elements if item)
result = "\n".join([item for item in elements if item])
trailing_newline = "\n"
result += trailing_newline
return result
Expand Down Expand Up @@ -527,13 +527,13 @@ def env_begin(self) -> str:
f"\\begin{{longtable}}{self._position_macro}{{{self.column_format}}}"
)
elements = [first_row, f"{self._caption_and_label()}"]
return "\n".join(item for item in elements if item)
return "\n".join([item for item in elements if item])

def _caption_and_label(self) -> str:
if self.caption or self.label:
double_backslash = "\\\\"
elements = [f"{self._caption_macro}", f"{self._label_macro}"]
caption_and_label = "\n".join(item for item in elements if item)
caption_and_label = "\n".join([item for item in elements if item])
caption_and_label += double_backslash
return caption_and_label
else:
Expand Down Expand Up @@ -611,7 +611,7 @@ def env_begin(self) -> str:
f"{self._label_macro}",
f"\\begin{{tabular}}{{{self.column_format}}}",
]
return "\n".join(item for item in elements if item)
return "\n".join([item for item in elements if item])

@property
def bottom_separator(self) -> str:
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,7 @@ def set_properties(self, subset: Subset | None = None, **kwargs) -> Styler:
>>> df.style.set_properties(color="white", align="right")
>>> df.style.set_properties(**{'background-color': 'yellow'})
"""
values = "".join(f"{p}: {v};" for p, v in kwargs.items())
values = "".join([f"{p}: {v};" for p, v in kwargs.items()])
return self.applymap(lambda x: values, subset=subset)

def bar(
Expand Down
16 changes: 8 additions & 8 deletions pandas/io/formats/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,9 @@ def build_attribs(self) -> None:
flat_col = col
if isinstance(col, tuple):
flat_col = (
"".join(str(c) for c in col).strip()
"".join([str(c) for c in col]).strip()
if "" in col
else "_".join(str(c) for c in col).strip()
else "_".join([str(c) for c in col]).strip()
)

attr_name = f"{self.prefix_uri}{flat_col}"
Expand All @@ -384,9 +384,9 @@ def build_elems(self) -> None:
flat_col = col
if isinstance(col, tuple):
flat_col = (
"".join(str(c) for c in col).strip()
"".join([str(c) for c in col]).strip()
if "" in col
else "_".join(str(c) for c in col).strip()
else "_".join([str(c) for c in col]).strip()
)

elem_name = f"{self.prefix_uri}{flat_col}"
Expand Down Expand Up @@ -529,9 +529,9 @@ def build_attribs(self) -> None:
flat_col = col
if isinstance(col, tuple):
flat_col = (
"".join(str(c) for c in col).strip()
"".join([str(c) for c in col]).strip()
if "" in col
else "_".join(str(c) for c in col).strip()
else "_".join([str(c) for c in col]).strip()
)

attr_name = f"{self.prefix_uri}{flat_col}"
Expand All @@ -556,9 +556,9 @@ def build_elems(self) -> None:
flat_col = col
if isinstance(col, tuple):
flat_col = (
"".join(str(c) for c in col).strip()
"".join([str(c) for c in col]).strip()
if "" in col
else "_".join(str(c) for c in col).strip()
else "_".join([str(c) for c in col]).strip()
)

elem_name = f"{self.prefix_uri}{flat_col}"
Expand Down
4 changes: 2 additions & 2 deletions pandas/io/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ def _build_xpath_expr(attrs) -> str:
if "class_" in attrs:
attrs["class"] = attrs.pop("class_")

s = " and ".join(f"@{k}={repr(v)}" for k, v in attrs.items())
s = " and ".join([f"@{k}={repr(v)}" for k, v in attrs.items()])
return f"[{s}]"


Expand Down Expand Up @@ -861,7 +861,7 @@ def _parser_dispatch(flavor):


def _print_as_set(s) -> str:
arg = ", ".join(pprint_thing(el) for el in s)
arg = ", ".join([pprint_thing(el) for el in s])
return f"{{{arg}}}"


Expand Down
4 changes: 2 additions & 2 deletions pandas/io/parsers/base_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def extract(r):
# level, then our header was too long.
for n in range(len(columns[0])):
if all(ensure_str(col[n]) in self.unnamed_cols for col in columns):
header = ",".join(str(x) for x in self.header)
header = ",".join([str(x) for x in self.header])
raise ParserError(
f"Passed header=[{header}] are too many rows "
"for this multi_index of columns"
Expand Down Expand Up @@ -1138,7 +1138,7 @@ def _try_convert_dates(parser: Callable, colspec, data_dict, columns):
else:
colnames.append(c)

new_name = "_".join(str(x) for x in colnames)
new_name = "_".join([str(x) for x in colnames])
to_parse = [data_dict[c] for c in colnames if c in data_dict]

new_col = parser(*to_parse)
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/parsers/python_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,7 @@ def get_rows(self, infer_nrows, skiprows=None):

def detect_colspecs(self, infer_nrows=100, skiprows=None):
# Regex escape the delimiters
delimiters = "".join(fr"\{x}" for x in self.delimiter)
delimiters = "".join([fr"\{x}" for x in self.delimiter])
pattern = re.compile(f"([^{delimiters}]+)")
rows = self.get_rows(infer_nrows, skiprows)
if not rows:
Expand Down
10 changes: 5 additions & 5 deletions pandas/io/pytables.py
Original file line number Diff line number Diff line change
Expand Up @@ -2641,7 +2641,7 @@ def __repr__(self) -> str:
s = self.shape
if s is not None:
if isinstance(s, (list, tuple)):
jshape = ",".join(pprint_thing(x) for x in s)
jshape = ",".join([pprint_thing(x) for x in s])
s = f"[{jshape}]"
return f"{self.pandas_type:12.12} (shape->{s})"
return self.pandas_type
Expand Down Expand Up @@ -3308,10 +3308,10 @@ def __repr__(self) -> str:

ver = ""
if self.is_old_version:
jver = ".".join(str(x) for x in self.version)
jver = ".".join([str(x) for x in self.version])
ver = f"[{jver}]"

jindex_axes = ",".join(a.name for a in self.index_axes)
jindex_axes = ",".join([a.name for a in self.index_axes])
return (
f"{self.pandas_type:12.12}{ver} "
f"(typ->{self.table_type_short},nrows->{self.nrows},"
Expand Down Expand Up @@ -3518,7 +3518,7 @@ def validate_version(self, where=None):
"""are we trying to operate on an old version?"""
if where is not None:
if self.version[0] <= 0 and self.version[1] <= 10 and self.version[2] < 1:
ws = incompatibility_doc % ".".join(str(x) for x in self.version)
ws = incompatibility_doc % ".".join([str(x) for x in self.version])
warnings.warn(ws, IncompatibilityWarning)

def validate_min_itemsize(self, min_itemsize):
Expand Down Expand Up @@ -4065,7 +4065,7 @@ def get_blk_items(mgr):
new_blocks.append(b)
new_blk_items.append(b_items)
except (IndexError, KeyError) as err:
jitems = ",".join(pprint_thing(item) for item in items)
jitems = ",".join([pprint_thing(item) for item in items])
raise ValueError(
f"cannot match existing table structure for [{jitems}] "
"on appending data"
Expand Down
6 changes: 3 additions & 3 deletions pandas/io/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -1913,7 +1913,7 @@ def insert_statement(self, *, num_rows: int):
col_names = ",".join(bracketed_names)

row_wildcards = ",".join([wld] * len(names))
wildcards = ",".join(f"({row_wildcards})" for _ in range(num_rows))
wildcards = ",".join([f"({row_wildcards})" for _ in range(num_rows)])
insert_statement = (
f"INSERT INTO {escape(self.name)} ({col_names}) VALUES {wildcards}"
)
Expand Down Expand Up @@ -1952,7 +1952,7 @@ def _create_table_setup(self):
keys = [self.keys]
else:
keys = self.keys
cnames_br = ", ".join(escape(c) for c in keys)
cnames_br = ", ".join([escape(c) for c in keys])
create_tbl_stmts.append(
f"CONSTRAINT {self.name}_pk PRIMARY KEY ({cnames_br})"
)
Expand All @@ -1972,7 +1972,7 @@ def _create_table_setup(self):
ix_cols = [cname for cname, _, is_index in column_names_and_types if is_index]
if len(ix_cols):
cnames = "_".join(ix_cols)
cnames_br = ",".join(escape(c) for c in ix_cols)
cnames_br = ",".join([escape(c) for c in ix_cols])
create_stmts.append(
"CREATE INDEX "
+ escape("ix_" + self.name + "_" + cnames)
Expand Down
4 changes: 2 additions & 2 deletions pandas/io/stata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1367,12 +1367,12 @@ def _read_old_header(self, first_char: bytes) -> None:
try:
self.typlist = [self.TYPE_MAP[typ] for typ in typlist]
except ValueError as err:
invalid_types = ",".join(str(x) for x in typlist)
invalid_types = ",".join([str(x) for x in typlist])
raise ValueError(f"cannot convert stata types [{invalid_types}]") from err
try:
self.dtyplist = [self.DTYPE_MAP[typ] for typ in typlist]
except ValueError as err:
invalid_dtypes = ",".join(str(x) for x in typlist)
invalid_dtypes = ",".join([str(x) for x in typlist])
raise ValueError(f"cannot convert stata dtypes [{invalid_dtypes}]") from err

if self.format_version > 108:
Expand Down
2 changes: 1 addition & 1 deletion pandas/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ def _get_call_args(backend_name, data, args, kwargs):
if args and isinstance(data, ABCSeries):
positional_args = str(args)[1:-1]
keyword_args = ", ".join(
f"{name}={repr(value)}" for (name, _), value in zip(arg_def, args)
[f"{name}={repr(value)}" for (name, _), value in zip(arg_def, args)]
)
msg = (
"`Series.plot()` should not be called with positional "
Expand Down
2 changes: 1 addition & 1 deletion pandas/plotting/_matplotlib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ def _get_index_name(self) -> str | None:
if isinstance(self.data.index, ABCMultiIndex):
name = self.data.index.names
if com.any_not_none(*name):
name = ",".join(pprint_thing(x) for x in name)
name = ",".join([pprint_thing(x) for x in name])
else:
name = None
else:
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/generic/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def finalize(self, other, method=None, **kwargs):
for name in self._metadata:
if method == "concat":
value = "+".join(
getattr(o, name) for o in other.objs if getattr(o, name, None)
[getattr(o, name) for o in other.objs if getattr(o, name, None)]
)
object.__setattr__(self, name, value)
else:
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/generic/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def finalize(self, other, method=None, **kwargs):
for name in self._metadata:
if method == "concat" and name == "filename":
value = "+".join(
getattr(o, name) for o in other.objs if getattr(o, name, None)
[getattr(o, name) for o in other.objs if getattr(o, name, None)]
)
object.__setattr__(self, name, value)
else:
Expand Down
12 changes: 7 additions & 5 deletions pandas/tests/indexes/period/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,13 @@ def test_get_indexer_mismatched_dtype_with_method(self, non_comparable_idx, meth
continue
# Two different error message patterns depending on dtypes
msg = "|".join(
re.escape(msg)
for msg in (
f"Cannot compare dtypes {pi.dtype} and {other.dtype}",
" not supported between instances of ",
)
[
re.escape(msg)
for msg in (
f"Cannot compare dtypes {pi.dtype} and {other.dtype}",
" not supported between instances of ",
)
]
)
with pytest.raises(TypeError, match=msg):
pi.get_indexer(other2, method=method)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/io/formats/style/test_align.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def bar_grad(a=None, b=None, c=None, d=None):
return ret + [
(
"background",
f"linear-gradient(90deg,{','.join(x for x in [a, b, c, d] if x)})",
f"linear-gradient(90deg,{','.join([x for x in [a, b, c, d] if x])})",
)
]

Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/io/formats/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,7 @@ def test_to_string(self):
)
lines = result.split("\n")
header = lines[0].strip().split()
joined = "\n".join(re.sub(r"\s+", " ", x).strip() for x in lines[1:])
joined = "\n".join([re.sub(r"\s+", " ", x).strip() for x in lines[1:]])
recons = read_csv(StringIO(joined), names=header, header=None, sep=" ")
tm.assert_series_equal(recons["B"], biggie["B"])
assert recons["A"].count() == biggie["A"].count()
Expand Down
Loading