פיתון למתכנת רובי

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

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

אז מה לא אינטואיטיבי עבורי?  הכל 🙂
סתם, הנה הדגמה קטנה לרובי:

[1, 2, 3, 4].each_with_index do |elem, idx|
puts "arr[#{idx}]=#{elem}"
end

המקביל (למעט שימוש ב format string) של זה בפיתון:

for idx, elem in enumerate([1, 2, 3, 4]):
print('arr[{}]={}'.format(idx, elem))

לפני שאסביר מה מפריע לי, בואו נראה איך זה יתבצע ב ES6 למשל:

[1, 2, 3, 4].forEach( (elem, idx) => console.log('arr[%d]=%d', idx, elem) )

בגו (go/golang) זה יראה ככה:

slice := []int{1, 2, 3, 4}
for idx, elem := range slice {
 fmt.Printf("arr[%d]=%d\n", idx, elem)
}

ברובי, הקוד מדבר בעד עצמו, אני יודע בוודאות שאני עושה איטרציה שמקבלת גם אינדקס. למעשה בקוד רובי, אם אני רואה מתודה בשם each, היא אמורה לבצע איטרציה על דברים ולספק לי בלוק ריצה, לרוב גם עם פרמטר, עוד לפני שקראתי את התיעוד מעבר.

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

בגו, יש לולאה מסוג אחד – for.
הלולאה הזו מסוגלת לבצע איטרציה באמצעות range, או להיות לולאת for כפי שהיא מוכרת בתחביר C.
אין עוד סוגים של לולאות.

אז מה מפריע לי בפיתון?
אני יכול לבצע איטרציה פשוטה של

for elem in [1, 2, 3, 4]:
...

אבל הייתי מצפה שיהיו בין פרמטר אחד לשני פרמטרים כאן. במידה ולא, הייתי מצפה שה instance של ה list יחזיר למשל iter_with_idx או משהו בסגנון. אבל לא! צריך משהו חיצוני לגמרי מסוג הקונטינר שיחזיר את זה.
זה משהו שאפשר לזכור, אבל הוא לא מגיע בצורה אינטואיטיבית. הסיבה לכך, היא שיש סוג של שעטנז בין תכנות מונחה עצמים לבין תכנות פרוצדורלי.
למשל בגו, הדרך להגיד שרוצים לבצע איטרציה מכל סוג שהוא, על משהו שהוא איטרבילי, יהיה באמצעות הפקודה range. זו לא פונקציה, אלא ממש פקודה של השפה. מילה שמורה.

אבל בפיתון האיטרציה מסוגלת להתבצע באמצעות הגדרה של שני מתודות: __iter__ ו __next__ (או next בגרסה 2), אז למה אין איטרציה לאינדקס? למה צריך משהו חיצוני בשביל זה?

סבבה, אפשר "לבלוע" את זה, אם זה היה הדבר היחיד.

הנה בעיה נוספת:

ברובי, יש לי פעולה כזו:

[1, 2, 3, 4].join(',')

אני למעשה הופך את כל המספרים במערך למחרוזת אחת מופרדת בפסיקים.

לרשימה בפיתון אי אפשר לעשות אותו הדבר. צריך לעשות את זה בגישה לגמרי שונה:

','.join(str(n) for n in [1, 2, 3, 4])

אם אני מעביר רשימה שאפשר להמיר אותה למחרוזת, הייתי מצפה שפעולת join תבין את זה, ותעשה את זה עבורי, במידה כמובן, שאפשר להמיר למחרוזת.
אבל אם אעשה זאת ככה:

','.join([1, 2, 3, 4])

הוא יצעק עלי:

TypeError: sequence item 0: expected str instance, int found

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

אפילו ES עושה את זה בגישה שאני מצפה לה:

[1, 2, 3, 4, 5].join(',')

כלומר זה לא ייחודי לרובי.

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

עוד הדגמה לבעיה שלי לגישה של תכנות מונחה העצמים, או יותר נכון המחסור בשימוש בו בצורה טובה יותר:

רובי:

[1, 2, 3, 4].length
[1, 2, 3, 4].count

ES:

[1, 2, 3, 4].length

פיתון:

