mypy versus pytype

41 views
Skip to first unread message

folkert...@gmail.com

unread,
Mar 9, 2020, 12:39:36 PM3/9/20
to pytype
Hi,

I'm puzzled, why does mypy 0.761 says that this code is fine while pytype 2020.02.20 says it is broken?

from __future__ import annotations
import typing

class MyClass:

    def get_version(self) -> int:
        assert self.version is not None
        return self.version

    def __init__(self) -> None:
        self.version: int

Mypy says:
Success: no issues found in 1 source file

Pytype says:
in get_version: No attribute 'version' on MyClass [attribute-error]

Who is right?


Regards,

Folkert van Heusden

Teddy Sudol

unread,
Mar 9, 2020, 2:24:44 PM3/9/20
to folkert...@gmail.com, pytype
Pytype is. If you run that code and try to access MyClass().version, you'll get an AttributeError. Since version is never initialized, it's never set on MyClass.

(I tested this with Python 3.7. I believe it will work the same under other versions.)

-- Teddy


--
You received this message because you are subscribed to the Google Groups "pytype" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pytype+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pytype/2466f56a-05cd-4c7d-aeae-8fb98392e55f%40googlegroups.com.

Folkert van Heusden

unread,
Mar 9, 2020, 3:52:24 PM3/9/20
to Teddy Sudol, pytype
Hi,

Ok, you're right. But if I extend it with a setter and access only through the get/set, it runs fine (3.7.5).

from __future__ import annotations
import typing

class MyClass:

    def get_version(self) -> int:
        assert self.version is not None
        return self.version

    def set_version(self, v: int) -> None:
        self.version = v


    def __init__(self) -> None:
        self.version: int

m = MyClass()
m.set_version(1)
print(m.get_version())


--

Teddy Sudol

unread,
Mar 9, 2020, 4:32:09 PM3/9/20
to Folkert van Heusden, pytype
Until set_version is called, instances of MyClass still don't have a "version" attribute. If you call get_version before set_version, you'll get a type error. Pytype is correct to produce an error here because there is no way to prove that get_version will always be called before set_version.
This is called late initialization. It comes up in pytype's User Guide, and you can also make pytype ignore the issue by adding `_HAS_DYNAMIC_ATTRIBUTES = True` to MyClass.

(There's also an argument to be made that MyPy is correct here, because `self.version: int` proves you intend for MyClass to have a self.version attribute, and MyPy assumes you'll initialize self.version later. The typing standard for Python doesn't say either interpretation is correct.)

-- Teddy

Reply all
Reply to author
Forward
0 new messages