python内存消耗和与类相关的性能

时间:2015-01-28 18:38:37

标签: python

我很好奇与嵌套类和类属性相关的python的内存消耗/性能。

如果我有名为OtherClass, ClassA, ClassB, ClassC的类,其中OtherClass需要访问ClassA-C的有限属性。假设ClassA-C是具有许多属性,方法和属性的大类。这些方案中哪一个更有效。

选项1:

def OtherClass(object):
    def __init__(self, classa, classb, classc):
        self.classa
        self.classb
        self.classc

选项2:

def OtherClass(object):
    def __init__(self, classa_id, classa_atr1, classa_atr2,
                 classb_id, classb_atr1, classb_atr2, 
                 classc_id, classc_atr1, classc_atr2):
        self.classa_id
        self.classb_id
        self.classc_id
        self.classa_atr1
        self.classb_atr1
        self.classc_atr1
        self.classa_atr2
        self.classb_atr2
        self.classc_atr2

我认为选项1更好,因为3个属性将简单地链接到已经存在于内存中的类实例。其中选项2每个实例向内存中添加6个附加属性。这是正确的吗?

1 个答案:

答案 0 :(得分:3)

<强> TL; DR

我的回答是,您应该更喜欢选项1,因为它的简单性和更好的OOP设计,并避免过早优化。

休息

我认为这里的效率问题与维持第二种选择将来会有多困难相形见绌。如果一个对象需要使用另一个对象的属性(您的示例代码使用composition的形式),那么它应该将这些对象作为属性,而不是直接创建它所需的对象属性的额外引用。你的第一个选择是要走的路。第一个选项支持encapsulation,选项2非常明显违反它。 (当然,封装并不像Python那样强有力地强制实施,比如Java,但它仍然是一个很好的原则。)

您应该更喜欢第二个与效率相关的唯一原因是,如果您发现代码很慢,那么您的个人资料,您的分析会显示这些额外的查找确实是您的瓶颈。 那么你可以考虑牺牲诸如易于维护之类的东西来提高你所需要的速度。如果您在紧密循环中使用它们,额外的引用层(foo = self.classa.bar()foo = self.bar())可能会减慢速度,但它不太可能。

事实上,我会更进一步说你应该修改你的代码,以便OtherClass实际实例化它需要的对象,而不是让它们传入。使用选项1,如果我想使用{ {1}},我必须这样做:

OtherClass

要实例化classa = ClassA(class_a_init_args) classb = ClassC(class_b_init_args) classc = ClassC(class_c_init_args) otherclass_obj = OtherClass(classa_obj, classb_obj, classc_obj) ,需要设置太多。相反,请将OtherClass更改为:

OtherClass

现在实例化一个def OtherClass(object): def __init__(self, classa_init_args, classb_init_args, classc_init_args): self.classa = ClassA(class_a_init_args) self.classb = ClassC(class_b_init_args) self.classc = ClassC(class_c_init_args) 对象就是这样:

OtherClass

如果可能,可以使用另一个选项重新配置您的课程,这样您甚至不必实例化其他课程!看看Class Attributesclassmethod装饰器。这允许你做这样的事情:

otherclass_obj = OtherClass(classa_init_args, classb_init_args, classc_init_args)

此代码打印出:

  

2
  我甚至不需要实例化!

如果您的class foo(object): bar = 2 @classmethod def frobble(self): return "I didn't even have to be instantiated!" print(foo.bar) print(foo.frobble()) 使用OtherClassclassaclassb的属性或方法,不需要绑定到那些类,考虑直接通过类方法和属性使用它们而不是实例化对象。这实际上可以通过避免创建整个对象来节省大部分内存。