MartinThoma / flake8-simplify

❄ A flake8 plugin that helps you to simplify code
MIT License
185 stars 19 forks source link

[New Rule] `dict` use get with default rather than `if in mydict: else` #72

Closed jcpunk closed 2 years ago

jcpunk commented 2 years ago

Explanation

Dictionaries have built in methods for "fetch this value if it exists or use this default". The pattern of checking for the key and then assigning tends to pop up here and there. It is a good practice to validate the data exists before accessing it, but in this case it is more complex than just using the language buit-in behavior.

Example

# Bad
if "my_key" in example_dict:
    thing = example_dict["my_key"]
else:
    thing = "default_value"

# Good
thing = example_dict.get("my_key", "default_value")
MartinThoma commented 2 years ago

That's a good one! I'm uncertain when I will find the time to add it, but I definitely want to add it!

MartinThoma commented 2 years ago

Taking this

if key in a_dict:
    value = a_dict[key]
else:
    value = "default"

gives

$ astpretty --no-show-offsets /dev/stdin <<< `cat example.txt`
Module(
    body=[
        If(
            test=Compare(
                left=Name(id='key', ctx=Load()),
                ops=[In()],
                comparators=[Name(id='a_dict', ctx=Load())],
            ),
            body=[
                Assign(
                    targets=[Name(id='value', ctx=Store())],
                    value=Subscript(
                        value=Name(id='a_dict', ctx=Load()),
                        slice=Name(id='key', ctx=Load()),
                        ctx=Load(),
                    ),
                    type_comment=None,
                ),
            ],
            orelse=[
                Assign(
                    targets=[Name(id='value', ctx=Store())],
                    value=Constant(value='default', kind=None),
                    type_comment=None,
                ),
            ],
        ),
    ],
    type_ignores=[],
)