שאלה בפייטון

maor650

New member
שאלה בפייטון

שלום, צירפתי לכאן קובץ עם משימה וקוד שהוא הפתרון למשימה.
אני לא הבנתי מה אני אמור לממש פה בעצם ומה אני צריך לכתוב ב-python shell כדי לראות אם הקוד עובד. אם תוכלו לתת לי דוגמא מה אפשר למשל לכתוב בקריאה לפונקציה ב-shell אשמח. צירפתי את הקוד ואשמח לקבל הסבר לגביו למה הוא המתאים למשימה זו.
תודה לעוזרים.
 

BravoMan

Active member
התרגיל הזה בא לבדוק את הידע שלך

ברכיב של שפת Python שנקרא "מילון" Dictioary.

תוכל לקרוא הסבר בסיסי עליו כאן:
http://docs.python.org/2/tutorial/datastructures.html#dictionaries

והנה מדריכון שימוש ש-Google מציע:
http://www.tutorialspoint.com/python/python_dictionary.htm
הוא מכסה את כל הפעולות בסיסיות עם דוגמאות.

מילון הוא מבנה נתונים שמשייך לכל נתון בו "מפתח" (בד"כ מחרוזת, אבל הוא יכול להיות כל אובייקט בר השוואה).
בעזרת המפתח הזה אתה ניגש לנתון.

מה שמבקשים בתרגיל זה שתכתוב פונקציה שבונה מילון בו המפתחות הם מחרוזות, והערך שכל מפתח משויך עליו הוא רשימה של מילים שמתחילות במחרוזת הזו.

כך למשל אם יש לך אות t תכניס אותה בתור מפתח למילון ותקבל את כל המילים שמתחילות ב-t כמו test, try, turtle וכו'.

כדי להפעיל את הפונקציה אתה צריך לקרוא לה עם אובייקט של מילון בתור הפרמטר הראשון (כדאי שהאובייקט יהיה שמור גם מחוץ לפונקציה כדי שתוכל לבדוק את השינויים אחר כך), ועם מילה כלשהי בתור הפרמטר השני.

אז, תוכל להתחיל ככה:

my_dict = {}
add_prefixes(my_dict, 'hello')
print my_dict

אחר כך תחזור על הקריאה עם מילים אחרות ותראה איך המילון גדל (רק על תחזור על השורה הראשונה כי היא מאתחלת את המשתנה my_dict עם מילון ריק).

מה שהפונקציה עושה בגדול זה:
1. רצה בלולאה כעורך המילה
2. בכל פעם חותכת מתחילת המילה מחרוזת בעורך של מספר הלולאה (פעם ראשונה אות אחת, פעם שנייה שתי אותיות וכך הלאה),
3. שולפת מהמילון את רשימת המילים שמשויכות לאותה חתיכה (ייתכן שהחתיכה בכלל לא במילון לכן משתמשים במתודה get שמחזירה ערך ברירת מחדל במקום לזרוק חריגה).
4. בודקת אם המילה ברשימה, ואם לא מוסיפה אותה.
5. מעדכנת את המילון עם הרשימה החדשה.
 
ברמה הטכנית/קטנונית

נדמה לי שאין שום דרישה ממפתחות לממש *משהו*.
היינו:

class Dummy: pass

d = {}
d[Dummy()] = 'test'
d[Dummy()] = 'other'

אמור להיות תחביר תקין (אם כי לא שימושי בעליל), ולייצר מילון עם 2 זוגות.
 

BravoMan

Active member
דווקא יש:

https://wiki.python.org/moin/DictionaryKeys

הם צריכים להיות hasable ובעלי equality comparison לכן list למשל, לא יכול להיות מפתח.
אבל אפילו class ריק ממש איזה __hash__ דיפולטיבי, לכן הדוגמה שלך עובדת.
 
לא. התיעוד בוויקי הזה לא נכון.

>>> class X: pass
>>> dir(X())
['__doc__', '__module__']

>>> X().__hash__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: X instance has no attribute '__hash__'

>>> X() == X()
False

>>> x = y = X()
>>> x == y
True

>>> x = X()
>>> d = {x: 'first', X(): 'second'}
>>> d[x]
'first'
>>>

אבל גלשנו קצת מחוץ ל-scope של ה-OP...
 

BravoMan

Active member
לא לגמרי גלשנו כי הוא העלה עוד שאלה

בנושא הזה ממש:
http://www.tapuz.co.il/forums2008/viewmsg.aspx?forumid=89&messageid=171821377

התיעוד אולי לא לגמרי מדויק, אבל שים לב לקוד הבא:

>>> class X: pass
...
>>> a = X()
>>> b = X()
>>> hash(a)
2555222
>>> hash(b)
2555195
>>> hash(X())
-9223372036852220618


מצד שני, הקוד הבא זורק שגיאה:

>>> hash([])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash([1, 2, 3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


וכמובן:

>>> d = {}
>>> a = X()
>>> d[a] = 'test'
>>> d[a]
'test'
>>> b = [1, 2]
>>> d = 'second'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'


בדקתי את זה גם על Python 2.7 וגם על 3.2.
אני לא סגור למה הפונקציה המובנית hash עובדת על אובייקט שאינו מכיל מתודה __hash__, ייתכן שיש כאן כלל מסוים שפספסתי (לא הקדשתי יותר מידי זמן לחיפושים), אבל נראה שבסופו של יום כן יש מגבלה על מפתחות מילון שקשורה ל-hash.
 
מסתבר שיש default hash, כמו שאמרת

קריאה לפונקציה hash מחזירה, במקרה שאין מימוש ל __hash__, את כתובת האובייקט בזכרון: id() z.
כדי להפוך אובייקט ל-none hashable, צריך במפורש להגדיר def __hash__(self): return None

כנראה שבאותו אופן, השוואה דיפולטית משווה כתובות בזכרון (ואת סוג האובייקט, אני מניח). משהו כמו ReferenceEquals של #C.
 
למעלה