簡體   English   中英

在python中優化for循環

[英]Optimizing a for-loop in python

我有一個代碼,將其數據放入字典中並聲明。 我目前在for循環中的時間很長,大約需要200萬個數據,大約需要2個小時。 現在,我正在考慮如果我有200萬個數據。

這是我的for循環示例(很抱歉為變量命名,這只是我的示例代碼):

# Gets the data in database
data_list = self.my_service.get_database_list()

my_dict_list = {}

for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age

    my_dict_list[primary_key] = value

這是我的模型/數據庫獲取代碼:

def get_database_list(self):
    return self.session.query(
        self.mapper.name,
        self.mapper.addreess,
        self.mapper.age,
        )

我的數據庫引擎是InnoDB 有沒有一種方法可以使其稍微優化或更快地遍歷數據。 感謝你的分享。

首先,我懷疑您的瓶頸(幾個小時)在於python部分。 您可以使用生成器和dict理解來獲得一些改進,但是要提高多少呢? 尋找200,000行的樣本:

import base64
import os
def random_ascii_string(srt_len):
    return base64.urlsafe_b64encode(os.urandom(3*srt_len))[0:srt_len]

>>> data = [{'id': x, 'name': random_ascii_string(10), 'age':'%s' % x,
             'address': random_ascii_string(20)} for x in xrange(2*10**5)]

你的方法

>>> timeit.timeit("""
... from __main__ import data
... my_dict_list = {}
... for item in data:
...     my_dict_list[item['id']] = item['name'] + item['address'] + item['age']""",
...         number = 100)
16.727806467023015

清單理解

>>> timeit.timeit("from __main__ import data; "
...    "my_dict_list = { d['id']: d['name']+d['address']+d['age'] for d in data}",
...     number = 100)
14.474646358685249

我懷疑您會在這些優化中找到兩個小時。 因此,您的首要任務是找到瓶頸。 我建議您看一下工作中的MySQL部分,並可能將其重新分配給:

  • 每個表使用單獨的inno db文件
  • 如果檢索較小部分的數據,請使用索引
  • 在數據庫端進行一些評估,例如name + address + age
  • 不對整個數據進行處理,僅檢索所需的部分(前幾行)

很難猜測您的代碼在哪里花費最多的時間。 最好的辦法是使用cProfile運行它,並檢查結果。

python -m cProfile -o prof <your_script> <args...>

這將輸出一個名為prof的文件,您可以通過多種方式進行檢查,其中最酷的方法是使用runtimenakerun

除此之外,對dict的理解通常比其他方法要快:

my_dict_list = { item.primarykey: item.name + item.address + item.age }

此外,還不清楚是否要執行item.name + item.address + item.age (它們都是字符串嗎?),但是如果您可以考慮更改數據結構,並存儲item而不是該組合值,則可能會有所幫助進一步。

同意以上關於迭代器的評論。 您可以嘗試使用字典理解代替循環。

import uuid
import time

class mock:
    def __init__(self):
        self.name = "foo"
        self.address = "address"
        self.age = "age"
        self.primarykey = uuid.uuid4()

data_list = [mock() for x in range(2000000)]

my_dict_list = {}
t1 = time.time()
for item in data_list:
    primary_key = item.primarykey
    value = item.name + item.address + item.age
    my_dict_list[primary_key] = value
print(time.time() - t1)


my_dict_list = {}
t2 = time.time()
new_dict = { item.primarykey: item.name + item.address + item.age for item in data_list }
print(time.time() - t2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM