48

I am using PyCharm to develop some Python app. I am trying to use as cutting-edge python as possible, so I am making use of new python features. I have a problem with type hinting.

Let's all take a look at my DataAnalyzer class:

class DataAnalyzer:

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass

Now PyCharm spams me with yellow bulbs wanting me to add type annotations to self.train_data and self.test_data. If I click this message to do so, PyCharm adds two lines at the beginning of my class:

class DataAnalyzer:
    train_data: pd.DataFrame
    test_data: pd.DataFrame

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass

I guess now it looks nicer, but AFAIK by writing those variables like this I make them static.

I thought about annotating the types like this:

class DataAnalyzer:

    def __init__(self, train_data: pd.DataFrame, test_data: pd.DataFrame) -> None:
        self.train_data: pd.DataFrame = train_data
        self.test_data: pd.DataFrame = test_data

    def analyze(self):
        pass

Which is definitely not clear, but I am not making my class members static, when I don't want to.

I know, that by having the types annotated in the method signature, doing this one more time when I just assign those, is an overkill, but I am asking for the general rule. Should I annotate those types like PyCharm suggests me to, or should I do this inline?

6
  • it's weird, which PyCharm version are you using? in my code it works fine with initial approach Commented Dec 22, 2018 at 15:45
  • 15
    By the way, it does not make the members static: python.org/dev/peps/pep-0526/… Commented Dec 22, 2018 at 15:46
  • @AzatIbrakov it works, but PyCharm suggests me to change it Commented Dec 22, 2018 at 15:46
  • 1
    Yes, ClassVar are (static) class variables, while otherwise it's an instance member. Though as described later in the PEP your last approach is also considered a valid convention (possibly related question: stackoverflow.com/questions/44959876/…) Commented Dec 22, 2018 at 15:53
  • 1
    Does this answer your question? Type Hints Convention for Instance Variables Python Commented Mar 21, 2020 at 10:10

2 Answers 2

35

PyCharm's suggest is right. In fact, I think the following code is better:

class DataAnalyzer:
    train_data: pd.DataFrame
    test_data: pd.DataFrame

    def __init__(self, train_data, test_data):
        self.train_data = train_data
        self.test_data = test_data

    def analyze(self):
        pass

Explain:

  • Annotate a member does not make it static.
  • We should not annotate arguments in the __init__ function again.
  • -> None after __init__ can be omitted. For __init__ never return a value.
Sign up to request clarification or add additional context in comments.

6 Comments

Your comment regarding -> None contradicts PEP 484: "Note that the return type of __init__ ought to be annotated with -> None. The reason for this is subtle. If __init__ assumed a return annotation of -> None, would that mean that an argument-less, un-annotated __init__ method should still be type-checked? Rather than leaving this ambiguous or introducing an exception to the exception, we simply say that __init__ ought to have a return annotation; the default behavior is thus the same as for other methods."
Why should you not annotate the types of the init parameters? They are carrying the same name as the instance members, but they are in fact different variables.
@Sternerson, you are right. Another point to annotate __init__ parameters is to get prompts from pycharm when you instantiate object (call its constructor).
I don't consider this method, artificial class attributes with same name as instance attributes, as correct. In fact, you setup both class and instance attributes with same name and I consider it misleading and potentially error prone. Class attributes are used for different purposes.
@karel-marik FYI the type hints do not create class attributes in this example. That only happens if a value is assigned. It's explained in peps.python.org/pep-0526/… "the value-less notation a: int allows one to annotate instance variables that should be initialized in __init__" Also I tested some sample code similar to this and confirmed that it does not create a class attribute.
|
13

Both options are valid - check out pep 526

Type annotations can also be used to annotate class and instance variables in class bodies and methods. In particular, the value-less notation a: int allows one to annotate instance variables that should be initialized in __init__ or __new__.

The MyPy documentation is also a good resource for type hinting

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.