不可变类型允许在 Python 中进行子类化
我想要拥有不可变的类型,理想情况下,它们可以整理自己的散列和相等性,但可以轻松地进行子类化。我开始使用 namedtuple
:
class Command(namedtuple('Command', 'cmd_string')):
def valid_msg(msg):
return True
def make_command(msg):
if self.valid_msg(msg):
return '%s:%s' % (self.cmd_string, msg)
else:
raise ValueError(INVALID_MSG)
.. .但这并不适合子类化。直接子类化这意味着元组的名称保持不变(对于打印......没什么大不了的),但更重要的是您不能添加字段:
class LimitedLengthCommand(Command):
# I want to have self.length! Where does it go?
def valid_msg(msg):
return len(msg) <= self.length
简单地创建另一个命名元组(根据文档)意味着我不不继承任何方法!
做这样的事情最简单、最容易的方法是什么?我打算有 Command
的多个子类(例如十六进制文字、1-或0 等),但没什么复杂的。善用多重继承并不是必要的。
I want to have immutable types that can, ideally, sort out their own hashing and equality, but can be easily subclassed. I started off using namedtuple
:
class Command(namedtuple('Command', 'cmd_string')):
def valid_msg(msg):
return True
def make_command(msg):
if self.valid_msg(msg):
return '%s:%s' % (self.cmd_string, msg)
else:
raise ValueError(INVALID_MSG)
...but this does not lend itself to subclassing. Directly subclassing this means that the name of the tuple remains the same (for printing... not such a big deal), but more importantly you can't add fields:
class LimitedLengthCommand(Command):
# I want to have self.length! Where does it go?
def valid_msg(msg):
return len(msg) <= self.length
Simply creating another named tuple (as per the docs) means I don't inherit any methods!
What is the simplest and easiest way to do something like this? I intend to have multiple subclasses of Command
(eg. hex literals, 1-or-0, etc), but nothing complicated. Playing nice with multiple inheritance is not essential.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是一个元类可以做你想做的事(我认为)。它的工作原理是将要继承的方法存储在字典中,然后手动将它们插入到新类字典中。它还存储传递给
namedtuple
构造函数的属性字符串,并将其与子类中的属性字符串合并。然后,它将其传递给namedtuple
并返回一个从结果namedtuple
继承的类,并在其字典中包含所有适当的方法。由于元类派生自abc.ABCMeta
,因此您可以免费进行工作类型检查。下面是构造几个类的样子:这是元类:
这是一些微不足道的测试代码。
希望有帮助。如果您不想将每个方法附加到每个应该继承它的类,您还可以提供一个默认的 __getattr__ 来查找元类字典并从中找到适当的方法。这需要以某种方式将基类硬编码到方法中,可能使用闭包。
Here's a metaclass to do what you want (I think). It works by storing the methods to be inherited in a dictionary and manually inserting them into the new classes dictionary. It also stores the attribute string that gets passed to the
namedtuple
constructor and merges that with the attribute string from the subclass. It then passes that tonamedtuple
and returns a class that's inherited from the resultingnamedtuple
with all appropriate methods in its dictionary. Because the metaclass is derived fromabc.ABCMeta
, you get working type checking for free. Here's how constructing a couple of classes looks:Here's the metaclass:
And here's some paltry test code.
Hope that helps. If you would prefer not to attach every method to every class that is supposed to inherit it, you could also provide a default
__getattr__
that looks through the metaclasses dictionary and finds the appropriate method out of that. That would require somehow hardcoding the baseclass into method, probably using a closure.