# Issue about Self type mismatch

**URL:** <https://discuss.python.org/t/issue-about-self-type-mismatch/52564>\
**Category:** Python Help\
**Tags:** typing\
**Created:** [May 4, 2024, 7:11am UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564 "2024-05-04T07:11:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![gmdzy2010](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/gmdzy2010/32/9027_2.png) [@gmdzy2010](https://discuss.python.org/u/gmdzy2010)\
**Post date:** [May 4, 2024, 7:11am UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/1 "2024-05-04T07:11:38Z")

</div>

code snippet as follow:

```python
from typing import List, Self

class A:
    def __init__ (self) -> None:
        self.a_instances: List[Self] = []

    def test(self):
        self.a_instances.append(A())

```

then the type checker (Pyright) will raise an type mismatch between `Self@A` and `A`

AFAIK, type of `A()` is equal to Self and it should be. Is there something wrong?

---

<div class="post-metadata">

**Author:** ![FelixFourcolor](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/felixfourcolor/32/13104_2.png) [@FelixFourcolor](https://discuss.python.org/u/FelixFourcolor)\
**Post date:** [May 4, 2024, 7:59am UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/2 "2024-05-04T07:59:14Z")

</div>

> [@gmdzy2010](#):
>
> AFAIK, type of `A()` is equal to Self and it should be.

That’s not true if you think of inheritance. If you have a class `B` that inherits `A`, `B.test` still appends an `A` which is not `Self`.

---

<div class="post-metadata">

**Author:** ![JamesParrott](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamesparrott/32/10534_2.png) [@JamesParrott](https://discuss.python.org/u/JamesParrott)\
**Post date:** [May 4, 2024, 9:30am UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/3 "2024-05-04T09:30:50Z")

</div>

@gmdzy2010 Mypy is fine with your code. Perhaps it’s a Pyright issue.

```python
mypy self_check.py
Success: no issues found in 1 source file

```

@FelixFourcolor  
This would make `Self` no more useful than hardcoding the name of the class (`A`) into the annotation (albeit more maintainable). `Self` is a lot more useful than that, and subclasses are specifically catered for.

Perhaps you meant that `a=A(); a.test(B())` would fail type-checking?

> **[typing — Support for type hints](https://docs.python.org/3/library/typing.html#typing.Self)**
>
> Source code: Lib/typing.py This module provides runtime support for type hints. Consider the function below: The function moon\_weight takes an argument expected to be an instance of float, as indic...

```python
from typing import Self, reveal_type

class Foo:
    def return_self(self) -> Self:
        ...
        return self

class SubclassOfFoo(Foo): pass

reveal_type(Foo().return_self()) # Revealed type is "Foo"
reveal_type(SubclassOfFoo().return_self()) # Revealed type is "SubclassOfFoo"

```

---

<div class="post-metadata">

**Author:** ![kknechtel](https://avatars.discourse-cdn.com/v4/letter/k/e47c2d/32.png) [@kknechtel](https://discuss.python.org/u/kknechtel)\
**Post date:** [May 4, 2024, 9:36am UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/4 "2024-05-04T09:36:43Z")

</div>

I put `pyright self` [into a search engine](https://duckduckgo.com/?q=pyright+self) and got a Stack Overflow Q&A off the top that seems to be exactly the question of this thread:

> <https://stackoverflow.com/questions/76572214/python-pyright-selft-is-not-compatible-with-t>

---

<div class="post-metadata">

**Author:** ![gmdzy2010](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/gmdzy2010/32/9027_2.png) [@gmdzy2010](https://discuss.python.org/u/gmdzy2010)\
**Post date:** [May 4, 2024, 3:24pm UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/6 "2024-05-04T15:24:33Z")

</div>

It really helps me thanks a lot!

---

<div class="post-metadata">

**Author:** ![FelixFourcolor](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/felixfourcolor/32/13104_2.png) [@FelixFourcolor](https://discuss.python.org/u/FelixFourcolor)\
**Post date:** [May 4, 2024, 4:38pm UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/8 "2024-05-04T16:38:18Z")

</div>

@JamesParrott I suppose that’s mypy’s fault, because I don’t think the code is valid. Consider

```python
class B(A): 
    pass

b = B()

b.test()

instance = b.a_instances[0]
reveal_type(instance)

```

What is this type? The `a_instances` is declared as `list[Self]`, so the result should be a `Self`, i.e, `B`. But `test()` appends an `A`.

> [@JamesParrott](#):
>
> ```python
> class Foo:
> def return_self(self) -> Self:
> return self
> 
> class SubclassOfFoo(Foo): pass
> 
> ```

Your example doesn’t demonstrate what I’m talking about. This method `return self`, so the annotation is `-> Self` as it should be. What I’m talking about is more akin to this:

```python
class Foo:
    def return_self(self):
        return Foo()

```

You can’t annotate this method `-> Self`, because it returns `Foo` which is not `Self` for child classes. Similarly for OP’s question, they don’t return but append to a list, but it’s the same idea.

---

<div class="post-metadata">

**Author:** ![tjreedy](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tjreedy/32/137_2.png) [@tjreedy](https://discuss.python.org/u/tjreedy)\
**Post date:** [May 4, 2024, 9:03pm UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/9 "2024-05-04T21:03:16Z")

</div>

I don’t know anything about Self, or what you mean `A` to be, but unless you expect A to be a tree, I would expect `a_instances` to be a class attribute.

```python
class A:
    a_instances: List[Self] = []

    def __init__ (self) -> None:
        self.a_instances.append(A())

```

If you do want an instance attribute to make a tree or more general graph, `children` would be a more usual name.

---

<div class="post-metadata">

**Author:** ![JamesParrott](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamesparrott/32/10534_2.png) [@JamesParrott](https://discuss.python.org/u/JamesParrott)\
**Post date:** [May 6, 2024, 8:00pm UTC](https://discuss.python.org/t/issue-about-self-type-mismatch/52564/10 "2024-05-06T20:00:03Z")

</div>

I don’t find “correctness” in the form of Python type hinting to be half as helpful, as it is in the form of using ABCs or protocols, from the point of view of expressing intent. And even then, I don’t think correctness is particularly helpful at all. Python’s a dynamic language… But my opinion for what it’s worth:

The programmer can both choose to hardcode `.test` to append `A()`, and type hint `a_instances` as `Self` with no harm done, only if they do not support, and never intend to subclass `A`.

If they want to subclass `A` (or if `A` is part of a library API, whose downstream users may quite reasonably wish to subclass `A`), and append subclasses of `A`, then yes indeedy, they should either change the annotation to `List[A]`, or `.test` should append `self. __class__ ()` instead (if the `Self` type hint is to be kept).

Alternatively, perhaps the whole point of `.test` is that the test fails for subclasses? If that’s what the programmer wants to test, then Python allows that.
