Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disallow access to instance variable via class #240

Open
JukkaL opened this issue Jul 15, 2013 · 6 comments
Open

Disallow access to instance variable via class #240

JukkaL opened this issue Jul 15, 2013 · 6 comments

Comments

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 15, 2013

Currently an instance variable can be accessed using the class, which is wrong. For example, this code is accepted by the type checker:

class A:
    def f(self) -> None:
        self.x = 1
A.x = 1 # accepted, but should be an error

Class variables need to be assigned in the class body:

class A:
    x = 1
A.x = 1 # ok, and should be ok
@JukkaL JukkaL removed the front end label Jul 25, 2014
@JukkaL
Copy link
Collaborator Author

JukkaL commented May 17, 2015

Actually, I'm no longer convinced that this is a bug. Turning this into an enhancement proposal.

@JukkaL JukkaL added needs discussion and removed bug mypy got something wrong labels May 17, 2015
@gvanrossum
Copy link
Member

Yeah, this may just be a somewhat unconventional wy of setting the default.

@JukkaL
Copy link
Collaborator Author

JukkaL commented Oct 13, 2015

Postponing this as I'm not sure if this is a good idea but might still be worth considering.

@mark-kubacki
Copy link

mark-kubacki commented Feb 18, 2022

The OP has it as writing—I ran into this erroneously reading a variable; consider:

from __future__ import annotations
import logging

from typing import Type


class A:
    def __init__(self):
        self._log = logging.getLogger()
        pass

    @classmethod
    def from_spam(cls: Type[A], spam):
        if spam:
            cls._log.warning("got spam")  # accepted, but should be an error
        return cls()

@gsakkis
Copy link

gsakkis commented Sep 11, 2023

I ran into a situation which is almost the opposite problem of the original one: not only a given attribute is deliberately accessible by both the instance and the class, but the type in each case different. Unsurprisingly mypy complains about Incompatible types in assignment.

Minimal example:

class A:
    x = "a"

    def __init__(self) -> None:
        self.x = 1

assert A().x == 1
assert A.x == "a"

I tried annotating x both as an instance and class variable but this caused a Name "x" already defined error without getting rid of the first one:

class A:
    x: int
    x: ClassVar[str] = "a"

    def __init__(self) -> None:
        self.x = 1

@vtgn
Copy link

vtgn commented Oct 15, 2024

Hello!
2024 here! What are the news since 2013?!

With Python 3.12.6 and mypy 1.11.2, mypy says still nothing on this case, but Pylint and Pylance do it, and there is an error during the code execution.

Plus, for this close similar case:

class A:
    id: Final[int] = 5

    def __init__(self):
        self.id = 10

a = A()

print(A.id) # => 5
print(a.id) # => 10
print(a.__class__.id) # => 5

mypy says Cannot assign to final attribute "id" mypy(misc) on the self.id = 10 line, which is incorrect because self.id defined in the constructor is considered as an instance attribute by Python, and not the class attribute A.id. :/
Pylance does exactly the same mistake. >_< !!!

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

No branches or pull requests

5 participants