קוד קטן שמצאתי באינטרנט אפשר לי לראות בעיניים את ההבדל בין השיטות השונות מבחינת יעילות של זיכרון וזמנים וחשבתי לשתף פה את מי שהעניין מסקרן אותו. כל פעם תפעילו מתודה אחת ותעשו comment לשניים האחרים.
אוסיף ואומר שישנם דברים שלא ברורים לי ומי שיכול להבהיר לי את העניין אודה לו מאוד.
שאלתי כאן שלוש שאלות שהם בעצם שאלה אחת עם כמה אספקטים.
א. מדוע ב the list comprehension method כאשר אני מבצע השמה למשתנה (X = list(people_interator)) הזיכרון של המערכת קופץ ישר לMB300 כאילו אני משתמש במתודה הראשונה. על פניו זה נשמע הגיוני כי אני שומר במערכת זיכרון רב, אולם מצד שני אם אני בוחר לעשות הדפסה לאותה רשימה, פעולה שמשאירה אותי עם זיכרון נמוך מאוד, אני מקבל את כל הערכים בבת אחת, וזה כאשר הgenerator כבר לא יכול להוציא עוד ערכים. ועל פניו נראה שאם אני מקבל את כל הערכים בבת אחת זה אומר שהם שמורים איפשהו במחשב לא כן? אבל אם ככה מדוע לא מופיעה במצב כזה הקפיצה בזיכרון. הסתירה כאן לא ברורה לי.
א.2 אם אכן כל שמירת מידע גם generators שכל מטרתם לחסוך בזיכרון, לא יכולים לעזור לי, האם זה בעצם מייתר את העבודה שלהם במקרים רבים. כלומר כל עוד אני לא רוצה רק להדפיס מידע ספציפי אלא להשתמש בכל המידע הקיים כדי להפיק תועלת האם יכולת זו לא תוכל לעזור לי?
ב. שאלה זו קשורה במעט לסעיף א. כאשר אני עושה list comprehension איפה נשמר המידע עד שהפעולה נגמרת, הרי כל הרעיון בgenerator שכל פעם עובדים על פיסת מידע חדשה והקודמת נדרסת?
לצורך העניין יש לי רצון לספור תווים לתוך מילון ואין לי רצון להכניס ערכים שכבר הכנסתי כיצד אני עושה זאת?
הקוד הבא ירוץ לי שלוש פעמים במקום פעמיים. ולהוסיף if letter not in word_dic לא עושה את העבודה כי מבחינת המחשב לא הוכנסו הערכים עדיין למילון.
פתרון אלגנטי שראיתי הוא להוריד את התנאי ואת המילון הריק ואת זה להכניס ללולאה set(word)
'word = 'aba
word_dic = {}
word_dic = {letter : word.count(letter) for letter in word if letter not in word_dic}
תודה ענקית למי שמתייחס
the original method
Memory (Before): [18.285] Mb
Memory (After) : [304.972] Mb
Took 1.5 Seconds
the generator method
Memory (Before): [18.289] MB
Memory (After) : [18.300] MB
Took 1.578 Seconds
the list comprehension method
Memory (Before): [18.289] MB
Memory (After) : [18.914] MB
Took 1.71875 Seconds
כל פעם תפעילו מתודה אחת ותעשו comment לשניים האחרים.
את memory_profiler תצטרכו להתקין
import memory_profiler
import random
import time
names = ['John', 'Corey', 'Adam', 'Steve', 'Rick', 'Thomas']
majors = ['Math', 'Engineering', 'CompSci', 'Arts', 'Business']
print('Memory (Before): ' + str(memory_profiler.memory_usage()) + ' MB' )
def people_list(num_people):
result = []
for i in range(num_people):
person = {
'id': i,
'name': random.choice(names),
'major': random.choice(majors)
}
result.append(person)
return result
def people_generator(upper_bound):
i = 0
while i < upper_bound:
person = {
'id': i,
'name': random.choice(names),
'major': random.choice(majors)
}
i += 1
yield person
t1 = time.process_time()
population = 1000000
# the original method
people = people_list(population)
# the generator method < -------------------------
#people_interator = people_generator(population)
#for _ in range(population):
# next(people_interator)
# the list comprehension method < -------------------------
# people_interator = people_generator(population)
# list(people_interator)
t2 = time.process_time()
print('Memory (After) : {} Mb'.format(memory_profiler.memory_usage()))
print( 'Took {} Seconds'.format(t2-t1))