'Python 3.10 Type Hinting causes Syntax Error
I have defined two classes. A Bookshelf class and a Book class and have defined each with its own methods and type hints. When I run the below code in VS Code using python 3.10 it comes up with the following error:
class Bookshelf:
SyntaxError: Invalid syntax
Which is referring to the init of the BookShelf class below. Can any of you spot the issue?
class Bookshelf:
def __init__(self, books: list[Book]):
self.books = books
def __str__(self) -> str:
return f"Bookshelf with {len(self.books)}"
class Book:
def __init__(self, name: str, page_count: int):
self.name=name
self.page_count = page_count
Solution 1:[1]
It is not a SyntaxError, It is a NameError because Book class is not defined yet when you are using it in your type hints.
1. First solution is moving the definition of Book class before the BookShelf.
2. Second solution is use the string instead of the book itself:
def __init__(self, books: list["Book"]):
I think in Python 3.11, They will allow to use it as it is. Evaluation of type annotations are gonna be postponed:
https://peps.python.org/pep-0563/
3. third solution: If you want to have this now, you can import:
from __future__ import annotations
then your code is going to work.
Solution 2:[2]
Using the code in your question, I'm actually getting a NameError because Book is used in the type hint before it's defined. Moving the Book class above Bookshelf took care of it.
class Book:
def __init__(self, name: str, page_count: int):
self.name = name
self.page_count = page_count
class Bookshelf:
def __init__(self, books: list[Book]):
self.books = books
def __str__(self) -> str:
return f"Bookshelf with {len(self.books)} books."
atlas = Book("Atlas", 100)
dictionary = Book("Dictionary", 1000)
print(atlas)
print(Bookshelf([atlas, dictionary]))
Output:
<__main__.Book object at 0x7f61af441fd0>
Bookshelf with 2 books.
Solution 3:[3]
Try switching:
list[Book]
with:
'list[Book]'
Solution 4:[4]
- You have defined the
Bookclass after you referred to it inbooks: list[Book] - You can't use
list[Book]as a parameter as the typelistis already defined in Python
Try this:
from typing import List #Using typing's List instead of list
class Book:
def __init__(self, name: str, page_count: int):
self.name=name
self.page_count = page_count
#Defined book class before its use
list_of_books = List[Book] #Using a type alias to solve the problem so you can use it as a parameter
class Bookshelf:
def __init__(self, books: list_of_books):
self.books = books
def __str__(self) -> str:
return f"Bookshelf with {len(self.books)}"
Use type aliases to define the complex type of parameter you want. See Using List/Tuple/etc. from typing vs directly referring type as list/tuple/etc
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Tim |
| Solution 3 | Ofirfr |
| Solution 4 |
