کدنویسی تمیز در پایتون: چگونه کدی کارآمد در پایتون بنویسیم؟
وقتی تازه شروع به یادگیری پایتون میکنید، اولویت اصلی شما این است که کدتان درست کار کند. اما با پیشرفت بهعنوان یک توسعهدهنده، علاوه بر درستی، به کارآمدی کد هم اهمیت خواهید داد. کد کارآمد سریعتر اجرا میشود، حافظه کمتری مصرف میکند و با دادههای بزرگتر بهتر مقیاسپذیر است. خبر خوب این است که برای نوشتن کد کارآمد در پایتون نیازی به سالها تجربه ندارید. با چند تکنیک ساده، حتی اگر مبتدی باشید، میتوانید کدنویسی تمیز در پایتون را اجرا کنید.
در این مقاله، تکنیکهای عملی برای بهبود کارایی کد و کدنویسی تمیز در پایتون را بررسی میکنیم. برای هر تکنیک، مقایسهای واضح بین روش ناکارآمد و روش کارآمدتر ارائه میشود.
فهرست مطالب
1- از توابع داخلی به جای پیادهسازی دستی استفاده کنید
پایتون توابع داخلی زیادی دارد که برای انجام کارهای رایج بهینهسازی شدهاند.
به جای این:
def process_sales_data(sales):
highest_sale = sales[0]
for sale in sales:
if sale > highest_sale:
highest_sale = sale
total_sales = 0
for sale in sales:
total_sales += sale
return highest_sale, total_sales, total_sales / len(sales)
این روش دو بار لیست را پیمایش میکند که ناکارآمد است.
این کار را انجام دهید:
def process_sales_data(sales):
return max(sales), sum(sales), sum(sales) / len(sales)
این روش از توابع داخلی max() و sum() استفاده میکند که برای این عملیاتها بهینه شدهاند. این کد نهتنها سریعتر است (بهویژه برای دادههای بزرگ)، بلکه خواناتر و کمتر مستعد خطاست.
نکته: هرگاه خواستید حلقهای برای عملیات رایج بنویسید، بررسی کنید آیا تابع داخلیای وجود دارد که کار را بهتر انجام دهد.
۲. از List Comprehension استفاده کنید، اما خوانا نگهش دارید
تکنیک List Comprehension راهی مختصر و اغلب سریعتر برای ایجاد لیستها از دادههای موجود است.
به جای این:
def get_premium_customer_emails(customers):
premium_emails = []
for customer in customers:
if customer['membership_level'] == 'premium' and customer['active']:
email = customer['email'].lower().strip()
premium_emails.append(email)
return premium_emails
این روش با هر بار فراخوانی .append() سربار ایجاد میکند.
این کار را انجام دهید:
def get_premium_customer_emails(customers):
return [
customer['email'].lower().strip()
for customer in customers
if customer['membership_level'] == 'premium' and customer['active']
]
تکنیک List Comprehension کل عملیات را در یک خط بیان میکند، سریعتر اجرا میشود و خواناتر است.
نکته: اگر منطق پیچیده شد، برای وضوح از حلقه معمولی یا مراحل سادهتر استفاده کنید.
۳. از مجموعهها (Set) و دیکشنریها برای جستجوی سریع استفاده کنید
برای جستجوی سریع، مجموعهها و دیکشنریها به دلیل استفاده از جدول هش، بسیار کارآمدتر از لیستها هستند.
به جای این:
def has_permission(user_id, permitted_users):
for p_user in permitted_users:
if p_user == user_id:
return True
return False
permitted_users = [1001, 1023, 1052, 1076, 1088, 1095, 1102, 1109]
print(has_permission(1088, permitted_users))
این روش زمان خطی O(n) دارد.
این کار را انجام دهید:
def has_permission(user_id, permitted_users):
return user_id in permitted_users
permitted_users = {1001, 1023, 1052, 1076, 1088, 1095, 1102, 1109}
print(has_permission(1088, permitted_users))
با استفاده از مجموعه (Set)، جستجو در زمان ثابت O(1) انجام میشود. برای دادههای بزرگ، این روش بسیار سریعتر است.
۴. از ژنراتورها برای پردازش دادههای بزرگ استفاده کنید
برای دادههای بزرگ، بارگذاری همه چیز در حافظه میتواند برنامه را کند یا متوقف کند. ژنراتورها با تولید مقادیر بهصورت تکتک، حافظه را بهینه مصرف میکنند.
به جای این:
def find_errors(log_file):
with open(log_file, 'r') as file:
lines = file.readlines()
error_messages = []
for line in lines:
if '[ERROR]' in line:
timestamp = line.split('[ERROR]')[0].strip()
message = line.split('[ERROR]')[1].strip()
error_messages.append((timestamp, message))
return error_messages
این روش کل فایل را در حافظه بارگذاری میکند که برای فایلهای بزرگ مشکلساز است.
این کار را انجام دهید:
def find_errors(log_file):
with open(log_file, 'r') as file:
for line in file:
if '[ERROR]' in line:
timestamp = line.split('[ERROR]')[0].strip()
message = line.split('[ERROR]')[1].strip()
yield (timestamp, message)
این روش با استفاده از ژنراتور، خط به خط پردازش میکند و حافظه کمی مصرف میکند.
۵. عملیاتهای سنگین را در حلقهها تکرار نکنید
عملیاتهای سنگین که به متغیر حلقه وابسته نیستند، باید خارج از حلقه انجام شوند.
به جای این:
import re
from datetime import datetime
def find_recent_errors(logs):
recent_errors = []
for log in logs:
timestamp_pattern = re.compile(r'\[(.*?)\]')
timestamp_match = timestamp_pattern.search(log)
if timestamp_match and '[ERROR]' in log:
log_time = datetime.strptime(timestamp_match.group(1), '%Y-%m-%d %H:%M:%S')
current_time = datetime.now()
time_diff = (current_time - log_time).total_seconds() / 3600
if time_diff <= 24:
recent_errors.append(log)
return recent_errors
این روش دو عملیات سنگین (کامپایل regex و گرفتن زمان فعلی) را در هر تکرار انجام میدهد.
این کار را انجام دهید:
import re
from datetime import datetime
def find_recent_errors(logs):
recent_errors = []
timestamp_pattern = re.compile(r'\[(.*?)\]')
current_time = datetime.now()
for log in logs:
timestamp_match = timestamp_pattern.search(log)
if timestamp_match and '[ERROR]' in log:
log_time = datetime.strptime(timestamp_match.group(1), '%Y-%m-%d %H:%M:%S')
time_diff = (current_time - log_time).total_seconds() / 3600
if time_diff <= 24:
recent_errors.append(log)
return recent_errors
این روش عملیاتهای سنگین را یک بار خارج از حلقه انجام میدهد و کارایی را بهبود میبخشد.
۶. از += برای رشتهها در حلقهها استفاده نکنید
استفاده از += برای ساخت رشتهها در حلقه ناکارآمد است، زیرا رشتهها در پایتون غیرقابل تغییر هستند و هر بار یک رشته جدید ایجاد میشود.
به جای این:
def generate_html_report(data_points):
html = "Data Report
"
for point in data_points:
html += f"- {point['name']}: {point['value']} ({point['timestamp']})
"
html += "
"
return html
این روش با هر += یک رشته جدید ایجاد میکند که هزینهبر است.
این کار را انجام دهید:
def generate_html_report(data_points):
parts = ["Data Report
"]
for point in data_points:
parts.append(f"- {point['name']}: {point['value']} ({point['timestamp']})
")
parts.append("
")
return "".join(parts)
این روش با جمعآوری تکههای رشته در یک لیست و اتصال نهایی، کارایی را افزایش میدهد.
جمعبندی
نوشتن کد کارآمد در پایتون نیازی به دانش پیشرفته ندارد. کافی است تکنیکهای مناسب را در موقعیتهای رایج به کار ببرید:
- استفاده از توابع داخلی به جای پیادهسازی دستی
- استفاده از List Comprehension برای تبدیلهای شفاف و کارآمد
- انتخاب ساختار داده مناسب (مجموعهها و دیکشنریها) برای جستجو
- استفاده از ژنراتورها برای پردازش دادههای بزرگ
- انتقال عملیاتهای ثابت به خارج از حلقهها
- ساخت رشتهها با استفاده از لیست و اتصال نهایی
خوانایی کد همچنان باید در اولویت باشد. خوشبختانه، بسیاری از این تکنیکها کد را نهتنها کارآمدتر، بلکه خواناتر نیز میکنند. نکاتی که گفته شد تمام نکات مهم برای کدنویسی تمیز نبودند اما برای شروع کار بد نیست آنها را رعایت کنید. برای آشنایی با تمام نکات کدنویسی تمیز میتوانید در دوره کامل پایتون شرکت کنید. امیدوارم این نکات به شما در مسیر تبدیل شدن به برنامهنویسی بهتر در پایتون کمک کند. به کدنویسی ادامه دهید!
دیدگاهتان را بنویسید