几周前,我花了一些时间调查collections.namedtuple
module。该模块使用工厂函数将动态数据(新namedtuple
类的名称和类属性名称)填充到一个非常大的字符串中。然后,以字符串(表示代码)作为参数执行exec
,并返回新类。
有没有人知道为什么要这样做,因为有一种特定的工具可以用来处理这种事情,即元类?我自己并没有尝试过这样做,但是似乎使用namedtuple
元类就可以轻松地完成namedtuple
模块中发生的所有事情,如下所示:
class namedtuple(type):
等等。
发布于 2016-06-24 18:04:15
这是另一种方法。
""" Subclass of tuple with named fields """
from operator import itemgetter
from inspect import signature
class MetaTuple(type):
""" metaclass for NamedTuple """
def __new__(mcs, name, bases, namespace):
cls = type.__new__(mcs, name, bases, namespace)
names = signature(cls._signature).parameters.keys()
for i, key in enumerate(names):
setattr(cls, key, property(itemgetter(i)))
return cls
class NamedTuple(tuple, metaclass=MetaTuple):
""" Subclass of tuple with named fields """
@staticmethod
def _signature():
" Override in subclass "
def __new__(cls, *args):
new = super().__new__(cls, *args)
if len(new) == len(signature(cls._signature).parameters):
return new
return new._signature(*new)
if __name__ == '__main__':
class Point(NamedTuple):
" Simple test "
@staticmethod
def _signature(x, y, z): # pylint: disable=arguments-differ
" Three coordinates "
print(Point((1, 2, 4)))
如果这种方法有任何优点的话,那就是它的简单性。如果没有NamedTuple.__new__
,它会更简单,因为它只用于强制执行元素计数。否则,它允许在命名元素之外添加匿名元素,省略元素的主要效果是在按名称访问省略的元素时对省略的元素进行IndexError
(只需做一些可以转换为AttributeError
的工作)。错误的元素计数的错误消息有点奇怪,但它让人明白了这一点。我不希望这在Python2上起作用。
还有进一步复杂化的空间,比如__repr__
方法。我不知道与其他实现相比性能如何(缓存签名长度可能会有所帮助),但与原生namedtuple
实现相比,我更喜欢调用约定。
https://stackoverflow.com/questions/28184531
复制相似问题