[1, 2, 3, 4].count() # TypeError: count() takes exactly one argument (0 given)
# oh, it looks up if an element exists... and how many times, okay then ...

len([1, 2, 3, 4])

אם אתעלם בכוח מכך ש count אינו אומר באמת מה הוא עושה. כלומר, סופר מה? הייתי מצפה ל count_occurent_elements או משהו כזה כאשר יש הפרדה בין פעולות ספירה שונות של איברים ברשימה.
אבל למה החיפוש של הגודל הוא חיצוני?
מדוע קונטיינר כדוגמת מחרוזת, רשימה, מפה או אפילו sequence לא יכולים להחזיק בערך הזה בעצמם ולייצא אותו בצורה מונחת עצמים?

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

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

ההתנהגות הזו של טיפוס דינאמי מול טיפוס שהוא strong typed, בצורה לא מובנת בעיני. כמובן שיש מקומות בהם חשוב לקבל ערך מסוג אחד ולא מסוג אחר. אבל למה כאשר רוצים לחבר הרבה איברים למחרוזת?! זה הרי מאוד explicit מה אני רוצה להשיג כאן.

העניין הוא שבלי לשנן בעל פה איך פיתון מתנהגת בכל דבר ודבר, מאוד קשה לדעת רק ממבט על הקוד כיצד הוא יתנהג.
ברובי, מאוד קל להבין, הבעיות שנתקלים בהם הם על התוכן, אבל מרבית התחביר נשאר זהה, רק במקומות שזה הגיוני הוא משתנה.
למשל מחרוזת, תכיל איטרציה על בתים, בנוסף על איטרציה על תווים. זה הגיוני, כי מחרוזות שהן לא ASCII יכולות להכיל תו שמורכב ממספר בתים, אבל לדעת את האורך יהיה עם מתודה בשם length.
אבל הגיוני שהמתודה each למחרוזת תבצע איטרציה. עכשיו השלב הבא, האם על בתים או על תווים, אבל קודם כל הבנו שיש כאן איטרציה על משהו.

אה, ועוד דבר, ברובי, count לא קיים למחרוזת אמנם, אבל בכל מה שיורש מ enumerable (כדוגמת מערך ו hash) ב3 צורות:

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

עבור Hash שימוש מספר 2, תמיד יחזיר 0, כי הבדיקה מורכבת מעט יותר, הרי על מה אנחנו רוצים לבצע את הספירה? על מפתחות? סבבה, יש מתודה בשם keys. על ערכים? סבבה, יש מתודה בשם values. שתיהן מחזירות מערכים. לבדוק אם מפתח וערך מתקיימים ביחד, זה לא הגיוני עבור count להחזיר, כי לא יכולים להיות 2 מפתחות באותו השם. לבדוק האם מפתח קיים, משתמשים ב include?‎ (סימן השאלה בסוף). אותו הדבר לגבי מערך, אותה מתודה תחזיר האם איבר קיים, שוב פעם ירושה, הפעם מ BasicObject.

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

