我很好奇为什么namedtuple比
python中的常规类慢.考虑以下:
In [1]: from collections import namedtuple
In [2]: Stock = namedtuple('Stock', 'name price shares')
In [3]: s = Stock('AAPL', 750.34, 90)
In [4]: %%timeit
...: value = s.price * s.shares
...:
175 ns ± 1.17 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [5]: class Stock2:
...: __slots__ = ('name', 'price', 'shares')
...: def __init__(self, name, price, shares):
...: self.name = name
...: self.price = price
...: self.shares = shares
In [6]: s2 = Stock2('AAPL', 750.34, 90)
In [8]: %%timeit
...: value = s2.price * s2.shares
...:
106 ns ± 0.832 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [9]: class Stock3:
...: def __init__(self, name, price, shares):
...: self.name = name
...: self.price = price
...: self.shares = shares
In [10]: s3 = Stock3('AAPL', 750.34, 90)
In [11]: %%timeit
...: value = s3.price * s3.shares
...:
118 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [12]: t = ('AAPL', 750.34, 90)
In [13]: %%timeit
...: values = t[1] * t[2]
...:
93.8 ns ± 1.13 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [14]: d = dict(name='AAPL', price=750.34, shares=90)
In [15]: %%timeit
...: value = d['price'] * d['shares']
...:
92.5 ns ± 0.37 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
我期望namedtuple来到没有插槽的课程之前.这是在python3.6上.同样令人惊讶的是,字典的性能可与元组相媲美.
最佳答案 对于python类的一个实例,通过点表示法设置和获取属性主要是通过__dict __ [attribute_name](__ dict__本身是一个属性,它是一个字典)的实例,取决于__dict的值__ [attribute_name]调用它v ,有不同的行为.
情况一:v不是descriptor,所以点符号只返回v.
情况二:v是一个描述符,结果将从描述符的__get__方法中获取.
对于描述中的简单类实例:很容易就是第一种情况
对于namedtuple情况:看看namedtuple source code,函数namedtuple正在使用这个template创建一个类,其中在dict中命名字段存储作为属性.
其中property是描述符,itemgetter实例将在描述符的__get__方法中使用!
这是python代码中的属性类,位于Cpython中c源代码的注释中:
class property(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
self.__get = fget
self.__set = fset
self.__del = fdel
self.__doc__ = doc
def __get__(self, inst, type=None):
if inst is None:
return self
if self.__get is None:
raise AttributeError, "unreadable attribute"
return self.__get(inst)
def __set__(self, inst, value):
if self.__set is None:
raise AttributeError, "can't set attribute"
return self.__set(inst, value)
def __delete__(self, inst):
if self.__del is None:
raise AttributeError, "can't delete attribute"
return self.__del(inst)
总结一下,我们应该理解为什么namedtupple访问速度较慢,有一些额外的步骤可以从nametuple创建的类的实例中获取值而不是简单的类.
如果你想深入挖掘,看看如何存储和获取值,你可以通过上面的链接阅读python3.6的源代码.
提示:
namedtuple创建类是一个子类,将字段值存储为元组,并通过属性存储相关索引及其名称.