Python 3.10类型提示导致语法错误

4

我定义了两个类,一个是Bookshelf类,另一个是Book类,每个类都有自己的方法和类型提示。当我在VS Code中使用Python 3.10运行下面的代码时,会出现以下错误:

class Bookshelf: 
SyntaxError: Invalid syntax

这是指下面的BookShelf类的初始化。你们中有人能发现问题吗?

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
4个回答

3

这不是一个 SyntaxError,而是一个 NameError,因为当您在类型提示中使用它时,Book类尚未定义。

1. 第一种解决方案是将 Book 类的定义移到 BookShelf 的前面。

2. 第二种解决方案是使用字符串替代 book 本身:

def __init__(self, books: list["Book"]):

我认为在Python 3.11中,他们将允许将其直接使用。类型注释的评估将被推迟:

https://peps.python.org/pep-0563/

第三种解决方案: 如果你现在想要使用它,可以导入:

from __future__ import annotations

那么你的代码将会正常工作。


1
非常感谢!这个很有效,就像你在第二个选项中所说的那样,它克服了控制流/名称错误问题,尽管我可以简单地将我的Book类放在我的BookShelf类之前。 - Machiavellie

2

使用您问题中的代码,实际上会出现NameError,因为Book在定义类型提示之前被使用。将Book类移到Bookshelf上面即可解决。

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]))

输出:

<__main__.Book object at 0x7f61af441fd0>
Bookshelf with 2 books.

1
谢谢。我刚刚注意到在我的Book类中定义之前,我在我的BookShelf类中使用了Book。 - Machiavellie

1

尝试切换:

list[Book]

使用:

'list[Book]'

它仍然在同一行返回相同的错误。没有区别。 - Machiavellie
再检查一遍,我用那个更改后可以工作。 - Ofirfr

1
  1. 您在 books: list[Book] 中引用了 Book 类,但是该类定义在此之后。
  2. 由于 list 已经在 Python 中定义,因此无法将 list[Book] 用作参数类型。

尝试这样做:

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)}"

使用类型别名来定义所需参数的复杂类型。 请参阅使用从typing导入List/Tuple等与直接引用list/tuple等类型的区别


您不能将list[Book]作为参数,因为在Python中已经定义了list类型。不,使用list[]是完全可以的。自从Python 3.9(我想是这样),内置类型成为了泛型类型。 - S.B
@SorousHBakhtiary 但是原帖作者正在使用Python 3.10。 - user19117824
1
Python 3.10 不是比 Python 3.9 更新吗? - S.B
1
@SorousHBakhtiary,非常抱歉。我没有想到或者注意到为什么人们说Python 3.10而不是3.1。我以为这是Python 3.1,所以3.9更新。 - user19117824

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接