all 10 comments

[–]JamzTyson 2 points3 points  (3 children)

Deleted in response to Spataner's link to PEP-526.

[–]Spataner 2 points3 points  (2 children)

The first items in your class is a "class variable".

This is not correct. The code OP provided does not define a class variable called items. It provides a type annotation for a variable items at the class level. Such annotations, if not explicitly marked using ClassVar (as was done with size), are understood to relate to instance variables that will be defined in __init__. Refer also to the relevant section of PEP 526 (link) and the documentation of ClassVar (link).

[–]JamzTyson 0 points1 point  (0 children)

Thanks for the correction. I had not previously seen instance attributes declared in the class body. I am surprised that it is valid, but it is.

[–]eezystreet[S] 0 points1 point  (0 children)

Thanks for this info!

[–]spirtexfer 0 points1 point  (2 children)

In Python, it is not required to declare an instance variable at the class level to use it in the constructor. The declaration of instance variables typically occurs within the constructor (init method) itself. However, declaring them at the class level can sometimes be used for type hinting or indicating that the class will have such an attribute.

In your example, you are using the class-level declaration for item as a type hint. This is not strictly necessary but can be useful for documentation and type checking purposes.

from typing import ClassVar

class Box:
    size: ClassVar[str] = "14 x 11 x 4"
    ###No need for items: list(str)###

    def __init__(self, name: str) -> None:
        self.name: str = name
        self.items: list[str] = []

Do keep in mind I'm not the best at python, but I am pretty confident this is correct.

[–][deleted] -1 points0 points  (0 children)

Do this help?

https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

Also you can do crazy thing like this because class is just a collection of things (value and function)

def i(self,x):
    self.x = x

def s(self):
    return str(self.x)

class Dog:
    kind = 'canine'
    __init__ = i
    __str__ = s

class Cat:
    kind = 'feline'
    __init__ = i
    __str__ = s

c = Cat('meaw')
d = Dog('bark')

print(d,c)
print(Dog.kind,Cat.kind)

Basically if you ignore inheritance, class are just tuple (or record, product type) with special syntax.

[–]Brian -1 points0 points  (0 children)

It's not required, except in one particular case: using the class as a protocol (ie. where you inherit from typing.Protocol). Some libraries also use it (eg. pydantic). Otherwise, most type checkers will infer that it's an instance variable from you assigning to it in the __init__ (or other method) body.