Skip to content

Specialized sub-classes of Generic never call __init__ #192

Closed

Description

@gvanrossum

See http://bugs.python.org/issue26391 .

"""
A specialized sub-class of a generic type never calls __init__ when it is instantiated. See below for an example:

from typing import Generic, TypeVar

T = TypeVar('T')
class Foo(Generic[T]):
    def __init__(self, value: T):
        self.value = value

Bar = Foo[str]

foo = Foo('foo')
bar = Bar('bar')

print(type(foo), end=' ')
print(foo.value)

print(type(bar), end=' ')
print(bar.value) # AttributeError

I would expect Foo[str], Foo[int], etc to be equivalent to Foo at run-time. If this is not the case it might deserve an explicit mention in the docs. At the moment, behaviour is confusing because an instance of Foo is returned that does not have any of its attributes set.
"""

Activity

  1. added this to the 3.5.2 milestone on Mar 23, 2016
  2. gvanrossum commented on Apr 1, 2016

    @gvanrossum
    MemberAuthor

    (Update, copied from the CPython bug:)

    Actually, I just realized why this is. Generic.__new__() calls next_in_mro.__new__(_gorg(cls)). Here next_in_mro is just object, but _gorg(cls) is Foo, in the case where cls is Bar (i.e. Foo[str]). The _gorg() call strips the [str] part of the type.

    So far so good. Where it gets interesting is that, in general in Python, whenever __new__(cls, ...) returns an object whose class is not cls, it is presumed to be an already properly initialized object!

    I think I can fix this by calling __init__() explicitly in the case where _gorg(cls) is not cls.

    The reason, BTW, why it strips the [str] part of the class is because that's what PEP 484 says, in the same section where it says that NodeT and Nodeint are allowed:

    At runtime the type is not preserved, and the class of x is just
    Node in all cases.

    So this bit of code is trying to do the right thing but obviously hasn't been tested much, because mypy disallows that syntax.

  3. added a commit that references this issue on Apr 2, 2016
  4. gvanrossum commented on Apr 2, 2016

    @gvanrossum
    MemberAuthor

    See also 37a3dd5 which backports the fix to Python 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions