以下は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)
未定義のClient
クラスにstringの名前を使用することで、 前方参照 を使用できます:
_class Server():
def register_client(self, client: 'Client')
pass
_
Python 3.7 以降、allランタイム解析を延期することもできます。モジュールの上部にある次の___future__
_インポート:
_from __future__ import annotations
_
その時点で、注釈は式の抽象構文ツリーの文字列表現として格納されます。 typing.get_type_hints()
を使用してそれらを解決できます(上記で使用した前方参照を解決できます)。
詳細は PEP 563-アノテーションの評価の延期 を参照してください。この動作は、Python 4.0ではデフォルトです。
Python 3.7+を使用している場合は、別の回答でfrom __future__ import annotations
言及されているように を使用してください。ただし、OSの制限のために3.7をまだ使用できない場合( Cygwin(2019年6月3日現在)では、 typing モジュールを使用して、これらのタイプの前方/循環依存の問題を満たすことができます。
不自然な例はご容赦ください。これは、この方法論の有用性を示しているはずです。
from typing import TypeVar, Generic
T_Server = TypeVar('T_Server')
T_Client = TypeVar('T_Client')
class Server(Generic[T_Server]):
clients: list = None
def __init__(self):
self.clients=[]
def register_client(self, client: T_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: T_Server) -> T_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: T_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()