观点-Python:多重继承还是组合
我目前正在用Python重新设计一些与加密货币项目相关的对象。在我的设计中,我喜欢在任何有意义的地方使用组合和依赖注入观点-Python:多重继承还是组合,python,inheritance,Python,Inheritance,我目前正在用Python重新设计一些与加密货币项目相关的对象。在我的设计中,我喜欢在任何有意义的地方使用组合和依赖注入 transaction对象是一种数据结构,其中的字段被拆分并与字符串连接在一起(序列化/反序列化)。在加密世界中,这种数据结构有多种变体,其中字段可以以不同的顺序添加、删除或序列化 我有基本的交易类: class CTransaction(object): def __init__(self): #Basics self.nVersion
transaction
对象是一种数据结构,其中的字段被拆分并与字符串连接在一起(序列化/反序列化)。在加密世界中,这种数据结构有多种变体,其中字段可以以不同的顺序添加、删除或序列化
我有基本的交易
类:
class CTransaction(object):
def __init__(self):
#Basics
self.nVersion = 1
self.vin = []
self.vout = []
self.nLockTime = 0
self.sha256 = None
def deserialize(self, f):
self.nVersion = struct.unpack("<i", f.read(4))[0]
self.vin = deser_vector(f, CTxIn)
self.vout = deser_vector(f, CTxOut)
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
def serialize(self):
r = ""
r += struct.pack("<i", self.nVersion)
r += ser_vector(self.vin)
r += ser_vector(self.vout)
r += struct.pack("<I", self.nLockTime)
return r
在另一个变体中,您可以进行POS类型货币的交易
class CPosTransaction(CTransaction):
def __init__(self, ntime):
super(CPosTransaction, self).__init__()
# POS blocks have an 'nTime' field
self.nTime = ntime
def deserialize(self, f):
self.nVersion = struct.unpack("<i", f.read(4))[0]
self.nTime = struct.unpack("<i", f.read(4))[0]
self.vin = deser_vector(f, CTxIn)
self.vout = deser_vector(f, CTxOut)
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
def serialize(self):
r = ""
r += struct.pack("<i", self.nVersion)
r += struct.pack("<i", self.nTime)
r += ser_vector(self.vin)
r += ser_vector(self.vout)
r += struct.pack("<I", self.nLockTime)
return r
我应该改为使用组合并将序列化/反序列化方法分离为更多对象吗?还是我想得太多/太复杂了?首先:
super
是你的朋友,尤其是当你做菱形继承的时候
第二:考虑不要那样做。Python支持它,但是只要可能,坚持使用mixin通常是个好主意。
因此,在您的情况下,它将是:
class CTransaction(object):
def serialize(self)
"do stuff"
class PosMixin(object):
def serialize(self, *args, **kwargs):
super(PosMixin, self).serialize(*args, **kwargs)
# do my stuff
class AnotherMixin(object):
def serialize(self, *args, **kwargs):
super(AnotherMixin, self).serialize(*args, **kwargs)
# do some more stuff
class TransactionPos(CTransaction, PosMixin): pass
class TransactionAnotherPos(CTransaction, PosMixin, AnotherMixin): pass
另一种方法是手动注册回调,然后调用它们。那是你的依赖注入。但是,除非您动态生成这些类的大量变体,否则没有什么意义。如果序列化格式是自由的,并且不严格依赖于数据结构(在您的示例中,
TxMessage
附加在末尾,而nTime
插入中间)您可以使用DSL来描述格式,然后在基类中编写通用代码,该基类将负责使用该方法进行序列化/反序列化:
class CTransaction(object):
format = [('nVersion', 'i'),
('vin', 'v', CTxIn),
('vout', 'v', CTxOut),
('nLockTime', 'I')]
def __init__(self):
... your usual code ...
def deserialize(self, f):
for field in self.__class__.format:
setattr(self, field[0],
deserializers[field[1]](f, *field[1:]))
self.sha256 = None
def serialize(self):
res = ""
for field in self.__class__.format:
res += serializers[field[1]](getattr(self, field[0]),
*field[1:])
return res
使用这种方法,您永远不会重新实现序列化
/反序列化
,例如CPosTransaction
类被实现为
class CPosTransaction(CTransaction):
format = [('nVersion', 'i'),
('nTime', 'I'),
('vin', 'v', CTxIn),
('vout', 'v', CTxOut),
('nLockTime', 'I')]
def __init__(self, ntime):
...
class CPosTransactionMessage(CTransaction):
format = [('nVersion', 'i'),
('nTime', 'I'),
('vin', 'v', CTxIn),
('vout', 'v', CTxOut),
('nLockTime', 'I'),
('strTxComment', 's')]
def __init__(self, Tx_Message, ntime):
...
而CPosTransactionMessage
实现为
class CPosTransaction(CTransaction):
format = [('nVersion', 'i'),
('nTime', 'I'),
('vin', 'v', CTxIn),
('vout', 'v', CTxOut),
('nLockTime', 'I')]
def __init__(self, ntime):
...
class CPosTransactionMessage(CTransaction):
format = [('nVersion', 'i'),
('nTime', 'I'),
('vin', 'v', CTxIn),
('vout', 'v', CTxOut),
('nLockTime', 'I'),
('strTxComment', 's')]
def __init__(self, Tx_Message, ntime):
...
如果干燥非常重要,您甚至可以在导入时构建配方
class CPosTransaction(CTransaction):
# Insert nTime after first field
format = (CTransaction.format[:1] +
[('nTime', 'I')] +
CTransaction.format[1:])
def __init__(self, ntime):
...
class CPosTransactionMessage(CPosTransaction):
# Append strTxComment at the end
format = (CPosTransaction.format +
[('strTxComment', 's')])
def __init__(self, Tx_Message, ntime):
...
但这当然会使阅读代码时更难理解代码
class CPosTransaction(CTransaction):
# Insert nTime after first field
format = (CTransaction.format[:1] +
[('nTime', 'I')] +
CTransaction.format[1:])
def __init__(self, ntime):
...
class CPosTransactionMessage(CPosTransaction):
# Append strTxComment at the end
format = (CPosTransaction.format +
[('strTxComment', 's')])
def __init__(self, Tx_Message, ntime):
...