זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/python/lessons/decorators-lab
זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/python/lessons/decorators-lab
אחלה פתרונות אבל איפה התרגילים?
הי
התרגילים עצמם נמצאים בטאב ״טקסט״ (כפתור למעבר ואב נמצא מעל הסרטון)
אגב כמעט לכל שיעור באתר יש טקסט מלווה בטאב טקסט, שהרבה פעמים כולל גם הרחבות ותוספות על מה שמופיע בוידאו. ממליץ להסתכל שם אחרי שרואים את הוידאו (בכל השיעורים)
"""
Answer 23-4
"""
from functools import wraps
def memoize(f):
data={}
@wraps(f)
def wapper(n):
if data.has_key(n) :return data[n]
res=f(n)
data.__setitem__(n,res)
return res
return wapper
@memoize
def fib(n):
print "fib(%d)" % n
if n <= 2:
return 1
else:
return fib(n-1) + fib(n-2)
print fib(10)
התשובה בשאלה - לא נכונה מכיוון שבפונקציה רשמת split - צריך להסיר אאת ה- split
"""
Answer 25-5
"""
from functools import wraps
def debug(f):
@wraps(f)
def wapper(*args,**kwargs):
print "[]Debug: args=%s , kwargs=%s" % (args,kwargs)
res=f(*args,**kwargs)
print "[]Debug: result=%s" % (res)
return res
return wapper
@debug
def sum_digits(n):
digits = str(n)
result = 0
for char in digits:
result += int(char)
return result
print sum_digits(1531221)
תודה על התיקון - עדכנתי את הטקסט!
שאלה על משהו שמבלבל אותי מדוע אחרי החזרה של פונקציית המעטפת עדיין בזיכרון
התוכנית יש שמירה של האובייקט data גם אחרי קריאות נוספות לפונקציית המעטפת ,היא לא אמורה להתנקות מהזיכרון אחרי החזרה הראשונה של פונקצית העיטור?
"""Write a decorator called after5 that takes a
function and returns a new version of it that ignores
first 5 invocations"""
def after5(f):
data = { 'counter' : 0 }
def wrapper(*args, **kwargs):
data['counter'] += 1
if data['counter'] > 5: return f(*args, **kwargs)
return wrapper
@after5
def doit(): print "Yo!"
# ignore the first 5 calls
doit()
doit()
doit()
doit()
doit()
# so only print yo once
doit()
ומדוע על אותו אופן של התוכנית הקודמת ,התוכנית הנ"ל לא עובדת?
def after5(func):
counter=0
def warpped(*args,**kwargs):
if counter !=5:
counter+=1
pass
else:
return func(*args,**kwargs)
return warpped
@after5
def doit(): print "Yo!"
doit()
doit()
doit()
doit()
doit()
doit()
doit()
לגבי ניהול זיכרון יש שיעור על זה בקורס המתקדם. שווה להעיף מבט ואולי זה יעזור להבין יותר טוב מה הולך שם:
https://www.tocode.co.il/bundles/advanced-python3/lessons/memory
לגבי התוכנית השניה יש בעיה שהפונקציה הפנימית לא מזהה שמשתנה counter שלה הוא אותו אחד מהפונקציה החיצונית. גם על זה יש שיעור בקורס המתקדם ואני חושב שכדאי להעיף מבט שם כדי לקבל תמונה יותר מקיפה:
https://www.tocode.co.il/bundles/advanced-python3/lessons/variable-scope
אם אחרי צפיה בשיעורים אלה עוד יהיו שאלות תרגיש חופשי להמשיך לפרסם כאן
לגבי הcounter נראה לי שהבנתי למה זה לא עובד מפני שבפונקציית warpped המשתנה counter נוצר כמקומי לפונקציה לפי מה שאני מבין בגלל ההשמה counter+=1 שגורמת לפייתון ליצור משתנה זה כמקומי למרות שניסתי לתקן לפי
nonlocal אבל פייתון זורק לי על זה שגיאה:
def after5(func):
counter=0
def warpped(*args,**kwargs):
nonlocal counter
if counter !=5:
counter+=1
pass
else:
return func(*args,**kwargs)
return warpped
@after5
def doit(): print "Yo!"
doit()
doit()
doit()
doit()
doit()
doit()
doit()
ולגבי השאלה הראשונה הבנתי שבאובייקט דאטה לא מת מכיוון שכל חזרה שלו מהפונקצייה אז כויכול הפונצקיה מצביעה עליו במרחב שלה ואז כל הפעלה נוספת שלה כויכול מעדכנת אותו
מדויק.
בפייתון 2 אין nonlocal (זה מילה חדשה של python3), הטריק במקום זה הוא להגדיר מערך למשל כך:
def after5(func):
counter=[0]
def warpped(*args,**kwargs):
if counter[0] !=5:
counter[0]+=1
pass
else:
return func(*args,**kwargs)
return warpped
מקסים… שיהיה יום טוב ורק דברים טובים…
חייב לציין שהקורס שלך בפייתון מהנה