روش‌هایی برای بهتر کد زدن در پایتون

امیرحسین بیگدلو 4 ماه قبل

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

 

وقتی سعی می کنید ثانیه ها یا حتی دقیقه ها را از زمان اجرا ذخیره کنید، یادآوری استراتژی هایی که ممکن است به شما کمک کند ، خوب است. استراتژی های موجود در این لیست می تواند به شما کمک کند تا برنامه های خود را در اسرع وقت بسازید.

 

برخی از موارد موجود در این لیست ممکن است برای شما واضح باشد ، اما برخی دیگر ممکن است کمتر آشکار باشند. برخی تأثیر زیادی بر اجرا خواهند داشت و برخی دیگر تأثیرات کوچکتر و ظریف تری خواهند داشت.

 

دوره پیشنهادی: دوره آموزش رایگان پایتون


 

1. از list comprehension استفاده کنید.

وقتی در پایتون کار می کنید ، حلقه ها رایج هستند. احتمالاً قبلاً با list comprehension آشنا شده اید. آنها راهی مختصر و سریع برای ایجاد لیست های جدید هستند.

 

اگر نمیدانید list comprehension چیست، میتوانید ویدیو آموزش list comprehension پایتون را ببینید.

 

به عنوان مثال ، فرض کنید می خواهید مکعب همه اعداد فرد را در یک محدوده مشخص پیدا کنید. با استفاده از حلقه for ، این کار ممکن است به این شکل باشد:

cube_numbers = []
  for n in range(0,10):
    if n % 2 == 1:
      cube_numbers.append(n**3)

 

در مقابل ، رویکرد list comprehension فقط یک خط است:

cube_numbers = [n**3 for n in range(1,10) if n%2 == 1]

 

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

 

 

 

2. فانکشن‌های داخل را به یاد داشته باشید.

پایتون با فانکشن‌های زیادی همراه است. شما می توانید کد با کیفیت بالا و کارآمد بنویسید، اما غلبه بر کتابخانه های داخلی دشوار است. اینها بهینه شده اند و به طور دقیق آزمایش شده اند. لیست برنامه های داخلی را بخوانید و بررسی کنید که آیا هر کدام از این قابلیت ها را در کد خود کپی می کنید یا خیر.

 

برای آشنایی عمیق با فانکشن‌های پایتون این ویدیو را ببینید.

 

3. از xrange بجای range استفاده کنید.

پایتون 2 از توابع ()range و xrange() برای تکرار حلقه ها استفاده کرد. تابع range همه اعداد موجود در محدوده را در حافظه ذخیره می کند و به صورت خطی بزرگ می شود. دومی ، xrange () ، شیء مولد را برگرداند. هنگام حلقه زدن با این شی ، اعداد فقط در صورت تقاضا در حافظه هستند.

 

import sys
numbers = range(1, 1000000)
print(sys.getsizeof(numbers))

 

این کد مقدار 8000064 را باز می گرداند، در حالی که همان محدوده اعداد با xrange مقدار 40 را برمی گرداند. اگر برنامه شما در پایتون 2 است ، تعویض این توابع می تواند تأثیر زیادی بر استفاده از حافظه داشته باشد. خبر خوب این است که پایتون 3 به طور پیش فرض عملکرد xrange () را پیاده سازی می کند. بنابراین ، در حالی که هیچ تابع xrange () وجود ندارد ، تابع () range قبلاً به این شکل عمل می کند.

 

 

 

4. generator خودتان را بسازید.

نکته قبلی به یک الگوی کلی برای بهینه سازی اشاره می کند - یعنی بهتر است در صورت امکان از ژنراتورها استفاده شود. اینها به شما امکان می دهد یک مورد را به طور همزمان برگردانید تا همه موارد را به طور همزمان. همانطور که گفته شد ، تابع xrange () یک مولد در پایتون 2 است ، و تابع range () در پایتون 3.

 

