FA-TOOLS — Header Component

list comprehension در پایتون — کوتاه‌نویسی حرفه‌ای

رفیق برنامه‌نویس، می‌دونی چقدر وقتا شده که برای ساخت یه لیست جدید، مجبور بودی یه حلقه `for` طولانی بنویسی؟ یا شاید می‌خواستی یه لیست رو فیلتر کنی و باز هم کلی کد تکراری زدی؟ اگه دلت می‌خواد کد نویسی رو توی پایتون ببری به یه سطح جدید و همزمان سرعت و خواناییش رو متحول کنی، همین الان یه سر به فروشگاه ابزارهای برنامه‌نویسی fa-tools.ir بزن. اونجا کلی کدهای آماده پایتون و اسنیپت‌های خفن پیدا می‌کنی که کارتو راه میندازه! همینطور اگه سوال یا نیاز به پشتیبانی داری، می‌تونی همین الان با ما تماس بگیری: 09202232789

🚀 نقشه‌راه کوتاه‌نویسی حرفه‌ای با List Comprehension

List comprehension در پایتون — کوتاه‌نویسی حرفه‌ای — تصویر 1
✨ مقدمه و تعریف

لیست کامپرهنشن چیه و چرا ازش استفاده می‌کنیم؟ قدرت پایتون در خلق لیست‌ها.

📝 ساختار پایه و شرطی

از سینتکس ساده تا اعمال شرط‌های پیچیده.

🔄 پیچیدگی‌ها: تودرتو و انواع دیگر

List، Set و Dictionary Comprehension در یک نگاه.

📊 مزایا و معایب

سرعت، خوانایی، و کی نباید استفاده کنیم؟

🛠️ عیب‌یابی و نکات حرفه‌ای

حل مشکلات رایج و تبدیل شدن به یک کدنویس حرفه‌ای.

لیست کامپرهنشن چیست و چرا باید از آن استفاده کنیم؟

List comprehension در پایتون — کوتاه‌نویسی حرفه‌ای — تصویر 2

تا حالا شده بخوای یه لیست جدید از روی یه لیست موجود بسازی؟ مثلاً همه‌ی اعداد زوج یه لیست رو برداری، یا همه‌ی کلمات یه متن رو به حروف بزرگ تبدیل کنی؟ اگه از روش‌های سنتی استفاده کنی، باید یه حلقه for بنویسی، یه لیست خالی تعریف کنی، و بعد آیتم‌ها رو یکی یکی بهش اضافه کنی. این روش درسته و کار می‌کنه، اما پایتون یه راه ظریف‌تر، کوتاه‌تر و سریع‌تر هم داره: لیست کامپرهنشن (List Comprehension).

تعریف ساده: جادو در یک خط!

لیست کامپرهنشن یه راه فشرده برای ساخت لیست‌ها در پایتونه. به جای اینکه چند خط کد بنویسی تا یه لیست رو پر کنی، می‌تونی همه‌ی این کارا رو در یک خط انجام بدی. این یعنی چی؟ یعنی کد نویسی کمتر، خطاهای کمتر، و کد تمیزتر و خواناتر. یه جورایی مثل اینه که شما یه چوب جادو داشته باشی و با یه حرکت، لیستت ساخته بشه!

چرا List Comprehension اینقدر مهمه؟

  1. خوانایی بالاتر: کد شما خیلی فشرده‌تر و قابل فهم‌تر میشه. هر کسی که با پایتون آشنا باشه، با دیدن یه لیست کامپرهنشن سریع منظورشو می‌فهمه.
  2. کارایی بهتر (Performance): در اکثر موارد، لیست کامپرهنشن‌ها از حلقه‌های for سنتی سریع‌تر عمل می‌کنن. چرا؟ چون این عملیات به زبان C بهینه شدن و سربار کمتری دارن.
  3. کد کمتر: همونطور که از اسمش پیداست، کدنویسی کمتری نیاز داره. این یعنی زمان توسعه کمتر و نگهداری راحت‌تر.
  4. استایل پایتونیک (Pythonic): استفاده از لیست کامپرهنشن‌ها یکی از ویژگی‌های بارز کدنویسی به سبک پایتون به حساب میاد. اگه می‌خوای کدات حرفه‌ای به نظر برسه، باید ازشون استفاده کنی.

ساختار پایه List Comprehension

List comprehension در پایتون — کوتاه‌نویسی حرفه‌ای — تصویر 3

لیست کامپرهنشن از یه ساختار ساده و در عین حال قدرتمند پیروی می‌کنه. درکش خیلی راحته و با چند تا مثال می‌تونی حسابی باهاش رفیق بشی.

سینتکس اصلی

[expression for item in iterable]

  • expression: عملیاتی که روی هر item انجام میدی (مثلاً ضرب در 2، تبدیل به حروف بزرگ و…). نتیجه این عملیات توی لیست جدید قرار می‌گیره.
  • item: هر عنصر تکی از iterable (مثل number یا word).
  • iterable: لیستی که داری روش کار می‌کنی (مثل یه لیست موجود، رشته، تاپل یا رنج اعداد).

مثال ۱: ساخت لیست اعداد توان ۲

تصور کن می‌خوای لیست توان دوم اعداد ۱ تا ۱۰ رو بسازی.


# روش سنتی با حلقه for
squares_for = []
for i in range(1, 11):
    squares_for.append(i ** 2)
print("For Loop:", squares_for)

# با List Comprehension: جادو!
squares_lc = [i ** 2 for i in range(1, 11)]
print("List Comprehension:", squares_lc)

function copyCode(buttonElement) {
const codeBlock = buttonElement.previousElementSibling.querySelector(‘code’);
const textToCopy = codeBlock.innerText;
navigator.clipboard.writeText(textToCopy).then(() => {
const originalText = buttonElement.innerText;
buttonElement.innerText = “کپی شد!”;
setTimeout(() => {
buttonElement.innerText = originalText;
}, 1500);
}).catch(err => {
console.error(‘Failed to copy text: ‘, err);
});
}

ببین چقدر کد کمتری نوشتی و چقدر خواناتر شد؟ عبارت i ** 2 همون expression ماست، i همون item و range(1, 11) همون iterable.

اضافه کردن شرط (Conditional Logic)

لیست کامپرهنشن فقط برای اعمال عملیات روی آیتم‌ها نیست؛ می‌تونی باهاش آیتم‌ها رو هم فیلتر کنی! اینجاست که قدرت واقعی خودشو نشون میده. ساختار کلیش اینجوری میشه:

[expression for item in iterable if condition]

  • condition: یه شرط منطقی (مثلاً item % 2 == 0). فقط آیتم‌هایی که این شرط براشون برقرار باشه، وارد لیست جدید میشن.

مثال ۲: فیلتر کردن اعداد زوج

می‌خوایم فقط اعداد زوج لیست numbers رو توی یه لیست جدید قرار بدیم.


numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# روش سنتی
even_numbers_for = []
for num in numbers:
    if num % 2 == 0:
        even_numbers_for.append(num)
print("For Loop:", even_numbers_for)

# با List Comprehension
even_numbers_lc = [num for num in numbers if num % 2 == 0]
print("List Comprehension:", even_numbers_lc)

استفاده از if-else در Expression

گاهی اوقات می‌خوای بر اساس یه شرط، خود آیتم رو قبل از اضافه شدن به لیست جدید تغییر بدی. یعنی شرط، دیگه برای فیلتر کردن نیست، بلکه برای تغییر دادنه. در این حالت، ساختار if-else میاد توی بخش expression، نه بعد از for:

[value_if_true if condition else value_if_false for item in iterable]

مثال ۳: تبدیل اعداد زوج به “زوج” و فرد به “فرد”


numbers = [1, 2, 3, 4, 5]

# با List Comprehension و if-else در expression
categorized_numbers = ["زوج" if num % 2 == 0 else "فرد" for num in numbers]
print("Categorized List:", categorized_numbers)
# خروجی: ['فرد', 'زوج', 'فرد', 'زوج', 'فرد']

مهمترین نکته اینجاست که محل if و else بسته به کاری که می‌خوای انجام بدی تغییر می‌کنه. اگه می‌خوای آیتمی رو فیلتر کنی و حذفش کنی، if رو بعد از for میذاری. اما اگه می‌خوای آیتمی رو تغییر بدی بر اساس یه شرط، اون وقت if-else میاد اول خط، توی قسمت expression.

فراتر از لیست‌ها: Set و Dictionary Comprehension

پایتون فقط به لیست‌ها محدود نیست! می‌تونی همین مفهوم فشرده‌سازی رو برای ساخت ست‌ها (Set) و دیکشنری‌ها (Dictionary) هم استفاده کنی. این قابلیت فوق‌العادع‌ای برای سازماندهی داده‌ها با کدی تمیز و کارآمد فراهم می‌کنه.

Set Comprehension

ست‌ها مثل لیست‌ها هستن با این تفاوت که آیتم‌های تکراری ندارن و ترتیب خاصی هم ندارن. برای ساخت ست کامپرهنشن، فقط کافیه به جای براکت ( [] ) از آکولاد ( {} ) استفاده کنی:

{expression for item in iterable if condition}

مثال ۴: ساخت ست از حروف منحصر به فرد یک کلمه


word = "programming"
unique_chars = {char for char in word}
print(unique_chars)
# خروجی احتمالی (ترتیب مهم نیست): {'p', 'r', 'o', 'g', 'a', 'm', 'i', 'n'}

Dictionary Comprehension

دیکشنری‌ها هم که دیگه نیازی به تعریف ندارن! برای ساخت دیکشنری با این روش، باز هم از آکولاد استفاده می‌کنیم، اما این بار هر آیتم رو به صورت key: value تعریف می‌کنیم:

{key_expression : value_expression for item in iterable if condition}

مثال ۵: ساخت دیکشنری از اعداد و توان دو آن‌ها


numbers = range(1, 6)
squares_dict = {num: num**2 for num in numbers}
print(squares_dict)
# خروجی: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

List Comprehension تودرتو (Nested)

تصور کن می‌خوای با یه ماتریس کار کنی یا یه لیست از لیست‌ها رو بسازی. اینجاست که لیست کامپرهنشن تودرتو به کارت میاد. ساختار کلیش یه کم پیچیده‌تر میشه ولی باز هم منطقی و قابل درکه:

[expression for item1 in iterable1 for item2 in iterable2]

ترتیب حلقه‌ها از چپ به راست، از حلقه بیرونی به حلقه درونیه. یعنی for item1 in iterable1 اول اجرا میشه، بعد برای هر item1، حلقه for item2 in iterable2 اجرا میشه.

مثال ۶: فلت کردن یک ماتریس


matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# فلت کردن ماتریس با List Comprehension تودرتو
flat_list = [num for row in matrix for num in row]
print("Flat List:", flat_list)
# خروجی: [1, 2, 3, 4, 5, 6, 7, 8, 9]

می‌تونی این ساختار تودرتو رو تا هرجا که نیاز داری ادامه بدی، ولی حواست باشه که زیاد از حد پیچیدش نکنی تا خواناییش از دست نره.

مقایسه: List Comprehension در برابر حلقه‌های سنتی

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

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

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

نکات حرفه‌ای و بهترین روش‌ها

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

چه زمانی از لیست کامپرهنشن استفاده نکنیم؟

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

  • پیچیدگی زیاد: اگه داری سه یا چهار تا for یا if تودرتو توی یه لیست کامپرهنشن می‌ذاری، احتمالاً کد شما دیگه خوانا نیست. بهتره به حلقه‌های سنتی برگردی.
  • عملیات جانبی (Side Effects): لیست کامپرهنشن‌ها برای “ساخت” یه لیست جدید هستن. اگه هدفت تغییر دادن یه متغیر خارجی، پرینت کردن چیزی یا انجام کارهایی با اثر جانبی هست، بهتره از حلقه for معمولی استفاده کنی. این موضوع خوانایی کد رو بسیار بهبود میده.
  • لیست‌های خیلی بزرگ: اگه با لیست‌های میلیون‌ها یا میلیاردها آیتم سروکار داری، ایجاد همه‌ی آیتم‌ها در حافظه با لیست کامپرهنشن ممکنه باعث مشکل بشه. در این حالت، Generator Expression (که شبیه لیست کامپرهنشنه اما از پرانتز () استفاده می‌کنه) گزینه بهتریه چون آیتم‌ها رو در لحظه تولید می‌کنه و حافظه کمتری مصرف می‌کنه.

خوانایی در مقابل کوتاهی

همیشه یادت باشه که هدف اصلی برنامه‌نویسی “کد خوانا” است. کوتاه بودن کد خوبه، اما اگه کوتاهی باعث بشه کدتو بعداً خودت هم نفهمی چی نوشتی، به درد نمی‌خوره. یه قانون سرانگشتی اینه: اگه یه لیست کامپرهنشن در یک خط جا میشه و راحت خونده میشه، استفاده کن. اگه نیاز به شکستن خطوط داره یا چندین شرط و حلقه تودرتو داره، شاید بهتر باشه به حلقه‌های سنتی برگردی.

عیب‌یابی سریع (Troubleshooting)

حتی با تجربه، ممکنه با لیست کامپرهنشن‌ها به مشکل بخوری. اینجا چند تا مشکل رایج و راه‌حلشون رو بررسی می‌کنیم:

مشکل ۱: SyntaxError

این مشکل معمولاً به دلیل اشتباه در چینش if و else یا استفاده نادرست از پرانتز/براکت پیش میاد.

  • راه‌حل:
    1. اگه فقط فیلتر می‌کنی (بدون elseif condition رو بعد از حلقه for بذار.
    2. اگه هم if و هم else داری (برای تغییر آیتم‌ها)، value_if_true if condition else value_if_false رو قبل از حلقه for بذار.
    3. مطمئن شو که براکت‌ها [] برای لیست، {} برای ست و دیکشنری، و () برای جنریتور در جای درستشون استفاده شدن.

مشکل ۲: لیست بیش از حد پیچیده شد

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

  • راه‌حل:
    1. کد رو به یه حلقه for سنتی با چندین خط کد برگردون. این روش هر چند طولانی‌تره، ولی خواناتر و قابل نگهداری‌تره.
    2. اگه امکان داره، عملیات رو به چند مرحله تقسیم کن. مثلاً اول یه لیست رو فیلتر کن، بعد لیست فیلتر شده رو با یه لیست کامپرهنشن دیگه تغییر بده.

مشکل ۳: مصرف زیاد حافظه

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

جمع‌بندی نهایی و کلام آخر

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

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

موفق باشی رفیق!

سوالات متداول (FAQ)

آیا لیست کامپرهنشن همیشه سریع‌تر از حلقه‌های for است؟

در اکثر موارد، بله. لیست کامپرهنشن‌ها به زبان C بهینه‌سازی شده‌اند و سربار کمتری نسبت به حلقه‌های for پایتونی دارند. با این حال، برای عملیات بسیار پیچیده یا لیست‌های کوچک، تفاوت سرعت ممکن است ناچیز باشد یا حتی برعکس شود.

چه زمانی باید از Set Comprehension یا Dictionary Comprehension استفاده کنم؟

از Set Comprehension زمانی استفاده کن که به مجموعه‌ای از آیتم‌های منحصر به فرد نیاز داری و ترتیب آیتم‌ها برایت مهم نیست. از Dictionary Comprehension هم زمانی استفاده کن که می‌خواهی یک دیکشنری جدید بر اساس زوج‌های کلید-مقدار (key-value pairs) بسازی، مثلاً از یک لیست موجود.

آیا می‌توانم چندین شرط if را در یک لیست کامپرهنشن استفاده کنم؟

بله، می‌توانی. می‌توانی چندین شرط if را بعد از حلقه for پشت سر هم قرار دهی (مثل [item for item in iterable if condition1 if condition2]) یا از عملگرهای منطقی and و or استفاده کنی.

تفاوت اصلی List Comprehension و Generator Expression چیست؟

لیست کامپرهنشن کل لیست را در حافظه می‌سازد و برمی‌گرداند. اما Generator Expression یک iterator (مکررکننده) تولید می‌کند که آیتم‌ها را “در لحظه نیاز” تولید می‌کند. این باعث می‌شود Generator Expression برای کار با داده‌های بزرگ‌تر، بهینه‌تر از نظر مصرف حافظه باشد و بهتر برای جریان‌سازی (streaming) داده‌ها استفاده شود. برای ساخت Generator Expression از پرانتز () به جای براکت [] استفاده می‌شود.

آیا می‌توانم از توابع در List Comprehension استفاده کنم؟

بله، قطعاً. می‌توانی توابع را هم در بخش expression و هم در بخش condition لیست کامپرهنشن فراخوانی کنی. این یک راه عالی برای سازماندهی منطق پیچیده‌تر و افزایش خوانایی کد است، به شرطی که تابع شما هیچ اثر جانبی (side effect) نداشته باشد.

 

Table of Contents

آخرین نوشته‌ها