فصل ۲: داده‌ها — متغیر، عدد، پول، متن فارسی و ورودی

رشته‌ها و یونیکد فارسی: len، نیم‌فاصله، ی و ک عربی، متدها و slicing

متن فارسی از نگاه پایتون

در پایتون ۳ هر رشته (str) دنباله‌ای از کاراکترهای یونیکد است؛ بنابراین فارسی، عربی و ایموجی همان‌قدر «طبیعی» هستند که حروف لاتین. رشته را می‌توان با '…' یا "…" ساخت و برای چندخطی از سه کوتیشن استفاده کرد. رشته‌ها تغییرناپذیرند: هر متدی مثل replace یک رشته‌ی جدید برمی‌گرداند و رشته‌ی اصلی دست‌نخورده می‌ماند.

len و کاراکترهای نامرئی

print(len("سلام"))          # 4
print(len("می‌روم"))        # 6 — نیم‌فاصله هم یک کاراکتر است
print("‌" in "می‌روم")  # True: U+200C همان نیم‌فاصله (ZWNJ) است
print(ord("ی"), ord("ي"))   # 1740 1610
print("علی" == "علي")       # False!

دو نکته‌ی حیاتی برای هر برنامه‌ی فارسی: اول، نیم‌فاصله کاراکتر واقعی است و در طول رشته، جست‌وجو و مقایسه حساب می‌شود. دوم، «ی» و «ک» فارسی (U+06CC و U+06A9) با «ي» و «ك» عربی (U+064A و U+0643) کدهای متفاوتی دارند. متنی که از کیبورد عربی، سیستم‌های قدیمی یا بعضی سایت‌ها می‌آید، ظاهراً یکسان است ولی در جست‌وجو پیدا نمی‌شود. راه‌حل، یکسان‌سازی پیش از ذخیره یا مقایسه است:

FA_FIX = str.maketrans({"ي": "ی", "ك": "ک", "ى": "ی"})

def normalize_fa(text: str) -> str:
    return " ".join(text.translate(FA_FIX).split())   # اصلاح حروف و فاصله‌های اضافی

print(normalize_fa("  فرش   كاشان  علي ") == "فرش کاشان علی")   # True

اندیس و برش (slicing)

هر کاراکتر یک شماره (اندیس) دارد که از صفر شروع می‌شود؛ اندیس منفی از انتها می‌شمارد. برش با [start:stop:step] زیررشته می‌سازد و stop جزو نتیجه نیست:

code = "KSH-1403-0587"
print(code[0])       # K
print(code[-4:])     # 0587   — چهار کاراکتر آخر
print(code[4:8])     # 1403
print(code[::-1])    # معکوس رشته
print(code[20:])     # '' — برش هیچ‌وقت IndexError نمی‌دهد

متدهای پرکاربرد

متدکارمثال
strip()حذف فاصله‌ی ابتدا و انتها" کاشان ".strip()
split(sep)شکستن به لیست"۳×۴,کاشان".split(",")
sep.join(list)چسباندن لیست رشته‌ها"، ".join(cities)
replace(a, b)جایگزینیs.replace("ك", "ک")
startswith / endswithبررسی ابتدا/انتها؛ تاپل هم می‌گیردf.endswith((".csv", ".xlsx"))
find / indexجای زیررشته؛ find در نبود ‎-1 می‌دهد، index خطاs.find("فرش")
zfill(n)صفر در ابتدا"87".zfill(4) ← 0087

نکته‌هایی که کمتر کسی می‌داند

  • strip() نیم‌فاصله را حذف نمی‌کند، چون ZWNJ از نظر یونیکد «فاصله» نیست؛ برای حذفش بنویسید s.strip(" ‌").
  • split() بدون آرگومان با split(" ") فرق دارد: اولی هر تعداد فاصله، Tab و خط جدید را یکی حساب می‌کند و رشته‌ی خالی تولید نمی‌کند.
  • unicodedata.name("ی") نام رسمی کاراکتر را می‌دهد (ARABIC LETTER FARSI YEH)؛ بهترین ابزار برای کشف کاراکترهای مشکوک در داده.
  • برعکس کردن رشته‌ی فارسی با [::-1] حروف را معکوس می‌کند اما چون نمایش فارسی راست‌به‌چپ است، نتیجه در ترمینال ممکن است غیرمنتظره به نظر برسد؛ منطق درست است، نمایش گول‌زننده است.
  • رشته‌سازی با += در حلقه‌ی بزرگ کند است؛ تکه‌ها را در لیست جمع کنید و در پایان یک‌بار "".join(parts) بزنید.

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