创建插槽对象实例性能

时间:2015-01-21 20:48:16

标签: python performance python-internals slots

我有一段代码使用值列表生成对象的实例。例如:

给出一个实现__slots__

的简单类
class A(object):
  __slots__ = ('a', 'b')

和值列表

>>> l = [1, 2]

我们通过

创建对象的新实例
>>> o = A.__new__(A)
>>> o
<__main__.A object at 0x0617AE70>

然后我们使用列表中的元素填充对象的属性

>>> for idx, element in enumerate(l):
...   setattr(o, o.__slots__[idx], element)
>>> o.a
1
>>> o.b
2

我在许多值列表的循环中执行此操作,并且在对我的程序进行概要分析后,这是它花费了很多时间的地方。我想知道是否有更好的方法可以更快地使用普通的python(没有pypy或cython)。

注意:

  • 我的程序实际上是从cls.__new__(cls)对象继承的方法调用__slots__。由于我不知道调用该方法的类,这是我找到创建该特定类类型的新实例的唯一方法。
  • 我是从包含值的文件创建这些对象的,但这是程序的要求。

2 个答案:

答案 0 :(得分:2)

所以,我可以在那里有一些想法,但它们或多或少都是投机性的。 一个想法是使用命名元组,而不是直接对象属性。

缺点是,除非你的类本身继承了namedtuples(并且需要一些黑客攻击),否则你将在属性的路径中有一个额外的组件。

但他们,有些事情:

from collections import namedtuple

class MyClass42(object):
    __slots__ = ["attrs"]
    scheme = namedtuple("attrs", "attr1 attr2 attr3 attr4")

    def __init__(self, attrs):
        self.attrs = self.scheme(*attrs)

# and to create the classes:
o = cls(attrs)

# the downsides are that you have to access attributes like

o.attrs.attr1
# and all such attributes are imutable :-/

请注意,您可以使用“cls”var作为可调用来构建 Python中的一个实例 - 与某些语言不同  您需要文字类名称。  无需调用cls.__new__并填充属性 “手动”。这将移动

(旁注,避免使用1个字母的变量名称可以提高可读性, 但是如果您愿意这样做,那么您应该避免使用名称'l',因为它看起来像'1' - 我上面使用了'attrs'

答案 1 :(得分:1)

另一种尝试是将值作为列表分配给对象,并在__getattribute__方法中懒惰地处理它们。虽然这几乎肯定可以节省您在对象创建中的时间,但它会将该时间转移到第一个属性使用(但是他们,我不知道您是否真的必须访问所有对象的所有属性 - 您可以微调您的策略) - 如果这是一个问题,你将对内存使用产生巨大影响。

class MyClass42(object):
    __slots__ = ["raw_attrs", "attr1", "attr2", ...]


    def __init__(self, attrs):
        self.raw_attrs = attrs

    def __getattr__(self, attr_name):
        attr = self.raw_attrs[self.__slots__.index(attr_name) - 1]
        setattr(self, attr_name, attr)
        return attr