这个Python代码可以更有效地编写吗?

时间:2010-08-02 21:00:02

标签: python

所以我在python中有这个代码,它将一些值写入一个Dictionary,其中每个键都是一个学生ID号,每个值都是一个Class(类型为student),其中每个Class都有一些与之关联的变量。 “

代码

        try:
                if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[1])):
                        valuetowrite=str(row[i])
                        if students[str(variablekey)].var2 != []:
                                students[str(variablekey)].var2.append(valuetowrite)
                        else:
                                students[str(variablekey)].var2=([valuetowrite])
        except:
                two=1#This is just a dummy assignment because I #can't leave it empty... I don't need my program to do anything if the "try" doesn't work. I just want to prevent a crash.

        #Assign var3
        try:
                if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[2])):
                        valuetowrite=str(row[i])
                        if students[str(variablekey)].var3 != []:
                                students[str(variablekey)].var3.append(valuetowrite)
                        else:
                                students[str(variablekey)].var3=([valuetowrite])
        except:
                two=1

        #Assign var4
        try:
                if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[3])):
                        valuetowrite=str(row[i])
                        if students[str(variablekey)].var4 != []:
                                students[str(variablekey)].var4.append(valuetowrite)
                        else:
                                students[str(variablekey)].var4=([valuetowrite])
        except:
                two=1

对于学生拥有的每个变量(var5,var6,...... varX),相同的代码会重复多次。但是,当我执行执行这一系列变量赋值的函数时,程序中的RAM峰值出现了。

我希望找到一种方法来提高速度或提高内存效率,因为运行我程序的这一部分需要大约半个内存。 :(

感谢您的帮助!

编辑:

好的,让我简化一下我的问题: 在我的例子中,我有一个大约6000个实例化类的字典,其中每个类有1000个属性变量,所有类型字符串或字符串列表。我真的不关心我的代码行数或运行速度(现在,我的代码大约是20,000行,大约是1 MB .py文件!)。我关心的是它占用的内存量,因为这是限制我的CPU的罪魁祸首。最终的问题是:我构建这个庞大的字典的代码行数在RAM使用方面是否如此重要?

我的原始代码运行正常,但RAM使用率很高。我不确定这与我收集的数据量是否“正常”。以简洁的方式编写代码(如下面帮助过我的人所示)实际上会使我吃掉的内存量明显不同吗?当然有X方法来构建字典,但在这种情况下它是否会影响RAM的使用?

4 个答案:

答案 0 :(得分:3)

编辑:下面建议的代码重构不会大幅减少内存消耗。每个有1000个属性的6000个类可能会消耗半个内存。

最好将数据存储在数据库中,并仅在需要时通过SQL查询提取数据。或者您可以使用shelvemarshal将部分或全部数据转储到磁盘,只有在需要时才能将其读回。第三种选择是使用numpy字符串数组。 numpy数组将更紧凑地保持字符串。 (Python字符串是具有许多方法的对象,这些方法使得它们在内存方面更加庞大。一个字符串的数组丢失了所有这些方法但需要相对较少的内存开销。)第四个选项可能是使用PyTables

最后(但并非最不重要),可能有方法重新设计您的算法,以减少内存密集。我们必须更多地了解您的计划以及它试图解决的问题,以提供更具体的建议。

原创建议

for v in ('var2','var3','var4'):
    try:
        if row_num_id.get(str(i))==varschosen[1]:
            valuetowrite=str(row[i])
            value=getattr(students[str(variablekey)],v)
            if value != []:
                value.append(valuetowrite)
            else:
                value=[valuetowrite]
    except PUT_AN_EXPLICT_EXCEPTION_HERE:
        pass

PUT_AN_EXPLICT_EXCEPTION_HERE应替换为AttributeErrorTypeErrorValueError等内容,或者其他内容。 很难猜测放在这里的内容因为我不知道变量可能具有什么样的值。

如果您运行没有try...exception块的代码,并且程序崩溃,请记下您收到的回溯错误消息。最后一行会说

TypeError: ...

在这种情况下,请将PUT_AN_EXPLICT_EXCEPTION_HERE替换为TypeError

如果您的代码可能会以多种方式失败,例如TypeErrorValueError,那么您可以将PUT_AN_EXPLICT_EXCEPTION_HERE替换为 (TypeError,ValueError)可以捕获这两种错误。

注意:应该提及一些技术性的警告 row_num_id.get(str(i))==varschosen[1]。如果row_num_id.get(str(i))不在None中,则str(i)表达式会返回row_num_id。 但是如果varschosen[1] Nonestr(i)不在row_num_id,该怎么办?然后条件为True,当较长的原始条件返回False时。

如果可能,那么解决方案是使用像row_num_id.get(str(i),object())==varschosen[1]这样的sentinal默认值。当row_num_id.get(str(i),object())不在object()时,str(i)会立即返回row_num_id。由于object()object的新实例,因此无法与varschosen[1]相等。

答案 1 :(得分:0)

你拼写错了

two=1#This is just a dummy assignment because I 
#can't leave it empty... I don't need my program to do anything if the "try" doesn't work. I just want to prevent a crash.

拼写

pass

您应该阅读有关Python的教程。

此外,

except:

是一个糟糕的政策。当程序崩溃时,你的程序将无法崩溃。

var2var3等名称是邪恶的。他们故意误导。

不要一遍又一遍地重复str(variablekey)

  

我希望找到一种方法来提高速度或提高内存效率,因为运行我程序的这一部分需要大约半个内存。 :(

这个请求是无法回答的,因为我们不知道它应该做什么。像var1var2这样的故意模糊名称使其无法理解。

答案 2 :(得分:0)

  

“6000个实例化类,其中每个类有1000个属性变量”

因此。 600万件物品?这是很多记忆。真的很多记忆。

  

我关注的是它占用的内存量,因为这是限制我的CPU的罪魁祸首

真的?有证据吗?

  

但RAM使用率很高

与什么相比?这个主张的基础是什么?

答案 3 :(得分:0)

Python dicts使用了大量的内存。尝试:

import sys
for i in range( 30 ):
   d = dict( ( j, j ) for j in range( i ) )
   print "dict with", i, "elements is", sys.getsizeof( d ), "bytes"

以说明它们有多贵。请注意,这只是dict本身的大小:它不包括存储在dict中的键或值的大小。

默认情况下,Python类的实例将其属性存储在dict中。因此,您的6000个实例中的每个实例都在为该字典使用大量内存。

如果您的实例都具有相同的属性集,则可以节省大量内存的一种方法是使用__slots__(请参阅http://docs.python.org/reference/datamodel.html#slots)。例如:

class Foo( object ):
   __slots__ = ( 'a', 'b', 'c' )

现在,类Foo的实例为三个属性abc分配了空间,但没有实例dict存储任何其他属性。每个属性只使用4个字节(在32位系统上),而使用dict的每个属性可能只有15-20个字节。

另一种可能浪费内存的方法,假设你有很多字符串,那就是你要存储同一个字符串的多个相同副本。如果这是一个问题,使用intern函数(请参阅http://docs.python.org/library/functions.html#intern)可能会有所帮助。

相关问题