1- تورفتگی باید چهار فاصله(space) باشد و  تب (tab)نباشد.

این اشتباهی است که اغلب به صورت تصادفی انجام می‌شود، زیرا تشخیص آن در بسیاری از ویرایشگرهای متن یا IDE دشوار است. هر ویرایشگر/IDE تنظیماتی در نوار منوی بالایی برای تورفتگی خواهد داشت، که در آن می‌توانید گزینه «تورفتگی با استفاده از 4 فاصله» یا یک گزینه مشابه را انتخاب کنید تا بتوانید از کلید تب استفاده کنید. بسیاری از اوقات این اشتباه تنها پس از رسیدن به تولید یا در حین ادغام درخواست های کشش (mergin pool) در git باعث ایجاد مشکل می شود.

2 - همیشه مطمئن شوید که نام متغیرها کلمات کلیدی رزرو شده نیستند.

یکی دیگر از اشتباهات رایج استفاده از کلمات کلیدی رزرو شده مانند نام توابع داخلی به عنوان نام متغیر است که احتمالاً می تواند باعث رفتار غیرمنتظره شود و زمان زیادی را در اشکال زدایی صرف کند. مثال: dict = {1: 2، 'a': 1}

3 - عبارت lambda را به یک متغیر اختصاص ندهید.

این هیچ مشکل در رفتار برنامه ایجاد نمی کند، اما به نوعی هدف لامبدا را شکست می دهد، بنابراین بخشی از استانداردهای کدگذاری PEP8 است.

برای مثال، از نوشتن تابع لامبدای زیر باید اجتناب شود و در عوض به عنوان یک تابع عادی نوشته شود.

res = lambda x: x % 2 == 0

اما چرا؟ زیرا تابع لامبدا یک تابع ناشناس است که به این معنی است که نباید نام (شناسه) داشته باشد. منظور این است که در عبارات دیگری مانند

list(filter(lambda x: (Counter(str) == Counter(x)), my_list))

4 - آرگومان های پیش فرض قابل تغییر را به توابع اضافه نکنید.

در پایتون، آرگومان های پیش فرض در تعریف تابع (فقط یک بار) و نه هر بار در طول فراخوانی تابع ارزیابی می شوند.

# bad practice def append_to(element, to=[]):
    to.append(element)
    return tomy_list = append_to("a")
print(my_list)Output
["a"] my_second_list = append_to("b")
print(my_second_list)Output
["a", "b"]# good practice def append_to(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

5 - همیشه یک بازگشت پیش فرض برای توابع داشته باشید و یا از عبارات بازگشت صریح برای همه سناریوهای ممکن اطمینان حاصل کنید.

زمانی که تابعی بدون دستور بازگشت صریح برمی گردد، پایتون یک شی None را برمی گرداند. این ممکن است به این دلیل رخ دهد که هیچ عبارت بازگشتی مشخص نشده باشد یا هیچ سناریوهای تعریف شده بازدهی مطابقت نداشته باشند در حالی که بازگشت پیش فرض ندارند. اگر کدی که تابع را فراخوانی می کند انتظار یک نوع داده عدد صحیح را مانند کد زیر داشته باشد، با خطا مواجه می شود.

def test_func(a):
   if a < 10:
   return a
a = test_func(11) * 2TypeError: unsupported operand type(s) for *: ‘NoneType’ and ‘int’

یا باید یک دستور پیش‌فرض که مقدار نوع داده منطبق را برمی‌گرداند اضافه شود یا باید در دستور فراخوانی تابع مدیریت شود.

def test_func(a):
   if a < 10:
        return a
    return 0Orval = test_func(11)
if val != None:
    a = val * 2

6 - اجتناب عبارات با جزییات بی نظم

عبارات جنریک عام باید بعد از تمام عبارات خاص  آمده باشند.

# Bad codetry:
    5 / 0
except Exception as e:
    print("Exception")
# unreachable code!
except ZeroDivisionError as e:
    print("ZeroDivisionError")
# Right codetry:
    5 / 0
except ZeroDivisionError as e:
    print("ZeroDivisionError")
except Exception as e:
    print("Exception")

7 - عدم دسترسی به اعضای محافظت شده از خارج از کلاس.

همانطور که همه ما می دانیم، عملا هیچ متغیر خصوصی یا محافظت شده ای وجود ندارد، بلکه با استفاده از قرارداد نامگذاری پیشوند زیر خط دوگانه پیاده سازی شده است. بنابراین از نظر فنی امکان دسترسی به این متغیرها در خارج از کلاس یا محدوده مورد انتظار وجود دارد، اما چیزی که باید به عنوان بهترین عمل از آن اجتناب شود.

دلایل:

  • اگر کد توسط شخص دیگری نوشته شده باشد، باید به دلیلی محدوده محدودی به آن داده شده باشد.
  • اگر عضو محافظت شده ای را تعریف می کنید که قصد دارید از آن خارج از محدوده استفاده کنید، نیازی به آن نخواهد بود و سوء استفاده از مفهوم خواهد بود.

8 - استفاده کافی از توضیحات درون کد.

این معمولاً یک اشتباه در جامعه توسعه دهندگان صرف نظر از زبان برنامه نویسی است. برخی از دلایلی که افراد از افزودن/ویرایش نظرات خودداری می کنند عبارتند از:

  • توسعه دهنده فرض می کند که او تنها فردی است که روی آن پروژه کار می کند.
  • یک تغییر در وسط یک رفع اشکال با اولویت بالا ایجاد شده و نیاز به بروزرسانی  توضیحات پس از ویرایش در اولویت توسعه دهنده نمیباشد. در این مورد، من پیشنهاد می‌کنم پس از اتمام اصلاح، دوباره برگردید و نظر را به‌روزرسانی کنید.
  • منطق این کار از نظر توسعه دهنده مهم نیست و سهل تنگاری میکند.
  • در کد تحویل گرفته شده هیچ توضیحاتی وجود نداشته و توسعه دهنده جدید همین کار را ادامه میدهد.
  • بخشی از کد به‌روزرسانی یا حذف شده، اما کامنتی که آن را توضیح می‌داد در بالای صفحه قرار داشت، بنابراین از قلم می افتد.

