פורסם: 25/01/2015 - 19:48
נושא ההודעה: איך לממש הורשה כששתי המחלקות צריכות לקבל ערכים?
|
היי לכולם
אני מתרגל הורשה בפייתון ואני מנסה לרשת אובייקט שמחייב לקבל מס ערכים כלשהם, כדי להיווצר.
העניין הוא שגם המחלקה השניה שמרחיבה את הראשונה צריכה לקבל ערכים, כשאני מריץ בקונסול את הקוד הבא אני מקבל שגיאה, היכן אני טועה?
קוד: |
class Person(object):
def __init__(self, first_name, last_name, person_id, date_of_birth, gender):
self.first_name = first_name
self.last_name = last_name
self.person_id = person_id
self.date_of_birth = date_of_birth
self.gender = gender
class Customer(Person):
def __init__(self, balance, frame_of_account, sum_of_loans):
Person.__init__(self, first_name, last_name, person_id, date_of_birth, gender)
self.balance = balance
self.frame_of_account = frame_of_account
self.sum_of_loans =sum_of_loans
|
קוד: |
c = classes.Customer("moshe", "cohen", "23", "12/12/12", "male", 100, 500, 1000)
|
קוד: |
Traceback (most recent call last):
File "<ipython-input-83-4b1b722001fa>", line 1, in <module>
c = classes.Customer("moshe", "cohen", "23", "12/12/12", "male", 100, 500, 1000)
TypeError: __init__() takes exactly 4 arguments (9 given)
|
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 20:34
נושא ההודעה:
|
היי מתרגל יקר,
גם אני לומד פייטון כרגע, אך אני פחות מתרגל ויותר לומד תוך כדי עבודה,
אז כך שנוצרים לי פערים שיהיה עליי כנראה להשלים בעתיד...
בכל מקרה,
פייטון אומרת לך בפירוש -
נתת לפונקציה 9 ארגומנטים והפונקציה מקבלת ארבעה.
למה שלא תגדיר גם את הארגומנטים החסרים באובייקט היורש?
ואז תקבל דבר כזה:
קוד: |
class Customer(Person):
def __init__(self, balance, frame_of_account, sum_of_loans, first_name, last_name, person_id, date_of_birth, gender):
Person.__init__(self, first_name, last_name, person_id, date_of_birth, gender)
|
האם אתה רוצה להימנע מלקבל את הארגומנטים הדרושים לperson ולהעבירם הלאה?
ולמה שתרצה להימנע מזה?
נראה לי שהגיוני (בלי קשר לפייטון) אם Y יורש מX,
אז Y אמור להעביר לX את כל הארגומנטים הדרושים ליצירתו של X..
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 20:38
נושא ההודעה:
|
חשבתי לעשות כך וזה באמת עובד אבל מסיבוב בנט ראיתי שלא עובדים כך
תראה את זה למשל (לקראת הסוף)
http://www.python-course.eu/inheritance_example.php
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 20:52
נושא ההודעה:
|
טוב זה גם לא ממש עובד, הוא טוען שחסר לו ערך נוסף, למה הוא מתייחס לself כמשהו שחסר (או שאני מפספס פה משהו)
קוד: |
class Person(object):
def __init__(self, first_name, last_name, person_id, date_of_birth, gender):
self.first_name = first_name
self.last_name = last_name
self.person_id = person_id
self.date_of_birth = date_of_birth
self.gender = gender
class Customer(Person):
def __init__(self, balance, frame_of_account, sum_of_loans,first_name,
last_name, person_id, date_of_birth, gender):
Person.__init__(self, first_name, last_name, person_id,
date_of_birth, gender)
self.balance = balance
self.frame_of_account = frame_of_account
self.sum_of_loans =sum_of_loans |
קוד: |
c = pkg.classes.Customer(100, 500, 1000, "moshe", "cohen" "123", "12/12/12", "male")
Traceback (most recent call last):
File "<ipython-input-14-a7aa7a860592>", line 1, in <module>
c = pkg.classes.Customer(100, 500, 1000, "moshe", "cohen" "123", "12/12/12", "male")
TypeError: __init__() takes exactly 9 arguments (8 given)
|
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 21:13
נושא ההודעה:
|
נקודה חשובה
גם אני עדיין מתבחבש קלות עם ה-self,
עליו תוכל לקרוא עוד כאן:
https://docs.python.org/2/tutorial/classes.html#random-remarks
עוד מידע רלוונטי יש כאן:
http://concentricsky.com/blog/2013/apr/pythons-magical-self
אין לי הסבר יפה משל עצמי לתת לך הפעם
אבל תמיד, או לפחות כך אני מבין את self
תעביר אותו בתור המשתנה הראשון של פונקציה..
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 21:16
נושא ההודעה:
|
ואיך שכחתי את:
http://en.wikipedia.org/wiki/Python_(programming_language)#Methods
self טיפה מזכיר את this, כשהייתי צריך להעביר את this באופן מפורש ב-Java לדוגמא..
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 22:09
נושא ההודעה:
|
לא קשור ל- self. הוא מועבר אוטמאטית באיתול של המחלקה. חסר לך פסיק בין "cohen" ו "123".
למרבה הפלא הוא מתייחס לזה כמחרוזת אחת כלומר "cohen123" ולא צועק על זה שאתה שם שם פעמיים מרכאות.
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 22:15
נושא ההודעה:
|
Anonymous : | לא קשור ל- self. הוא מועבר אוטמאטית באיתול של המחלקה. חסר לך פסיק בין "cohen" ו "123".
למרבה הפלא הוא מתייחס לזה כמחרוזת אחת כלומר "cohen123" ולא צועק על זה שאתה שם שם פעמיים מרכאות. |
אמממ אני חושב ש-self לא מועבר אוטומאטית,
ראה כאן:
http://neopythonic.blogspot.co.il/2008/10/why-explicit-self-has-to-stay.html
על סמך מה אתה מבסס את זה שלא חייבים להעביר את self?
נכון אפשר לקרוא לו בשם אחר, אך הוא עדיין יהיה self..
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 22:26
נושא ההודעה:
|
ציטוט: |
ל סמך מה אתה מבסס את זה שלא חייבים להעביר את self?
נכון אפשר לקרוא לו בשם אחר, אך הוא עדיין יהיה self.. |
לא מועבר בצורה מפורשת בקריאה לפונקציה. אתה כן צריך אותו כפרמטר לפונקציה.
על סמך זה:
קוד: |
class Customer(object):
def __init__(self):
print self
c = Customer()
$ python /tmp/t.py
<__main__.Customer object at 0x7f1a49c21750>
|
כמו שאתה רוצה הפונקציה מקבל פרמטר (אתה לא חייב לקרוא לו self) אבל לא העברתי כלום ביצירה של האובייקט.
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 22:54
נושא ההודעה:
|
Anonymous : | ציטוט: |
ל סמך מה אתה מבסס את זה שלא חייבים להעביר את self?
נכון אפשר לקרוא לו בשם אחר, אך הוא עדיין יהיה self.. |
לא מועבר בצורה מפורשת בקריאה לפונקציה. אתה כן צריך אותו כפרמטר לפונקציה.
על סמך זה:
קוד: |
class Customer(object):
def __init__(self):
print self
c = Customer()
$ python /tmp/t.py
<__main__.Customer object at 0x7f1a49c21750>
|
כמו שאתה רוצה הפונקציה מקבל פרמטר (אתה לא חייב לקרוא לו self) אבל לא העברתי כלום ביצירה של האובייקט. |
דוגמא יפה
עכשיו מה יקרה נוסיף פונקציה שבארגומנטים שהיא מקבלת לא נציין כלום:
קוד: |
class Customer(object):
def __init__(self):
print (self)
def funckyMonkey():
print ("bla bla")
|
וכעת נקרא לפונקציה הזאת:
קוד: |
In [1]: import bla
In [2]: bla
Out[2]: <module 'bla' from '/home/****/bla.py'>
In [4]: c = bla.Customer()
<bla.Customer object at 0x7f6a93e02c18>
In [5]: c.funckyMonkey()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-78780ac96bd1> in <module>()
----> 1 c.funckyMonkey()
TypeError: funckyMonkey() takes 0 positional arguments but 1 was given
|
אך אם נוסיף את הארגומנט self כארגומנט שהפונקציה מקבלת:
קוד: |
def funckyMonkey(self):
print ("bla bla")
|
נוכל להריץ ללא העברת self:
קוד: |
In [4]: c.funckyMonkey()
bla bla
|
אבל משום מה אם ננסה להריץ עם self נקבל כי self לא מוגר,
מעניין היכן הייתי צריך להגדיר אותו :\
לא סתם self הוא מבלבל קלות...
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 23:09
נושא ההודעה:
|
קוד: |
TypeError: funckyMonkey() takes 0 positional arguments but 1 was given |
זה אומר שהפונציה אמורה לקבל פרמטר אחד (self) אבל לא הגדרת אותו.
נראה לי שאתה מבלבל בין העברה של פרטטרמים להגדרה שלהם בפונקציה.
תתחיל ללמוד בלי OOP ואז תמשיך.
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 23:29
נושא ההודעה:
|
ועוד משהו:
קוד: |
>>> a="lll" "jjj"
>>> a
'llljjj'
>>>
|
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 23:33
נושא ההודעה:
|
וגם זה:
קוד: |
class Customer(object):
def __init__(thing):
print thing
c = Customer()
print c
|
|
|
חזרה לתוכן הדיון |
פורסם: 25/01/2015 - 23:41
נושא ההודעה:
|
Anonymous : | קוד: |
TypeError: funckyMonkey() takes 0 positional arguments but 1 was given |
זה אומר שהפונציה אמורה לקבל פרמטר אחד (self) אבל לא הגדרת אותו.
נראה לי שאתה מבלבל בין העברה של פרטטרמים להגדרה שלהם בפונקציה.
תתחיל ללמוד בלי OOP ואז תמשיך. |
התלהבתי יותר מדיי
חטאתי בחטא ההיבריס, פשוט לא קראתי את הודעת השגיאה,
וכן אני בטוח יכול לשפר את הידע התיאורטי שלי, גם עם OOP וגם בלי,
זה מה שקורה כשאתה עדיין מתכנת מתחיל
|
|
חזרה לתוכן הדיון |
פורסם: 26/01/2015 - 00:07
נושא ההודעה:
|
אתה צריך להשתמש ב־super:
קוד: | >>> class Chair(object):
... def __init__(self, legs):
... self.legs = legs
...
>>> class BrandedChair(Chair):
... def __init__(self, legs, brand):
... super(BrandedChair, self).__init__(legs)
... self.brand = brand
...
>>> c = BrandedChair(4, 'test')
>>> c.legs
4
>>> c.brand
'test' |
הדוגמא הנ"ל היא לפייתון 2. ב־3 לא צריך לרשת מ־object ו־super לא צריך פרמטרים.
קרא עוד על super ו־bound methods להבין self וכו'.
|
|
חזרה לתוכן הדיון |
פורסם: 26/01/2015 - 09:12
נושא ההודעה:
|
ציטוט: |
התלהבתי יותר מדיי Smile
חטאתי בחטא ההיבריס, פשוט לא קראתי את הודעת השגיאה,
וכן אני בטוח יכול לשפר את הידע התיאורטי שלי, גם עם OOP וגם בלי,
זה מה שקורה כשאתה עדיין מתכנת מתחיל Smile
|
לא יודע במה טעית אבל זה בסדר. אתה יכול להגיד תודה וסליחה.
|
|
חזרה לתוכן הדיון |
פורסם: 26/01/2015 - 10:38
נושא ההודעה:
|
mksoft : | אתה צריך להשתמש ב־super:
קוד: | >>> class Chair(object):
... def __init__(self, legs):
... self.legs = legs
...
>>> class BrandedChair(Chair):
... def __init__(self, legs, brand):
... super(BrandedChair, self).__init__(legs)
... self.brand = brand
...
>>> c = BrandedChair(4, 'test')
>>> c.legs
4
>>> c.brand
'test' |
הדוגמא הנ"ל היא לפייתון 2. ב־3 לא צריך לרשת מ־object ו־super לא צריך פרמטרים.
קרא עוד על super ו־bound methods להבין self וכו'. |
קראתי על super לא הבנתי עדין למה אני צריך אותו.
ברגע שאני יורש את המחלקה אז אני מקבל גם את כל המשתנים ומה שהיא מכילה, עד כמה שאני מבין בלי super גם יהיו לי רגלים לכיסא, מה פספסתי?
ותודה רבה לכולם על העזרה
|
|
חזרה לתוכן הדיון |
פורסם: 26/01/2015 - 12:20
נושא ההודעה:
|
לאחר refactoring, שינתי בקוד ש־BrandedChair יורש מ־ExpansiveChair (שהוא בתורו יורש מ־Chair). אני לא צריך/רוצה לעבור על הקוד של BrandedChair ולמצוא את כל המקומות שהתייחסתי בהם לאבא, super דואג להחזיר את הנכון לפי ה־MRO (קרא גם על Method Resoluton Order).
זה לא מקרה קצה, זה קורה כל הזמן כשעובדים עם מחלקות.
לדוגמא יש לי מספר יורשים מ־DetailView באפליקציית Django ואני רואה שיש לא מעט משותף ב־get_context_data שלהם. אני מזקק את זה למחלקת אב משותפת שיורשת מ־DetailView ומגדירה את ה-context המשותף.
לאחר מכן אני משנה את ה־views שיירשו מהמחלקה החדשה, אני לא רוצה לשנות את כל הקריאות שלהם לאבא (get_context_data, וכו').
ראה דוגמא לשימוש הנ"ל בתיעוד של Django:
https://docs.djangoproject.com/en/1.7/topics/class-based-views/generic-display/
|
|
חזרה לתוכן הדיון |
פורסם: 26/01/2015 - 12:46
נושא ההודעה:
|
ציטוט: |
עד כמה שאני מבין בלי super גם יהיו לי רגלים לכיסא, מה פספסתי?
|
אולי יהיה לך כיסא אבל לא יהיה לו רגליים.
קוד: |
AttributeError: 'BrandedChair' object has no attribute 'legs'
|
|
|
חזרה לתוכן הדיון |
פורסם: 27/01/2015 - 10:32
נושא ההודעה:
|
מה שהוא התכוון: במקום להשתמש ב־super לקרוא ישירות ל-init של האבא.
|
|
חזרה לתוכן הדיון |
פורסם: 27/01/2015 - 20:28
נושא ההודעה:
|
נכון מאוד לזה התכוונתי
תודה רבה לכולם החכמתם אותי מאוד
|
|
חזרה לתוכן הדיון |
|