Namedtuple' _source'使用' exec'引用后,方法被停用。

时间:2017-12-14 13:40:44

标签: python python-3.x

_sourcenamedtupleIn [90]: Book = namedtuple('Book', 'name, author') In [91]: Book._source Out[91]: "from builtins import property as _property, tuple as _tuple\nfrom operator import itemgetter as _itemgetter\nfrom collections import OrderedDict\n\nclass Book(tuple):\n 'Book(name, author)'\n\n __slots__ = ()\n\n _fields = ('name', 'author')\n\n def __new__(_cls, name, author):\n 'Create new instance of Book(name, author)'\n return _tuple.__new__(_cls, (name, author))\n\n @classmethod\n def _make(cls, iterable, new=tuple.__new__, len=len):\n 'Make a new Book object from a sequence or iterable'\n result = new(cls, iterable)\n if len(result) != 2:\n raise TypeError('Expected 2 arguments, got %d' % len(result))\n return result\n\n def _replace(_self, **kwds):\n 'Return a new Book object replacing specified fields with new values'\n result = _self._make(map(kwds.pop, ('name', 'author'), _self))\n if kwds:\n raise ValueError('Got unexpected field names: %r' % list(kwds))\n return result\n\n def __repr__(self):\n 'Return a nicely formatted representation string'\n return self.__class__.__name__ + '(name=%r, author=%r)' % self\n\n def _asdict(self):\n 'Return a new OrderedDict which maps field names to their values.'\n return OrderedDict(zip(self._fields, self))\n\n def __getnewargs__(self):\n 'Return self as a plain tuple. Used by copy and pickle.'\n return tuple(self)\n\n name = _property(_itemgetter(0), doc='Alias for field number 0')\n\n author = _property(_itemgetter(1), doc='Alias for field number 1')\n\n" 中指定的一种方法。

其用法示例:

exec

但是,如果我们使用_source引用它,则后续调用In [87]: Book = namedtuple('Book', 'name, author') In [88]: exec(Book._source) In [89]: Book._source AttributeError: type object 'Book' has no attribute '_source' 会引发错误。

pandas

背后的机制是什么?

1 个答案:

答案 0 :(得分:1)

collections.namedtuple通过填写模板字符串并将其传递给exec来创建一个类对象。在创建之后,类对象仅获取_source属性,即模板字符串未定义 - 否则模板将是递归。这意味着,如果您自己exec模板,那么您将获得相同的课程,但没有_source属性。

然后,exec(Book._source)在当前命名空间中运行Book._source并将原始Book类替换为从该字符串生成的新类(因为名称匹配),但没有_source属性。提供你自己的全局字典,看看差异:

In [1]: from collections import namedtuple

In [2]: Book = namedtuple('Book', 'name, author')

In [3]: ns = {}; exec(Book._source, ns)

In [4]: hasattr(Book, '_source')
Out[4]: True

In [5]: hasattr(ns['Book'], '_source')
Out[5]: False

作为旁注,在Python 3.7中完全删除了该属性。