输入提示:解决循环依赖

Tam*_*iel 41 python type-hinting python-3.5

以下产生NameError: name 'Client' is not defined.我该如何解决?

class Server():
    def register_client(self, client: Client)
        pass


class Client():
    def __init__(self, server: Server):
        server.register_client(self)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 62

您可以通过使用尚未定义的类的字符串名称来使用转发引用:Client

class Server():
    def register_client(self, client: 'Client')
        pass
Run Code Online (Sandbox Code Playgroud)

从Python 3.7开始,您还可以通过在模块顶部添加以下导入来推迟所有运行时解析注释__future__:

from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)

此时,注释被存储为表达式的抽象语法树的字符串表示; 您可以使用它typing.get_type_hints()来解决这些问题(并解决上面使用的前向引用).

有关详细信息,请参阅PEP 563 - 延迟评注注释 ; 此行为将是Python 4.0中的默认行为.

  • 请注意,从Python 3.7开始,不再需要使用字符串前向引用 - 而是将"from __future__ import annotations"导入添加到[延迟评估注释](https://www.python.org/dev/PEPS/PEP-0563 /).一旦[Python 4.0](https://www.python.org/dev/peps/pep-0563/#deprecation-policy)滚动,这种行为显然会默认启用. (4认同)

Tim*_*inn 5

如果您使用的是 Python 3.7+,请使用另一个答案中from __future__ import annotations 提到的方法。但是,如果由于操作系统限制(如 Cygwin 截至 2019-06-03)而无法使用 3.7,则可以使用前向引用模块来满足这些类型的前向/循环依赖问题。

请原谅这个人为的例子,但这应该说明这种方法的有用性。

class Server():
    clients: list = None

    def __init__(self):
        self.clients=[]

    def register_client(self, client: 'Client') -> None:
        self.clients.append(client)
        print('Client `%s` registered with server' % client.name)

    def print_clients(self) -> None:
        for i, client in enumerate(self.clients):
            print('client %i: %s' % (i, client.name))

    @staticmethod
    def build_clone(server: 'Server') -> 'Server':
        svr_new: Server = Server()
        for client in server.clients:
            svr_new.register_client(client)
        return svr_new

class Client():
    name: str = None
    def __init__(self, name: str, server: 'Server'):
        self.name = name
        server.register_client(self)


svr = Server()
cli = Client('foo', svr)
svr.print_clients()

svr_clone = Server.build_clone(svr)
svr_clone.print_clients()
Run Code Online (Sandbox Code Playgroud)