اگر با لیست ها کار می کنید ، در نظر داشته باشید که ژنراتور خود را بنویسید تا از این بارگذاری تنبل و بهره وری حافظه استفاده کنید. ژنراتورها هنگام خواندن تعداد زیادی پرونده بزرگ مفید هستند. پردازش تکه های واحد بدون نگرانی در مورد حجم فایل ها امکان پذیر است.

 

در اینجا مثالی است که ممکن است هنگام خزیدن وب به صورت بازگشتی استفاده کنید.

 

import requests
import re

def get_pages(link):
  pages_to_visit = []
  pages_to_visit.append(link)
  pattern = re.compile('https?')
  while pages_to_visit:
    current_page = pages_to_visit.pop(0)
    page = requests.get(current_page)
    for url in re.findall('<a href="([^"]+)">', str(page.content)):
      if url[0] == '/':
        url = current_page + url[1:]
      if pattern.match(url):
        pages_to_visit.append(url)
    yield current_page
webpage = get_pages('http://www.example.com')
for result in webpage:
  print(result)

 

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

 

اگر نمیدانید generator چیست، پیشنهاد میکنیم ویدیو آموزش generator در پایتون را ببینید.

 

 

 

5. از in استفاده کنید.

برای بررسی اینکه آیا عضویت در یک لیست وجود دارد ، به طور کلی سریعتر از کلمه کلیدی "in" استفاده می شود.

for name in member_list:
  print('{} is a member'.format(name))

 

ویدیو پیشنهادی: ویدیو آموزش آبجکت های container در پایتون

 

 

6. در زمان import کردن تنبل باشید.

وقتی شروع به یادگیری پایتون کردید ، احتمالاً import کردن همه ماژول هایی که در ابتدای برنامه خود استفاده می کنید ، توصیه شده است. شاید هنوز آنها را به ترتیب حروف الفبا مرتب کنید.

 

این رویکرد به راحتی می تواند پیگیری کند که برنامه شما چه وابستگی هایی دارد. با این حال ، عیب آن این است که تمام importهای شما هنگام راه اندازی بارگیری می شود.

 

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

 

 

 

7. از set و union استفاده کنید.

من قبلاً چند بار در این لیست به حلقه ها اشاره کرده ام. اکثر کارشناسان موافقند که حلقه زیاد، فشار غیر ضروری به سرور شما وارد می کند. به ندرت کارآمدترین روش است.

 

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

 

a = [1,2,3,4,5]
b = [2,3,4,5,6]

overlaps = []
for x in a:
  for y in b:
    if x==y:
      overlaps.append(x)

print(overlaps)

 

با این کار لیست [2 ، 3 ، 4 ، 5] چاپ می شود. تعداد مقایسه در اینجا بسیار زیاد و بسیار سریع خواهد شد.

 

رویکرد دیگر این خواهد بود:

a = [1,2,3,4,5]
b = [2,3,4,5,6]

overlaps = set(a) & set(b)

print(overlaps)

 

با این کار دیکشنری {2 ، 3 ، 4 ، 5} چاپ می شود. شما به فانکشن‌های داخلی تکیه کرده اید و در نتیجه سرعت و حافظه زیادی را تجربه می کنید.

 

 

 

8. از انتساب چندگانه استفاده کنید.

 

پایتون راهی زیبا برای اختصاص مقادیر چند متغیر دارد:

first_name, last_name, city = "Kevin", "Cunningham", "Brighton"

 

می توانید از این روش برای جابجایی مقادیر متغیرها استفاده کنید:

x, y = y, x

 

این روش بسیار سریعتر و تمیزتر از موارد زیر است:

temp = x 
x = y
y = temp

 

 

 

9. از متغیرهای global استفاده نکنید.

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

 

 

 

10. از join برای چسباندن چند string استفاده کنید.

در پایتون ، می توانید رشته ها را با استفاده از "+" به هم متصل کنید. با این حال ، رشته ها در پایتون تغییر ناپذیر هستند و عملیات "+" شامل ایجاد یک رشته جدید و کپی محتوای قدیمی در هر مرحله است. یک روش کارآمدتر این است که از ماژول آرایه برای تغییر کاراکترهای جداگانه و سپس استفاده از تابع join () برای ایجاد مجدد رشته نهایی خود استفاده کنید.

 

new = "This" + "is" + "going" + "to" + "require" + "a" + "new" + "string" + "for" + "every" + "word"
print(new)


# OUTPUT
Thisisgoingtorequireanewstringforeveryword

 

یا روش دیگری که میتوانید استفاده کنید:

new = " ".join(["This", "will", "only", "create", "one", "string", "and", "we", "can", "add", "spaces."])
print(new)


# OUTPUT
This will only create one string and we can add spaces.

 

برای آموزش بیشتر در مورد فانکشن‌های join و split میتوانید این ویدیو را مشاهده کنید.

 

 

11. همیشه از آخرین نسخه پایتون استفاده کنید.

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

 

 

 

12. برای حلقه نامتناهی از "while 1" استفاده کنید.

اگر به socket گوش می دهید ، احتمالاً می خواهید از یک حلقه بی نهایت استفاده کنید. مسیر عادی برای دستیابی به این هدف استفاده از True است. این کار می کند ، اما با استفاده از 1 می توانید همان اثر را کمی سریعتر به دست آورید. این یک عملیات تک جهشی است ، زیرا یک مقایسه عددی است.

 

 

 

13. روش دیگری را امتحان کنید.

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

 

برای درک بهتر، میتوانید آموزش الگوریتم‌نویسی در پایتون را ببینید.

 

 

 

14. سریع خارج شوید.

سعی کنید یک تابع را به محض این که می دانید نمی تواند کار معنی داری انجام دهد را ترک کنید. با این کار تورفتگی برنامه شما کاهش می یابد و خوانایی آن بیشتر می شود. همچنین به شما امکان می دهد از دستورات تو در تو جلوگیری کنید.

 

if positive_case:
  if particular_example: 
    do_something
else:
  raise exception

 

می توانید ورودی را به چند روش قبل از انجام اقدامات خود آزمایش کنید. رویکرد دیگر این است که exception را زودتر مطرح کرده و اقدام اصلی را در قسمت دیگر حلقه انجام دهید.

if not positive_case:
  raise exception
if not particular_example:
  raise exception
do_something 

 

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

 

 

 

15. ماژول itertools را یاد بگیرید.

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

 

برای آموزش ماژول itertools روی این لینک کلیک کنید.

 

فرض کنید می خواهید همه ترکیب‌های [“Alice”, “Bob”, “Carol”] را ایجاد کنید.

import itertools
iter = itertools.permutations(["Alice", "Bob", "Carol"])
list(iter)


# OUTPUT
[('Alice', 'Bob', 'Carol'),
 ('Alice', 'Carol', 'Bob'),
 ('Bob', 'Alice', 'Carol'),
 ('Bob', 'Carol', 'Alice'),
 ('Carol', 'Alice', 'Bob'),
 ('Carol', 'Bob', 'Alice')]

 

 

 

16. سیستم کش دکوریتور‌ها را امتحان کنید.

Memoization نوع خاصی از ذخیره سازی است که سرعت اجرای نرم افزار را بهینه می کند. اساساً ، یک کش نتایج عملیات را برای استفاده بعدی ذخیره می کند. نتایج را می توان صفحات وب یا نتایج محاسبات پیچیده ارائه داد.

 

می توانید خودتان این کار را با محاسبه عدد 100 فیبوناچی امتحان کنید. اگر با این اعداد برخورد نکرده اید ، هر یک مجموع دو عدد قبلی است. فیبوناچی ریاضیدان ایتالیایی بود که کشف کرد این اعداد در بسیاری از نقاط جمع شده است. از تعداد گلبرگهای روی یک گل تا ساقهای روی حشرات یا شاخه های روی درخت ، این اعداد در طبیعت رایج هستند. چند مورد اول 1 ، 1 ، 2 ، 3 ، 5 است.

 

def fibonacci(n):
  if n == 0: # There is no 0'th number
    return 0
  elif n == 1: # We define the first number as 1
    return 1
  return fibonacci(n - 1) + fibonacci(n-2)

 

وقتی از این الگوریتم برای پیدا کردن شماره 36 فیبوناچی، استفاده کردم ، رایانه من به نظر می رسید که قرار است بترکد! محاسبه پنج ثانیه طول کشید و (در صورت کنجکاوی) پاسخ 14،930،352 بود.

 

با این حال ، هنگام کش از کتابخانه استاندارد، همه چیز تغییر می کند. فقط چند خط کد نیاز دارد.

import functools

@functools.lru_cache(maxsize=128)
def fibonacci(n):
  if n == 0:
    return 0
  elif n == 1:
    return 1
  return fibonacci(n - 1) + fibonacci(n-2)

 

در پایتون ، یک تابع دکوریتور یک تابع دیگر را می گیرد و عملکرد آن را گسترش می دهد. این توابع را با نماد @ نشان می دهیم. در مثال بالا ، من از تابع functools.lru_cache استفاده شده توسط ماژول functools استفاده کرده ام. من حداکثر تعداد مواردی را که باید در حافظه پنهان ذخیره کنم به عنوان استدلال تصویب کرده ام. اشکال دیگری برای ذخیره سازی تزئین کننده وجود دارد ، از جمله نوشتن خودتان ، اما این سریع و داخلی است. چقدر سریع؟ خوب ، این بار محاسبه 0.7 ثانیه به طول انجامید ، و اطمینان بخش ، پاسخ یکسان بود.

 

 

 

17. از کلید‌ها برای مرتب کردن استفاده کنید.

اگر چند نمونه از مرتب سازی را جستجو کنید ، بسیاری از نمونه های کدی که پیدا می کنید کار می کنند اما ممکن است قدیمی باشند. اغلب این نمونه ها مرتب سازی سفارشی و زمان زیادی را در راه اندازی و انجام مرتب سازی ایجاد می کنند. بهترین راه برای مرتب سازی موارد استفاده از کلیدها و روش مرتب سازی sort() در صورت امکان است. قبلاً اشاره کردم که فانکشن‌های داخلی به طور کلی سریعتر هستند و این یکی از آن زمانها است.

import operator
my_list = [("Josh", "Grobin", "Singer"), ("Marco", "Polo", "General"), ("Ada", "Lovelace", "Scientist")]
my_list.sort(key=operator.itemgetter(0))
my_list



‌# OUTPUT
[('Ada', 'Lovelace', 'Scientist'),
 ('Josh', 'Grobin', 'Singer'),
 ('Marco', 'Polo', 'General')]

 

 

به راحتی می توانید با کلید دوم مرتب کنید ، مانند این:

my_list.sort(key=operator.itemgetter(1))
my_list


# OUTPUT
[('Josh', 'Grobin', 'Singer'),
 ('Ada', 'Lovelace', 'Scientist'),
 ('Marco', 'Polo', 'General')]

 

در هر مورد ، فهرست بر اساس index که به عنوان بخشی از آرگومان کلیدی انتخاب کرده اید مرتب شده است. این رویکرد با اعداد و رشته کار می کند و قابل خواندن و سریع است.

 

 

نتیجه گیری

امیدوارم برخی از این نکات به اجرای سریع کد شما کمک کرده و به شما این امکان را می دهد که از برنامه خود عملکرد پایتون بهتری دریافت کنید.

 

مطالب مشابه



مونگارد