我一直在开发一个客户端/服务器TCP应用程序,下面是它的大致轮廓:
config_type = namedtuple('config', ['host', 'port'])
class Server:
def __init__(self, config: config_type):
self.config = config
class Client:
def __init__(self, config: config_type):
self.config = config
现在我正在将这个体系结构扩展到其他计算机,所以我正在实现一个"从"服务器,它将在其他主机上运行,并将消息从主服务器分发到该主机上的客户端,所以我写了这样的东西:
class SlaveServer(Server, Client):
def __init__(self, master_server_config: config_type, slave_server_config: config_type):
Client.__init__(self, master_server_config)
Server.__init__(self, slave_server_config)
但是,由于我的Client
和Server
类定义了一个名为config的属性,所以最后一个init调用似乎获胜:
master = config_type('localhost', 4342)
slave_config = config_type('localhost', 6555)
slave = SlaveServer(master, slave_config)
print(f'master={master}')
print(f'slave_config={slave_config}')
print(f'slave.config={slave.config}')
输出:
master=config(host='localhost', port=4342)
slave_config=config(host='localhost', port=6555)
slave.config=config(host='localhost', port=6555)
这显然会打破局面。
在这种情况下应该如何使用多重继承?我是否应该确保不存在冲突的财产名称?在这种情况下,多重继承可能是个坏主意,我应该更改SlaveServer
,使其不使用继承,而只具有两个属性,server
和client
。
如果您拥有其中的所有代码,则可以使用Python的名称篡改功能:只需在名称中添加与两个__
冲突的属性和方法的前缀,并不要试图触及子类上的那些属性和方法(仅在定义它们的类上(。
双__
前缀触发了一个构建时功能,该功能以透明的方式更改属性的名称,以包括它们被定义为前缀的类,因此Server
和Client
都可以看到自己的__config
属性。如果你试图在ClientServer
上访问.__config
,你会得到一个AttributeError
,但你可以尝试使用损坏的名称来访问它们:
from collections import namedtuple
config_type = namedtuple('config', ['host', 'port'])
class Server:
def __init__(self, config: config_type):
self.__config = config
class Client:
def __init__(self, config: config_type):
self.__config = config
class SlaveServer(Server, Client):
def __init__(self, master_server_config: config_type, slave_server_config: config_type):
Client.__init__(self, master_server_config)
Server.__init__(self, slave_server_config)
在REPL上实例化后,我们可以验证两个属性都已保存:
In [65]: a = SlaveServer((0,0), (1,1))
In [67]: print(a._Server__config)
(1, 1)
In [68]: print(a._Client__config)
(0, 0)
免责声明:我不是在评判您的体系结构,只是向您指出一个内置的解决方案,该语言用于在多重继承中进行这种属性访问。即使没有看到更多的代码,这似乎是一个教科书上的明确例子,其中应该使用组合而不是继承,。