-
Notifications
You must be signed in to change notification settings - Fork 1k
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
PLR6201 should only hit for membership test on constant collections #8322
Comments
I also just interalized after writing this that in Python constants for the interpreter is just literals. Anything else, even if say you use the typing And there is a difference between using set and tuple and list for performance. OR more like between set and tuple/list. The latter are almost identical in some quick tests. import dis
import timeit
from enum import Enum, auto
from typing import Final
class Color(Enum):
RED = auto()
BLUE = auto()
GREEN = auto()
WHITE = auto()
YELLOW = auto()
BB = auto()
CC = auto()
DD = auto()
FF = auto()
EE = auto()
a: Final = 1
b: Final = 2
def foo():
test1 = 2 in [1, 2, 3]
test2 = 'c' in {'a', 'b', 'c'}
test3 = b in {Color.RED, Color.GREEN}
return None
dis.dis(foo)
def with_set():
return b in {Color.RED, Color.BLUE, Color.GREEN, Color.WHITE, Color.YELLOW, Color.BB, Color.CC, Color.DD, Color.FF, Color.EE}
def with_tuple():
return b in (Color.RED, Color.BLUE, Color.GREEN, Color.WHITE, Color.YELLOW, Color.BB, Color.CC, Color.DD, Color.FF, Color.EE)
def with_list():
return b in [Color.RED, Color.BLUE, Color.GREEN, Color.WHITE, Color.YELLOW, Color.BB, Color.CC, Color.DD, Color.FF, Color.EE]
print(f'With set: {timeit.timeit(with_set, number=10000)}')
print(f'With tuple: {timeit.timeit(with_tuple, number=10000)}')
print(f'With list: {timeit.timeit(with_list, number=10000)}') Output:
|
According to https://docs.python.org/3/whatsnew/3.2.html#optimizations since Python 3.2 constant literal collections are automatically loaded as a frozen set at compile time which make their loading time insignificant. So at that point it's suggested to replace constant collections of list/tuples with sets as set IN comparison is faster. Used ruff's https://docs.astral.sh/ruff/rules/literal-membership/ for this but had to be very careful and only accept constant literal suggestions. Since it suggests all IN collection checks to have this rule, I also disabled it from ruff's pyproject toml for now and opened an issue: astral-sh/ruff#8322
According to https://docs.python.org/3/whatsnew/3.2.html#optimizations since Python 3.2 constant literal collections are automatically loaded as a frozen set at compile time which make their loading time insignificant. So at that point it's suggested to replace constant collections of list/tuples with sets as set IN comparison is faster. Used ruff's https://docs.astral.sh/ruff/rules/literal-membership/ for this but had to be very careful and only accept constant literal suggestions. Since it suggests all IN collection checks to have this rule, I also disabled it from ruff's pyproject toml for now and opened an issue: astral-sh/ruff#8322
According to https://docs.python.org/3/whatsnew/3.2.html#optimizations since Python 3.2 constant literal collections are automatically loaded as a frozen set at compile time which make their loading time insignificant. So at that point it's suggested to replace constant collections of list/tuples with sets as set IN comparison is faster. Used ruff's https://docs.astral.sh/ruff/rules/literal-membership/ for this but had to be very careful and only accept constant literal suggestions. Since it suggests all IN collection checks to have this rule, I also disabled it from ruff's pyproject toml for now and opened an issue: astral-sh/ruff#8322
Ruff version
ruff 0.1.3
Ruff settings
Just make sure PLR6201 is enabled
Problem
Run ruff on this one.
It will hit you with something like:
As far as I understand this rule should only hit us for constant collections as the optimization in question mentions: https://docs.python.org/3/whatsnew/3.2.html#optimizations . So I would not expect to see it in test3.
For collections that have variables inside the optimizer does not, or more like can not do anything so initializing a set does not help in any way and incurs the set initialization "penalty" which the optimizer fixes for constant values.
Does this make sense?
The text was updated successfully, but these errors were encountered: