Python tricks

12 טריקים שכל מפתח python חייב להכיר

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

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"]

8 תגובות בנושא “12 טריקים שכל מפתח python חייב להכיר”

  1. סיכום מעולה!
    מכיל טריקים שימושיים מאוד, חידשת לי בטיפ האחרון (פרמטרי ברירת מחדל מצביעים תמיד לאותו אובייקט)

  2. אתה צריך לתקן משהו אחד –
    הפרמטרים והprint לא שווים פה, אתה משתמש בregular_arg וregular_args
    def func(regular_arg, *args, **kwargs):
    print regular_args, args, kwargs

  3. אפשר להוסיף טריק חשוב נוסף?

    a = 10
    b = ""
    c = b or a

    הרעיון הוא שאפשר להשתמש במשתנה השני אם הראשון שלילי בלי להשתמש בif

    1. תודה יוני :)
      רשמתי לעצמי, אשתדל לכתוב פוסט על הנושא בעתיד.
      בינתיים אציין שקימפול python נועד בעיקר לשיפור ביצועים, מכיוון ש-python היא שפת סקריפט (מורצת ע"י interpreter ולא מתקמפלת לשפת מכונה) ואיטית יותר מאשר שפות תכנות מתקמפלות. כאשר חשוב לנו מאוד שהקוד ירוץ מהר, למשל כאשר מבצעים חישובים מתמטיים רבים, יש כמה אפשרויות:
      – להשתמש בספריות python הכתובות ב-C כמו Numpy, SciPy, SciKit-Learn וכד'
      – להריץ את הקוד בעזרת PyPy
      – לקמפל את הקוד בעזרת Cython ודומיו
      – לכתוב פלאגינים ב-C ולייצר להם bindings ל-Python.
      לכל שיטה הייתרונות והחסרונות שלה. אני ממליץ להתחיל עם השיטה הראשונה, כך ממשיכים לכתוב python סטנדרטי, ובמידה והביצועים עדיין לא מספקים להמשיך לשיטות הבאות.
      מקווה שעזרתי :)

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים