שפת פייתון ידועה בזכות גמישותה הרבה והתחביר הפשוט שלה, אך לצד אלו קיימים גם טריקים פחות מוכרים שיכולים לחסוך ולפשט קוד רב. אספתי עבורכם את אלו שנראו לי החשובים והשימושיים ביותר.
Dict Comprehension
אחת מפניני התחביר המוכרים ביותר של python היא list comprehension:
>>> [x ** 2 for x in range(10) if x != 4]
[0, 1, 4, 9, 25, 36, 49, 64, 81]
אך טריק פחות ידוע, בעיקר כי קיים רק בגרסאות האחרונות, הוא שאפשר לעשות אותו דבר עם מילון:
>>> {x: x ** 2 for x in range(5) if x != 4}
{0: 0, 1: 1, 2: 4, 3: 9}
Argument Unpacking
בדומה ל-params בשפת C#, גם פייתון תומכת בהמרת הפרמטרים של פונקצייה למערך, ואת הפרמטרים השמיים (keyword params) למילון. זה נראה כך:
def func(regular_arg, *args, **kwargs):
print regular_arg, args, kwargs
כשנקרא לפונקציה, args יהיה מערך של כל הפרמטרים הרגילים, פרט לראשון שמועבר כ-regular arg, ובנוסף kwargs יהיה מילון שיכיל את כל הפרמטרים שהועברו לפי שם.
>>> func(1, 2, 3, a=1, b=2)
1 (2, 3) {'a': 1, 'b': 2}
הפונקציה enumerate
לפני שהכרתי את הפונקציה enumerate, לעיתים קרובות הייתי כותב קוד כזה:
i = 0
for x in my_list:
print i, some_processing(x)
i += 1
הפונקציה enumerate מקבלת iterable כמו רשימה או tuple, ומחזירה iterable אחר בו כל איבר הוא tuple המכיל שני איברים: מספר רץ, ואיבר מתוך ה-iterable המקורי. בעזרת הפונקציה ניתן לפשט את הקוד:
for i, x in enumerate(my_list):
print i, some_processing(x)
IPython
אמנם לא מדובר בחלק מהשפה עצמה, אך חבילת IPython מציעה shell נוח הרבה יותר מה-interactive interpreter של פייתון. בין תכונותיו הרבות:
- Ctrl-C ו-Ctrl-V עובדים
- השלמה אוטומטית באמצעות מקש TAB
- צביעת הפלט
- זיכרון של פקודות מריצות קודמות באמצעות מקש חץ למעלה
- אפשרות לביצוע embed בתוכניות שלנו ליצירת shell נוח
ניתן להתקין IPython באמצעות pip:
pip install ipython
If טרינארי
במקום לכתוב:
if something:
x = "yes"
else:
x = "no"
ניתן לכתוב פשוט:
x = "yes" if something else "no"
הפונקציה get של מילון
לפעמים נרצה להוציא ערך ממילון, ואם הוא לא קיים להחזיר ערך ברירת מחדל. השיטה הנאיבית היא:
x = "default"
if key in my_dict:
x = my_dict[key]
בדיוק לשם כך קיימת הפונקציה get של מילון:
x = my_dict.get(key, "default")
במידה ולא נעביר ערך ברירת מחדל, הפונקציה תחזיר None אם הערך לא מופיע במילון.
New Style Formatting
כמעט כולם מכירים את האופרטור % המבצע string formatting בדומה לפונקציה printf בשפת c:
"My %s is almost %u years old" % ("grandma", 22)
שיטה נוספת, חדשה יותר ומוכרת פחות לביצוע אותה פעולה היא הפונקציה format של מחרוזות:
"My {relative} is almost {years} years old".format(
relative = "son", years = 120)
The Zen of Python
מתוך ה-interpreter הריצו את השורה הבאה:
import this
גנרטורים
התחביר של גנרטורים (generators) דומה לזה של list comprehension, אך עם סוגריים רגילים במקום סוגריים מרובעים:
(x ** 2 for x in range(3))
ההבדל הוא שגנרטורים לא בונים את התוצאה מיד, אלא מחכים עד איטרציה עליהם. כמו כן ניתן לבצע עליהם איטרציה רק פעם אחת:
>>> generator = (x ** 2 for x in range(3))
>>> generator
<generator object <genexpr> at 0x0000000002B0CF78>
>>> generator.next()
0
>>> generator.next()
1
>>> for x in generator: print x
...
4
>>> generator.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
ניתן להשתמש בגנרטורים כדי לחסוך זיכרון, למשל אם רוצים לרוץ על איטרטור אחר עם הרבה איברים, לשמור את התוצאה של כל איבר ולשחרר את הזיכרון שלה.
List Comprehension מקונן
אמנם התחביר שלו לא הכי אינטואיטיבי, אבל לפעמים הוא יכול לחסוך הרבה קוד:
[(i,j) for i in range(3) for j in range(i)]
המשתנה _ ב-interpreter
אם הרצנו ביטוי ב-interpreter, ושכחנו לשים את התוצאה במשתנה, ניתן לגשת לתוצאה האחרונה במשתנה _ (קו תחתון):
>>> expensive_processing("bla")
'ffa6706ff2127a749973072756f83c532e43ed02'
>>> _
'ffa6706ff2127a749973072756f83c532e43ed02'
אופרטורי השוואה משורשרים
בפייתון התחביר הבא הוא חוקי:
>>> 10 < x < 11
False
>>> 10 < x < y < 11
False
>>> 1 >= x < 2
True
פרמטרי ברירת מחדל מצביעים תמיד לאותו אובייקט
כאשר קובעים פרמטרי ברירת מחדל לפונקציה, צריך להיזהר עם כאלו שניתנים לשינוי (mutable), מכיוון ששינוי שלהם למעשה ישנה את פרמטר ברירת המחדל:
>>> def func(x=[]):
... x.append("wa")
... print x
...
>>> foo()
["wa"]
>>> foo()
["wa", "wa"]
>>> foo()
["wa", "wa", "wa"]
סיכום נחמד ! שמרתי לעצמי ….
סיכום מעולה!
מכיל טריקים שימושיים מאוד, חידשת לי בטיפ האחרון (פרמטרי ברירת מחדל מצביעים תמיד לאותו אובייקט)
אתה צריך לתקן משהו אחד –
הפרמטרים והprint לא שווים פה, אתה משתמש בregular_arg וregular_args
def func(regular_arg, *args, **kwargs):
print regular_args, args, kwargs
תוקן. תודה רבה 🙂
אפשר להוסיף טריק חשוב נוסף?
a = 10
b = ""
c = b or a
הרעיון הוא שאפשר להשתמש במשתנה השני אם הראשון שלילי בלי להשתמש בif
מועיל מאוד, תודה!
האם אפשר פוסט על קימפול פייתון, מה האפשרויות שיש כיום, מתי משתמשים ב-cython וכו'?
תודה יוני 🙂
רשמתי לעצמי, אשתדל לכתוב פוסט על הנושא בעתיד.
בינתיים אציין שקימפול python נועד בעיקר לשיפור ביצועים, מכיוון ש-python היא שפת סקריפט (מורצת ע"י interpreter ולא מתקמפלת לשפת מכונה) ואיטית יותר מאשר שפות תכנות מתקמפלות. כאשר חשוב לנו מאוד שהקוד ירוץ מהר, למשל כאשר מבצעים חישובים מתמטיים רבים, יש כמה אפשרויות:
– להשתמש בספריות python הכתובות ב-C כמו Numpy, SciPy, SciKit-Learn וכד'
– להריץ את הקוד בעזרת PyPy
– לקמפל את הקוד בעזרת Cython ודומיו
– לכתוב פלאגינים ב-C ולייצר להם bindings ל-Python.
לכל שיטה הייתרונות והחסרונות שלה. אני ממליץ להתחיל עם השיטה הראשונה, כך ממשיכים לכתוב python סטנדרטי, ובמידה והביצועים עדיין לא מספקים להמשיך לשיטות הבאות.
מקווה שעזרתי 🙂
תודה צח, אשמח לקרוא בעתיד איך אתה נעזר ב-scipy וכו' 🙂