Repository: pylint-dev/pylint (Python)

Issue:
False positive undefined-variable when a function attribute of same name is set
### Steps to reproduce
```python
CONDITION = None
FUNC = lambda: CONDITION
FUNC.CONDITION = 42
```
Pylint output:
```
pylint_bug_repro.py:2:15: E0602: Undefined variable 'CONDITION' (undefined-variable)
```

### Current behavior
An "undefined variable" is incorrectly reported.

### Expected behavior
Zero issue detected when defining a [function attribute](https://www.python.org/dev/peps/pep-0232/)
with the same name of a local variable in the current scope.

### pylint --version output
```
$ pylint --version
pylint 2.6.0
astroid 2.4.2
Python 3.7.7 (default, Apr 10 2020, 07:59:19)
[GCC 9.3.0]
```

### Additional notes
There are a few other existing issues related to "false positive undefined-variable" errors:
- https://github.com/PyCQA/pylint/issues/2491
- https://github.com/PyCQA/pylint/issues/3688
- https://github.com/PyCQA/pylint/issues/3791
False positive: E0602 undefined variable with assignment expression
### Bug description

The following snippet produces `E0602: Undefined variable 'x_0' (undefined-variable)` as output from pylint.

```py
sorted_things = sorted(
        things,
        key=lambda thing: x_0 
        if (x_0 := thing.this_value)
        < (x_1 := thing.that_value)
        else x_1,
)
```

### Configuration

_No response_

### Command used

```shell
Basic `pylint` call as a pre-commit hook.
```


### Pylint output

```shell
pylint...................................................................Failed
- hook id: pylint
- exit code: 2

************* Module utils
project_dir/utils.py:197:22: E0602: Undefined variable 'x_0' (undefined-variable)
```


### Expected behavior

Should be no error.

### Pylint version

```shell
pylint --version
pylint 2.11.1
astroid 2.8.4
Python 3.9.5 (default, May  4 2021, 03:36:27) 
[Clang 12.0.0 (clang-1200.0.32.29)]
```


### OS / Environment

MacOS 11.5.2

### Additional dependencies

_No response_


Discussion:
@Lucas-C thanks for this clear report!
Thanks for the fix @Pierre-Sassoulas !
I just reviewed ; @DanielNoord did the actual work :wink: 





Patch:
diff --git a/ChangeLog b/ChangeLog
index 128ae03af3..3e4dc07652 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -50,6 +50,11 @@ Release date: TBA
 
 * ``used-before-assignment`` now checks names in try blocks.
 
+* Fixed false positive with ``used-before-assignment`` for assignment expressions
+  in lambda statements.
+
+  Closes #5360, #3877
+
 * Some files in ``pylint.testutils`` were deprecated. In the future imports should be done from the
   ``pylint.testutils.functional`` namespace directly.
 
diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst
index 5e5d73493a..73b6aa87e9 100644
--- a/doc/whatsnew/2.13.rst
+++ b/doc/whatsnew/2.13.rst
@@ -86,6 +86,11 @@ Other Changes
 
 * ``used-before-assignment`` now checks names in try blocks.
 
+* Fixed false positive with ``used-before-assignment`` for assignment expressions
+  in lambda statements.
+
+  Closes #5360, #3877
+
 * Require Python ``3.6.2`` to run pylint.
 
   Closes #5065
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 40fc99b633..8e2f868391 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -1402,10 +1402,6 @@ def _check_consumer(
                         "used-before-assignment", args=node.name, node=node
                     )
 
-                elif current_consumer.scope_type == "lambda":
-                    self.add_message("undefined-variable", args=node.name, node=node)
-                    return (VariableVisitConsumerAction.CONSUME, found_nodes)
-
         elif self._is_only_type_assignment(node, defstmt):
             self.add_message("undefined-variable", args=node.name, node=node)
             return (VariableVisitConsumerAction.CONSUME, found_nodes)


Test patch:
diff --git a/tests/functional/u/undefined/undefined_variable_py38.py b/tests/functional/u/undefined/undefined_variable_py38.py
index 3c00bfd854..81fa19f527 100644
--- a/tests/functional/u/undefined/undefined_variable_py38.py
+++ b/tests/functional/u/undefined/undefined_variable_py38.py
@@ -97,3 +97,14 @@ def no_parameters_in_function_default() -> None:
 COMPREHENSION_FIVE = {i: (else_assign_2 := i) if False else 0 for i in range(10)}
 
 print(else_assign_2)  # [undefined-variable]
+
+
+# Tests for assignment expressions in lambda statements
+
+things = []
+sorted_things = sorted(
+    things,
+    key=lambda thing: x_0
+    if (x_0 := thing.this_value) < (x_1 := thing.that_value)
+    else x_1,
+)