Skip to content

Cannot override class variable -- using Final and ClassVar #15616

Description

@christianbundy

Bug Report

PEP 591 indicates:

Type checkers should infer a final attribute that is initialized in a class body as being a class variable. Variables should not be annotated with both ClassVar and Final.

But in practice, Mypy displays a type error when you use Final on a subclass where the parent class used a ClassVar.

To Reproduce

from typing import ClassVar, Final, ClassVar, Literal


class Animal:
    description: ClassVar[str] = "hard to generalize"
    
    
class Dog(Animal):
    description: Final[str] = "very good"

https://mypy-play.net/?mypy=latest&python=3.11&gist=69298f23e25b94da7dadc694769db16d

Expected Behavior

No error.

Actual Behavior

Cannot override class variable (previously declared on base class "Animal") with instance variable  [misc]

You may be tempted to work around this with:

class Dog(Animal):
    description: Final[ClassVar[str]] = "very good"

But then Mypy outputs:

Variable should not be annotated with both ClassVar and Final  [misc]

Your Environment

  • Mypy version used: 1.4.1
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.11

Activity

  1. AlexWaygood commented on Jul 6, 2023

    @AlexWaygood
    Member

    I think mypy's behaviour is correct here. Your base class has an attribute description that's settable on the class object itself. But your subclass has an attribute description that's read-only in all situations. That seems like an incompatible override that violates the Liskov Substitution Principle.

    Remember that Final does not just mean "the name cannot be overridden in subclasses"; it also means "the name cannot be reassigned to in the same scope".

  2. christianbundy commented on Jul 7, 2023

    @christianbundy
    ContributorAuthor

    Makes sense to me, thanks a lot for the explanation!

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

    bugmypy got something wrongtopic-finalPEP 591topic-inheritanceInheritance and incompatible overrides

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions