Type annotation pitfall

Peter Saalbrink petersaalbrink at gmail.com
Fri Sep 24 07:28:29 EDT 2021


I don't think this has anything to do with typing or providing type hints.
The type hint is the `: set` part, not the `= set()` part.
You can declare the type without assigning to the variable.
Indeed, as you already said, `x` is a class property here, and is shared
amongst instances of the class.
It might be a good idea to move the attribute assignment to the `__init__`
method.

In the following way, you can safely provide the type hint:

```python
class Foo:
    x: set

    def __init__(self, s):
        self.x = set()
        if s:
            self.x.add(s)
```

Or, even shorter:

```python
class Foo:
    def __init__(self, s: str):
        self.x: set[str] = {s} if s else set()

print(reveal_type(Foo.x))  # mypy only
```

On Fri, Sep 24, 2021 at 7:58 AM Robert Latest via Python-list <
python-list at python.org> wrote:

> Hi all,
>
> this just caused me several hours of my life until I could whittle it down
> to
> this minimal example. Simple question: Why is the x member of object "foo"
> modified by initializing "bar"?
>
> Obviously, initializing foo with None doesn't set foo.x at all. So I guess
> x
> stays a class property, not an instance property. And instantiating bar
> just
> added an item to the class property but didn't instantiate a new set. So
> basically, neither foo nor bar ever had their "own" x, right?
>
> Oooohh, dangerous! Never use mutable types in type hint, unless it's in
> explicit dataclasses (which automatically add an appropriate __init__()?)
>
> Now I must fine-comb all my code for more of these.
>
> class Foo():
>     x : set = set()
>
>     def __init__(self, s):
>         if s:
>             self.x.add(s)
>
> foo = Foo(None)
> print(foo.x) # prints 'set()'
> bar = Foo('abc')
> print(foo.x) # prints '{'abc'}
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>


More information about the Python-list mailing list