python - 在 __init__ 中构造对象

标签 python constructor

我见过类似这样的代码:

class MyClass:
    def __init__(self, someargs):
        myObj = OtherClass()
        myDict = {}
        ...code to setup myObj, myDict...
        self.myObj = myObj
        self.myDict = myDict

当我看到这个时,我的第一个想法是:为什么不一开始就使用 self.myObj 和 self.myDict?构造本地对象,然后将它们分配给成员似乎效率低下。构造对象的代码确实可能会抛出异常,也许他们这样做是为了不留下半构造的对象?你这样做,还是直接构造成员?

最佳答案

构造对象然后将其附加到 self 会更快并且更具可读性。

class Test1(object):
    def __init__(self):
        d = {}
        d['a'] = 1
        d['b'] = 2
        d['c'] = 3
        self.d = d

class Test2(object):
    def __init__(self):
        self.d = {}
        self.d['a'] = 1
        self.d['b'] = 2
        self.d['c'] = 3

import dis
print "Test1.__init__"
dis.dis(Test1.__init__)

print "Test2.__init__"
dis.dis(Test2.__init__)

反汇编为:

Test1.__init__
  4           0 BUILD_MAP                0
              3 STORE_FAST               1 (d)

  5           6 LOAD_CONST               1 (1)
              9 LOAD_FAST                1 (d)
             12 LOAD_CONST               2 ('a')
             15 STORE_SUBSCR        

  6          16 LOAD_CONST               3 (2)
             19 LOAD_FAST                1 (d)
             22 LOAD_CONST               4 ('b')
             25 STORE_SUBSCR        

  7          26 LOAD_CONST               5 (3)
             29 LOAD_FAST                1 (d)
             32 LOAD_CONST               6 ('c')
             35 STORE_SUBSCR        

  8          36 LOAD_FAST                1 (d)
             39 LOAD_FAST                0 (self)
             42 STORE_ATTR               0 (d)
             45 LOAD_CONST               0 (None)
             48 RETURN_VALUE        
Test2.__init__
 12           0 BUILD_MAP                0
              3 LOAD_FAST                0 (self)
              6 STORE_ATTR               0 (d)

 13           9 LOAD_CONST               1 (1)
             12 LOAD_FAST                0 (self)
             15 LOAD_ATTR                0 (d)
             18 LOAD_CONST               2 ('a')
             21 STORE_SUBSCR        

 14          22 LOAD_CONST               3 (2)
             25 LOAD_FAST                0 (self)
             28 LOAD_ATTR                0 (d)
             31 LOAD_CONST               4 ('b')
             34 STORE_SUBSCR        

 15          35 LOAD_CONST               5 (3)
             38 LOAD_FAST                0 (self)
             41 LOAD_ATTR                0 (d)
             44 LOAD_CONST               6 ('c')
             47 STORE_SUBSCR        
             48 LOAD_CONST               0 (None)
             51 RETURN_VALUE

您可以看到 STORE_ATTR 只在最后以第一种方式调用一次。换一种方式,STORE_ATTR 仍然会在开始时被调用,但现在 LOAD_ATTR 会在每次访问字典时被调用。任务越多,成本越高。其他所有指令都是相同的。这仍然是一个小得离谱的成本。

可以利用此技巧使具有许多迭代的循环运行得更快。看到类似这样的事情并不少见

foo = self.foo
factorial = math.factorial
for x in really_big_iterator:
    foo(factorial(x))

另一个技巧是将全局函数作为默认参数传递给具有类似循环的函数,或者被调用一大堆以保存一些属性查找:它在本地范围内,这是第一个查看的范围。

def fast(iterators, sum=sum):
    for i in iterator:
        yield sum(i)

现在 sum 就在本地范围内。

关于python - 在 __init__ 中构造对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3605766/

相关文章:

javascript - javascript面向对象编程中super()构造函数和子类方法的执行顺序是什么?

python - Python中有什么函数可以聚合秒级毫秒数据吗?

python - 在 Python 的字典树中生成所有从叶到根的路径

python - 无法在 Linux 上安装 Python 包

Java - 子类调用 super 构造函数,它调用子类方法而不是它自己的方法

java - 默认构造函数链接

c++ - 在C++中使用具有可变数量参数的构造函数初始化对象

c++ - 无法使用大括号初始化智能感知错误调用基类构造函数

python - Pandas Dataframe 到键值对和 csv 格式

python - ehem 恒星时 Python