8 מחשבות על “פיתון למתכנת רובי

  1. phpandmore

    אני אוהב את שפת פייתון בעיקר בזכות הצורך באינדנטציה נכונה בפקודות Flow of Control, נוח לי מאוד גם לאתחל מערכים בשפה הזאת, בנוסף, אני ממליץ על המודול numpy לביצוע פעולות מתמטיות גם על וקטורים, מטריצות ושאר מערכים.

    1. ik_5 מאת

      האינדטציה קיימת בעוד שפות, וגם אתחול מערכים קיימים בעוד שפות.
      הבעיה היא שהשפה לא אחידה. יש המון "סיבות" למה זה ככה, יש מליארד מסמכי PEP שבאים לתרץ את זה.

      אבל הבעיה עדיין נשארת אין אחידות בשפה.

  2. שי


    https://polldaddy.com/js/rating/rating.jsרוב התלונות שלך מבוססות על חוסר היכרות עם פיתון. או שהתלונה היא חסרת חשיבות כמו התלונה הראשונה על האינדקס או פשוט בורות של אדם שלא השתמש הרבה בשפה. וכמובן שאין פה בכדי להעליב אותך ומקווה שתקבל את זה ברוח הזו:
    פיתון היא כן strongly typed, היא עושה הפרדה מוחלטת בין טיפוסי נתונים. האופי הדינאמי שלה הוא ההתיחסות שלה למשתנים, כלומר משתנה לא מוגדר כ-type מסויים. אבל אם תנסה לחבר שני ערכים מטיפוסים שונים אתה תקבל שגיאה, אלא אם הטיפוסים הללו הגדירו interface שמאפשר לחבר ביניהם (כמו int ו-float לדוגמה).
    זו הסיבה ש-join עובדת בדרך שבה היא עובדת. join היא מתודה שמחברת מחרוזות ברשימה. אז הייתי משנה את התלונה שלך על join ללמה join לא קוראת ל-__str__ או __rep__. זה עדיין עניין של חלקית סגנון וחלקית חלק מהפילוסופיה של פיתון ולא משהו שיש לו חשיבות מיוחדת בעיצוב שפה לדעתי, אבל זה יותר הגיוני.
    | אבל למה החיפוש של הגודל הוא חיצוני?
    | מדוע קונטיינר כדוגמת מחרוזת, רשימה, מפה או אפילו sequence לא יכולים להחזיק בערך הזה בעצמם ולייצא אותו בצורה מונחת עצמים?
    כל אובייקט שתומך ב-len צריך לממש מתודת __len__, זה בדיוק הכוונה ב-OOP. זה לא משנה מה האובייקט או מה הוא מכיל, אם הוא מממש את הפונקציה __len__ תוכל להשתמש בפונקציה len בכדי לבקש ממנו את הגודל. האם להשתמש בפונקציה או מתודה, זה כבר עניין של העדפה אבל זה שזה שונה משפות אחרות זה לא אוטומטית אומר שזה בעיה בשפה עצמה. רק עניין של הרגלים.
    | אבל למה כאשר רוצים לחבר הרבה איברים למחרוזת?! זה הרי מאוד explicit מה אני רוצה להשיג כאן.
    כתבת בפוסט קוד שעושה את זה. תעשה import this ותבין את הפילוסופיה של פיתון יותר טוב. ביחוד השורה "explicit is better than implicit". אם אתה רוצה ליצור מחרוזת ענקית מטיפוסי נתונים שונים (כולל None וערכי זבל שיכולים להופיע שם), השפה לא מונעת את זה ממך, רק דורשת שתעשה זאת בצורה explicit.

    1. ik_5 מאת

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

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

      סתם לצורך העניין, אפילו אתה הגבת שהיא לא בדיוק dynamic type, אלא בכלל strong type .

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

      בפוסט הזה הצגתי איך יש הבדל בין גישה ישירה של שפה, מול גישה שהיא בעיני מוזרה מאוד.

      למשל, היא שפה התומכת אובייקטים, אבל מרבית הפעולות עליה לא נובעות מאובייקט למרות שאתה משתמש באובייקט עצמו, או יותר נכון ב instance.

      ככה שהמסר של פיתון מאוד לא ברור בשימוש, יש לה המון code smells בתכנון שאיכשהו מקובלים על מרבית המפתחים בה.

  3. שי


    שוב זה חוזר לנקודה על חוסר ניסיון. strong typing זה עניין של טיפוסי נתונים. אם יש לך dict ורשימה, לא תוכל להתייחס אליהם בצורה זהה, כמו לדוגמה לחבר ביניהם. לא תוכל לעשות זאת מכיוון שפיתון היא strongly typed והיא לא מאפשרת לך לעשות עירבוביה בלי לעשות זאת באופן מפורש (עם מימוש הממשק המתאים). dynamic typing מדבר על *משתנים*. אין טיפוסי משתנים בפיתון, ותוכל להכניס למשתנה כל ערך מכל סוג. a=5;a='hello world' זה תקין לחלוטין בפיתון בגלל שהיא דינאמית לחלוטין. זה דבר מאוד בסיסי שחשוב להבין כאשר אתה כותב בכל שפה, וההחלטה לעשות את פיתון strongly typed היא החלטה חכמה שמונעת באגים ולא "code smells" שנובע מחוסר הבנה של הטכנולוגיה שבה אתה משתמש.
    > למשל, היא שפה התומכת אובייקטים, אבל מרבית הפעולות עליה לא נובעות מאובייקט למרות שאתה משתמש באובייקט עצמו, או יותר נכון ב instance.
    OOP מדבר על אבסטרקציה של פעולות ונתונים, פיתון מייצרת ממשק מאוד אבסטרקטי ומאפשרת לך המון גמישות כשזה נוגע לאיך פעולות מוגדרות. יש לך ממשקים שונים לדברים שמובנים בשפה (כמו דוגמת החיבור של שני טיפוסי נתונים), וכל אובייקט שאתה מייצר יכול לבחור באיזה ממשקים הוא תומך. יש לך מתודת __len__ אם זה כל כך חשוב לך להשתמש בסינטקס של מתודה, אבל אין לזה שום חשיבות, זה רק עניין של סינטקס.
    פיתון היא לא Perl/Ruby/Javascript יש לה את המבנה וההגיון שלה, אם תלחם בה בכדי לגרום לה לעבוד כמו השפות האחרות מן הסתם שזה יתסכל אותך, אבל אם תנסה להבין למה נעשו הבחירות שנעשו אתה תראה שהיא מאוד הגיונית ורוב ההחלטות תורמות לפרודקטיביות.

    1. ik_5 מאת

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

      אבל היא ממש לא explicit בדברים שלה.

      מה הכוונה?
      ובכן, אם כל משהו שמסוגל להחזיר כמות או אורך, לפחות יורש ממחלקה שכזו, אפשר להציג API אחיד לזה. היות ואין primitives בשפה אשר בהם יש אורך או גודל, זה היה הגיוני שתהיה אחידות בשפה. אבל אין. יש לך מימוש "פרטי", שבמקרא נקרא __len__ בכולם, אשר בעצם פונקציה חיצונית בשם len קוראת לה.

      אבל למעשה יש כאן כפילות של עבודה. ואין כאן explicit אלא implicit למימוש, היות ובמידול קוד, היית מצפה עכשיו בלי להכיר את השפה, או המימוש של משהו, לספק את זה כ first class citizen.

      גם כ strong typed, אתה יכול לקבל את התכונות האלו.
      יותר מזה, במידה ולקונטינרים יש אב משותף במחלקה שהם יורשים, אשר מאפשרת לשתף מידע בניהם, היה ניתן לעשות זאת.
      המחסור בגישה שכזו, היא שעושה את פיתון ללא נגישה או קריאה באמת. רק כאשר אתה מכיר כאמור את ההתנהגויות האלו, אתה מתחיל להתמודד איתם ופתאום זה מובן.

      עכשיו מישהו בעל רקע בתכנות אבל ללא רקע בפיתון שמסתכל על זה ולא ברור לו, מראה כי העיקרון של implicit מול explicit אינו מתקיים בפועל. זה נחמד להגיד שזה קיים, כי להחזרת ערך משתמשים ב return, אבל זה עדיין לא זה, אם מרבית האלמנטים בשפה אינם כאלו.

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

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

      עכשיו בנושא הבחירות. לדעתי חלק מהבחירות של גווידו טובות (למשל יצירת "קבוע" למחרוזת, אשר כל מי שצריך את אותו התוכן, מקבל את אותה הכתובת.
      גם הבחירה למשל לא להשתמש בsoftware exceptions, אלא בפעולה דמוית return, היא בחירה מאוד טובה שחסרה בהמון מקומות. ולצערי רובי די גרוע בניהול חריגות כאשר מדובר בחגירות חיצוניות שנכתבו ב C למשל.

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

  4. שי

    >היות ויש לי המון רקע ברובי, ואין לי כמעט רקע בפיתון, אני לא מוצא בשום צורה את פיתון נוחה. היא עוף מוזר שהגישה שלה מסבכת את הפיתוח בעיני.
    > אבל למעשה יש כאן כפילות של עבודה. ואין כאן explicit אלא implicit למימוש, היות ובמידול קוד, היית מצפה עכשיו בלי להכיר את השפה, או המימוש של משהו, לספק את זה כ first class citizen.

    המשפטים האלה די מסכמים את הגישה שלך, ואני אמרתי למה אני חושב שזו לא הגישה הנכונה ל-evalutaion של שפה. היה לך פעם פוסט ממש טוב על מערכת הפעלה חדשה ומוזרה שנקראת windows, הטיעונים בפוסט הזה נשמעים כמו הרבה מהטיעונים שהיו בפוסט ההוא. אני לא רגיל זה לא טיעון טוב. פיתון היא מאוד הגיונית, ההחלטות בעיצוב שלה הן עקביות והלוגיקה מאחוריהם היא OOP קלאסית. רובי היא אחרת, ויכול להיות שהיא מאוד טובה במה שהיא עושה, הנקודה היחידה שרציתי להעלות היא שפיתון גם מאוד טובה במה שהיא עושה רק שהיא עושה זאת אחרת.

    ו-explicit זה אומר לא לקרוא את המחשבות של המשתמש, אם התנהגות יכולה להיות דו-משמעית, to err on the side of caution ולדרוש שהמשתמש יאמר בדיוק מה הוא רוצה לעשות. אין התנהגות סטנדרטית כאשר אתה עובר לשפת תיכנות אחרת גם אם מדובר ב"שפת סקריפט". לכל שפת תיכנות יש ההיסטוריה והעיצוב שלה, וגישה שהתפתחה בהתאם לבעיות שהיא שימשה לפתור.

    ובקשר לנקודה על תורשה מול API אחיד. יש לך המון ממשקים שונים בפיתון כמו indexing, with, iterators, reference, מילון, אורך וכו'… אם היית צריך להוריש מקלאס אב בכל פעם שרצית לתמוך בתכונה היו לך מצב שכל קלאס בסיסי צריך היה לרשת מהרבה אבות או מצב שיש לך מספר "אבות סטנדרטיים" שמכילים הרבה ממשקים שהקלאס שלך לא צריך. ואתה עדיין צריך לממש את המתודה שעושה את הפעולה. עם ממשקים, כל מה שצריך זה לממש מתודה אחת או שתיים והקלאס שלך תומך באותו ממשק בלי כל הזבל שמגיע עם subclassing. אני חושב שזה גישה יותר טובה, אבל לא בצורה משמעותית, כי שוב זה חוזר לנקודה שזה לא דברים שהם משמעותיים לדעתי. מה כן משמעותי זה כמה קל זה לממש רעיון או פיטצ'ר ובפיתון ברגע שאתה מכיר אותה אתה כותב במהירות המחשבה. זה קשה לומר את זה על שפה כמו C ולפעמים גם JS (כי רוב השימושים שלה הם בסביבה לא לינארית). את רובי אני לא מכיר כמעט בכלל, אבל מהמעט שהשתמשתי בה היא מאוד דומה לפיתון (ברמה הרעיונית).

    1. ik_5 מאת

      מצטער אבל אתה עדיין לא מספק הסבר.
      אני שומע המון דברים מסביב, אבל לא את ההגיון מאחוריהם.

      למשל מדוע יש מימוש של מתודת __len__ ופונקציה חיצונית שמשתמשת בה בשביל להציג את המידע הזה?

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

      קח למשל את vim, אתה לא צריך לדעת ולזכור את כל הפעולות שיש. אבל, הנה לוגיקה שאתה יכול לזכור, שתעזור לך עם הכל:
      יש לך כמות, אחריה יש פעולה, והדבר האחרון הוא פעולה. כלומר 10Fr, אומר שתעשה משהו 10 פעמים, אח"כ מה תעשה, ואז התנועה של זה.
      במקרה הזה, זה אומר לך 10 מופעים של r אחורה ועמוד עליו.

      הלוגיקה עוזרת להבין איך לחשוב בשפה. הבעיה היא שאתה ואנשים רבים אחרים שהגיבו לי על הפוסט (רובם בפרטי), אומרים שאני לא מבין, אבל לא יודעים להסביר מה אני לא מבין. אני שומע משפטים כמו "היא שפה strong typed". סבבה, אבל זו תכונה, זו לא לוגיקה. אז כאשר זו התשובה, מן הסתם אלך לשפות תכנות נוספות שהן כאלו, ואחפש לוגיקה זהה, אני לא אמצא, היות "פיתון היא לא Perl/Ruby/Javascript יש לה את המבנה וההגיון שלה".

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

להשאיר תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת /  לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת /  לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת /  לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת /  לשנות )

w

מתחבר ל-%s