【问题标题】:Python: performance issue implemenating nested classes with staticmethodPython:使用静态方法实现嵌套类的性能问题
【发布时间】:2013-10-04 14:37:59
【问题描述】:

检查以下我们实现nested classes 和混合staticmethods 的示例工作代码。

import time

class A:
    def __init__(self):
        time.sleep(0.1)

    def a1(self):
        print 'a1'

    @staticmethod
    def a2(): 
        print 'a2'

    class B:
        @staticmethod
        def b2():
            A.a2()         #fine.  
            A().a1()       #very bad solution, computation cost is high !!!

        @staticmethod
        def x():
            t = time.clock()
            for i in xrange(100):
                A.B.b2()
            print 'elapsed: %0.1fs'%(time.clock()-t)

用作:

A.B.x()

上述方法有效,但正如您可能注意到的那样,对于 A().a1() 行,我们尝试从容器类 A 访问非静态方法 a1,计算成本太高。我们通过在A 初始化中使用sleep 来强调这一点。所以你明白了,它可以是任何耗时的初始化,这在我们的工作中是必要的,例如。所以我们不相信在上述行中实例化类A 是一个不错的选择。如何不在上面实例化A,但要像上面一样完成工作。尽管相关问题包括thisthat,但上述问题已在任何地方得到解答。

编辑
我们对why use it 等建议不感兴趣。正如上面明确指出的,我们感兴趣的问题是如何改进这一行

A().a1()

就是这样。

根据Martijn Pieters给出的建议,通过以下方式解决。由于显示了解决方法,我们接受了答案。

class B:
    @staticmethod
    def b2(Ai):
        A.a2()         #fine.
        if Ai is None: Ai = A()
        Ai.a1()        #now is fine.

    @staticmethod
    def x():
        t = time.clock()
        Ai = A()
        for i in xrange(100):
            A.B.b2(Ai=Ai)
        print 'elapsed: %0.1fs'%(time.clock()-t)

谢谢。

【问题讨论】:

  • 对不起,什么?您想在不实例化A 的情况下执行需要A 实例的代码?
  • 我完全不清楚你在问什么,但是嵌套静态方法的行为与非嵌套静态方法没有任何不同。没有额外的性能损失(除了属性查找,这并不完全昂贵)会使情况变得异常。
  • @MartijnPieters 请注意,在上面的代码中,我们正在寻找一种解决方案不实例化A 百万次,只是为了访问方法a1。应该以某种方式仅对一个实例执行此操作。
  • 如果A 需要很长时间来初始化,那么只做一次,缓存实例。你可以通过一个非常简单的__new__ 方法来做到这一点。
  • 那只是缓存问题;与静态方法或嵌套对象无关

标签: python class nested static-methods


【解决方案1】:

您的问题与静态方法或嵌套类无关。全局函数存在完全相同的问题

class A:
    def __init__(self):
        time.sleep(0.1)

    def a1(self):
        print 'a1'

def a2(): 
    print 'a2'

def b2():
    a2()  
    A().a1()

def x():
    t = time.clock()
    for i in xrange(100):
        b2()
    print 'elapsed: %0.1fs'%(time.clock()-t)

调用x() 仍会导致在b2() 之外的循环中创建昂贵的A() 实例。

您需要设计一个缓存策略来创建A()。有太多的方法可以在这里总结,当然,关于何时重用 A() 的实例比创建一个新实例是可以接受的信息很少。

如果您想重用A() 的实例只需 用于x() 中的循环,则将其作为可选参数传递:

def x():
    t = time.clock()
    instance = A()
    for i in xrange(100):
        b2(instance)
    print 'elapsed: %0.1fs'%(time.clock()-t)

def b2(instance=None):
    a2()
    if instance is None:
        instance = A()
    instance.a1()

现在实例在函数x() 的持续时间内被缓存。

【讨论】:

  • 我们担心这不是我们想要的。我们对更改代码结构不感兴趣。你看,缺少的一点是没有容器结构。 A.B.x()在哪里?
  • 而且您已经知道问题中的示例是为了证明我们的目的,而不是可能包含数千种方法和结构的原始代码。看重点。不允许改变结构。我们很想填补我们对上面提到的A().a1() 行的缺乏了解。
  • 简化情况来说明这与收容无关。只需将其重新添加即可。嵌套类的结构与您的问题无关
  • 你需要弄清楚A()的实例何时可以被重用,然后去做;重用这些实例。 根本您如何使用实例并不重要,同样的问题适用于您的嵌套结构,也适用于我的简化扁平结构。
  • 现在我们您的 cmets / 回答我们可以解决问题。我们的解决方案是在问题的末尾添加的。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
相关资源
最近更新 更多