【发布时间】:2013-10-08 10:53:27
【问题描述】:
我有一个对象,它封装了具有某些特征的网络配置文件。例如,我的个人资料有一个 Connection 并且取决于它,它可能有也可能没有 IP 选项(static 或 dhcp)。
所以,我的第一次尝试是使用从 dict 扩展而来的普通类并添加一些辅助函数:
class Profile(dict):
IP_CONNECTIONS = ('ethernet', 'wireless', 'pppoe')
def is_ethernet(self): return self['Connection'] == 'ethernet'
def is_wireless(self): return self['Connection'] == 'wireless'
def is_wireless_adhoc(self): return self.is_wireless() and 'AdHoc' in self
def has_ip(self)
return self['Connection'] in self.IP_CONNECTIONS
def has_ip_static(self)
if not self.has_ip():
return False
if self.is_ipv4():
return self['IP'] == 'static'
if self.is_ipv6():
return self['IP6'] == 'static'
return False
def has_ip_dhcp(self):
if not self.has_ip():
return False
if self.is_ipv4():
return self['IP'] == 'dhcp'
if self.is_ipv6():
return self['IP6'] == 'dhcp' or self['IP6'] == 'dhcp-noaddr'
return False
def is_ipv4(self): return self.has_ip() and 'IP' in self
def is_ipv6(self): return self.has_ip() and 'IP6' in self
def get_client(self):
if self.has_ip_dhcp() and 'DHCPClient' in self:
return self['DHCPClient']
return None
这行得通,但我有一个庞大的类,其中包含很多 is_* 和 has_* 特征函数。它们中的大多数只会用于非常特定的配置文件,并且大部分时间会返回False。
然后我突然想到我可以使用继承来描述特征。
在尝试并未能实现元类后,因为在调用 __new__ 方法时数据尚不可用。我想出了这样的事情:
def load_profile(filename):
data = _read_profile(filename)
bases = _classify_profile(data)
baseclass = type('Profile', bases, {})
return baseclass(data)
class IP:
CONNECTIONS = ('ethernet', 'wireless')
class IPv4(IP):
def is_static(self):
return self['IP'] == 'static'
class IPv6(IP):
def is_static(self):
return self['IP6'] == 'static'
class DHCP:
def get_client(self):
return self['DHCPClient'] if 'DHCPClient' in self else None
class Wireless:
def is_adhoc(self):
return 'AdHoc' in self
def _classify_profile(data):
classes = [dict]
if data['Connection'] == 'wireless':
classes.append(Wireless)
if data['Connection'] in IP.CONNECTIONS:
if 'IP' in data:
classes.append(IPv4)
if data['IP'] == 'dhcp':
classes.append(DHCP)
if 'IP6' in data:
classes.append(IPv6)
if data['IP6'] == 'dhcp' or data['IP6'] == 'dhcp-noaddr':
classes.append(DHCP)
return tuple(classes)
以前我在做profile.has_ip(),现在我只是用isinstance(profile, IP) 测试它。在我看来,通过良好的责任分离,这一点更加清晰。
问题:这是实现动态继承的好方法吗?这样做的pythonic方式是什么?
提前致谢!
【问题讨论】:
-
我非常喜欢这个关于设计的视频:vimeo.com/26330100
-
@User 非常有趣。谢谢!
标签: python oop multiple-inheritance