دلیل هر چه باشد، توسعه‌دهنده/تیم باید راه‌حل‌هایی ارائه دهد تا اطمینان حاصل شود که نظرات به درستی اضافه، ویرایش یا حذف می‌شوند. چند راه حل عبارتند از:

  • بررسی نظرات در حین تأیید تحویل کد.
  • بازبینی منظم کد توسط خود، همتایان یا مدیر
  • حفظ چک لیست برای اطمینان از آن قبل از هر تعهد یا استقرار نرم افزار

9 - استفاده از آیتم های نوع دار به جای استفاده از ایندکس ها در دستورات تکرار.

اشتباهی که اغلب توسط افرادی که از زبان های برنامه نویسی دیگربه پایتون مهاجرت میکنند مرتکب می شوند این است که با استفاده از ایندکس روی فهرست یا هر دنباله ای حلقه می زنند در حالی که پایتون از تکرار مستقیماً روی عناصر موجود در آن پشتیبانی می کند.

a_list = [1, 2, 3] 
# bad practice 
for index in range(len(a_list)):
    item = a_list[index]
    call_func(item)
# good practice
for item in a_list:
    call_func(fruit)

10 - انتقال نمونه/کلاس مرجع به عنوان اولین آرگومان به یک متد.

پایتون به تنهایی ارجاعات را به یک نمونه یا اشیاء کلاس به صورت داخلی منتقل نمی کند. بنابراین اگر هر یک از اعضای کلاس - متدها یا متغیرهای دیگر باید در متد دسترسی داشته باشند، ارجاع به کلاس یا نمونه باید به صراحت در کد ارسال شود.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.area = width * height
    # missing first argument "self"
    def area():
        # self is undefined here
        return self.area

11 - هنگام داشتن else درون یک حلقه یک عبارت break اضافه کنید.

def check_for_even_num(ip_list):
    for item in ip_list:
        if item % 2 == 0:
            print("This list contains an even number.")
        else:
            print("This list has no even numbers.")check_for_even_num(range(5)

خروجی اشتباه

This list contains an even number.
This list has no even numbers.

کد صحیح

def check_for_even_num(ip_list):
    for item in ip_list:
        if item % 2 == 0:
            print("This list contains an even number.")
            # added break statement here
            return
        
    print("This list has no even numbers.")check_for_even_num(range(5))Output
This list contains an even number.

12 - تعریف تک خطی عناصر برای خوانایی بیشتر.

# bad practice
items = [1, 2, 3]
item1 = items[0]
item2 = items[1]
item3 = items[2]


# good practice
items = [4, 7, 18]
item1, item2, item3 = items

در کد اول، پایتون باید برای هر آیتم روی لیست تکرار کند در حالی که در کد دوم در یک تکرار انجام می‌شود. این بسیار موثر خواهد بود به خصوص زمانی که لیست ای که در حال تعریف آن هستید بزرگ باشد.

13 - از برگرداندن انواع مختلف در یک تابع خودداری کنید.

این مشابه همان چیزی است که در بالا در افزودن یک دستور پیش‌فرض به آن اشاره کردم، تا نوع بازگشتی دستور پیش‌فرض با نوع مورد انتظار مطابقت داشته باشد. در یک تابع، این یک عمل بد و همچنین پیچیدگی ناخواسته در داشتن انواع برگشت های متعدد است. اگر کد شما ایجاب می کند، احتمالاً لازم است دوباره نحوه بازنویسی یا تقسیم تابع را دوباره بررسی کنید. اگر فوراً این کار را انجام ندهید، مطمئناً در آینده باعث ایجاد نوعی باگ یا مشکل در اشکال زدایی یا آزمایش می شود.

14 - برای بازیابی مقادیر از دیکشنری از «get» استفاده کنید.

# good practice
sample_dict = {"message": "Hello, World!"}
data = sample_dict.get("message", "")
print(data)Hello, World!
# bad practice 1
print(sample_dict["message"]) 
# throws error if key not present
# bad practice 2
if "message" in sample_dict.keys()
    print(sample_dict["message"]) 
# two dict loops, not efficient

15 - از collections.defaultdict هنگام ایجاد دیکشنری ها و مجموعه ها استفاده کنید که اگر کلید از قبل موجود نیست، عناصر آن باید با مقدار پیش‌فرض مقداردهی اولیه شوند.

برای درک بهتر به مثال زیر توجه کنید. یک لیست "s" با لیستی از تاپل ها با رنگ به عنوان عنصر اول یک شرکت خودروسازی به عنوان عنصر دوم وجود دارد. اگر نیاز به ایجاد دیکت ‘d’ با رنگ به عنوان کلید و لیست شرکت های خودروسازی با آن رنگ داشته باشیم و آن را مرتب کنیم، می توانیم از پیش فرض مانند کد زیر استفاده کنیم و سپس آن را مرتب کنیم.

s = [('yellow', 'lamborghini'), ('blue', 'aston martin'), ('yellow', porsche), ('blue', 'BMW'), ('red', 'Ferrari')]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> sorted(d.items())
[('blue', ['aston martin', 'BMW']), ('red', ['Ferrari']), ('yellow', ['lamborghini', 'porsche'])]

بهترین روش های دیگری که در مورد آنها می دانید چیست؟ در نظرات به من اطلاع دهید!!

 

 

منبع : medium.com