Skip to content

E731: Lambda default value for a Callable dataclass field is incorrectly flagged as lambda assignment #10718

@richardxia

Description

@richardxia

The pycodestyle rule lambda-assignment (E731) is supposed to check whether a lambda expression is being assigned to a variable and instead suggest using a def statement. However, Ruff's implementation appears to be incorrectly flagging a dataclass field with a default value consisting of a lambda expression as violation of this rule, whereas pycodestyle does not. Here is a short example:

from dataclasses import dataclass
from typing import Callable


@dataclass
class Filter:
    filter: Callable[[str], bool] = lambda _: True

Here is the command-line output of both Ruff and pycodestyle:

$ ruff check --isolated --select=E731 mycode.py 
mycode.py:7:5: E731 Do not assign a `lambda` expression, use a `def`
Found 1 error.
$ pycodestyle --select=E731 mycode.py

(No output for pycodestyle, but exits successfully with status code 0.)

The examples above were run with ruff 0.3.4 and pycodestyle 2.11.1, which are the latest versions at the time of this writing.

This should apply to more classes than just dataclasses, but I'm not exactly sure where I would draw the line. You probably do want to flag cases where someone assigned a lambda to a class variable when it should have been a class or instance method, but I'm not sure which heuristics you want to apply.

I haven't tried reading the pycodestyle source code to see how they implemented it, but playing with my example above, I think their heuristic may just be whether or not an annotation is present on the class member declaration, which seems reasonable to me. Here are a few specific example with inline comments on whether pycodestyle reports a violation:

from dataclasses import dataclass
from typing import Callable


# pycodestyle is happy with this
@dataclass
class FilterDataclass:
    filter: Callable[[str], bool] = lambda _: True


# pycodestyle is happy with this
class FilterClassWithCallableAnno:
    filter: Callable[[str], bool] = lambda _: True


# pycodestyle is happy with this
class FilterClassWithAribtraryAnno:
    filter: Foo = lambda _: True


# pycodestyle is _not_ happy with this
# mycode.py:24:5: E731 do not assign a lambda expression, use a def
class FilterClassWithoutAnno:
    filter = lambda _: True

Metadata

Metadata

Assignees

Labels

ruleImplementing or modifying a lint rule

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions