قالب بندی رشته در پایتون
در واقع، در این درس قالب بندی رشته در پایتون را از پایه و با مثال یاد میگیرید.

بنابراین حتما تا کنون چنین دفترچه هایی را در مغازه ها دیده اید. در این دفترچه، چیز هایی که بین همه خرید ها یکسان است از پیش نوشته شده است و اطلاعاتی که متناسب با هر خرید متغیر است خالی قرار داده شده تا فروشنده پر کند. هدف این دفترچه افزایش سهولت و سرعت صدور فاکتور است.
همچنین، در برنامهنویسی نیز گاهی لازم داریم تا الگو های مشابهی در متن ها داشته باشیم. بدین ترتیب قسمت هایی که بین همه الگو ها یکسان است را به عنوان یک قالب تعریف کرده و قسمت هایی که متغیر هستند را با استفاده از string formatting مقدار دهی میکنیم.
Old-style string formatting
روش قالببندی رشته با عملگر % که به Old-Style String Formatting معروف است، از همان نسخههای اولیه پایتون و بهطور مشخص از Python 1.0 معرفی شد. این روش که الهامگرفته از تابع printf در زبان C است، با استفاده از مشخصکنندههایی مانند %s و %d و %f مقادیر متغیرها را داخل رشته جایگزین میکند. با وجود اینکه این شیوه هنوز در پایتون پشتیبانی میشود، امروزه به دلیل خوانایی کمتر، احتمال بروز خطا و محدودیت در قالببندیهای پیچیده، برای کدنویسیهای جدید توصیه نمیشود و جای خود را به روشهای مدرنتری مانند str.format و f-string داده است.
چرا باید یادش بگیریم؟
شاید لازم شود کدی که سالها پیش نوشته شده را بخوانید. در این صورت احتمال دارد چنین سینتکسی به چشم تان بخورد. به همین دلیل بهتر است با آن آشنا باشید.
سینتکس چیست؟
به قوانین و دستور زبانِ یک زبان برنامهنویسی، سینتکس (syntax) میگویند.
Single Positional Placeholders
به این ترتیب، یا به صورت دقیق تر، single old-style positional formatting روشی است که برای جایگذاری تنها یک مقدار در یک رشته استفاده میشود.
name = "John"
formatted_string = "My name is %s." % name
print(formatted_string) # خروجی: "My name is John ."
Multiple Positional Placeholders
علاوه بر این، یا به صورت دقیق تر، Multiple old-style positional formatting روشی است که برای جایگذاری چندین مقدار در یک رشته استفاده میشود.
name = "John"
age = 30
formatted_string = "My name is %s and I'm %d years old." % (name, age)
print(formatted_string) # خروجی: "My name is John and I'm 30 years old."در نهایت، در کد بالا، ۲ تا جای خالی تعریف کردهایم.
- اولین جای خالی را با
%sتعریف کرده ایم بدین معنی که قرار است یک رشته در این قسمت جایگذاری شود. (s اولین حرف string است) - دومین جای خالی را با
%dتعریف کرده ایم بدین معنی که قرار است یک عدد در این قسمت جایگذاری شود. (d اولین حرف digit است)
برای جایگذاری یک عدد در یک رشته، هم از %s و هم از %d و هم از %f میتوان استفاده کرد ولی بهتر است از %d برای اعداد صحیح و از %f برای اعداد اعشاری استفاده شود زیرا این عملگر ها امکاناتی برای اعداد ارائه میدهند که %s آن امکانات را ندارد.
در واقع، در کد بالا، دقیقا ۲ بار از علامت % برای مشخص کردن جای خالی استفاده شده و دقیقا ۲ مقدار نیز در پرانتز به رشته ارسال کرده ایم. اگر تعداد % ها با مقادیری که به رشته ارسال میشود برابر نباشد با خطا مواجه خواهیم شد.
Named Placeholders
بنابراین روش های قبلی در برخی حالات پیچیده میشوند. به تکه کد زیر توجه کنید.
product = "Laptop"
price = 1250
buyer = "Ali"
seller = "TechStore"
discount = 150
final_price = price - discount
warranty_years = 2
report = (
"Purchase Report:n"
"Buyer: %sn"
"Seller: %sn"
"Product: %sn"
"Original Price: %d USDn"
"Discount: %d USDn"
"Final Price: %d USDn"
"Warranty: %d yearsnn"
"Summary:n"
"%s purchased a %s from %s. The original price was %d USD but after a "
"discount of %d USD, the final cost became %d USD. The product includes "
"%d years of warranty.n"
) % (
buyer, seller, product, price, discount, final_price, warranty_years,
buyer, product, seller, price, discount, final_price, warranty_years
)
print(report)همچنین، کد بالا مشکلات زیر را دارد:
- مثلا پیدا کردن متغیری که مقدار %d را در خط ۱۸ پر میکند سخت است.
- در خط ۲۳ و ۲۴ برخی از متغیر ها چندین بار تکرار شده اند. این تکرار بیهوده است و خوانایی را کاهش میدهد.
- اگر یکی از متغیر هایی که در خط ۲۳ و ۲۴ نوشته شده است، ترتیبشان تغییر کند خروجی برنامه بدون اینکه خطایی رخ دهد اشتباه میشود. این یعنی این روش باعث شده تا استیبل بودن این کد کاسته شده و احتمال باگ خیز بودن افزایش پیدا کند.
به این ترتیب، راه حل این مشکل، استفاده از Named Placeholders یا به صورت دقیق تر، Old-Style Named Placeholders است.
product = "Laptop"
price = 1250
buyer = "Ali"
seller = "TechStore"
discount = 150
final_price = price - discount
warranty_years = 2
data = {
"buyer": buyer,
"seller": seller,
"product": product,
"price": price,
"discount": discount,
"final_price": final_price,
"warranty": warranty_years
}
report = (
"Purchase Report:n"
"Buyer: %(buyer)sn"
"Seller: %(seller)sn"
"Product: %(product)sn"
"Original Price: %(price)d USDn"
"Discount: %(discount)d USDn"
"Final Price: %(final_price)d USDn"
"Warranty: %(warranty)d yearsnn"
"Summary:n"
"%(buyer)s purchased a %(product)s from %(seller)s. The original price was "
"%(price)d USD but after a discount of %(discount)d USD, the final cost became "
"%(final_price)d USD. The product includes %(warranty)d years of warranty.n"
) % data
print(report)امکانات مخصوص اعداد
نمایش عدد صحیح
علاوه بر این، برای نمایش عدد صحیح بهتر است از %d استفاده شود.
age = 25
print("Age: %d" % age)
# Output: Age: 25نمایش عدد اعشاری
در نهایت، برای نمایش اعداد اعشاری بهتر است از %f استفاده شود.
pi = 3.14159
print("Pi value: %f" % pi)
# Output: Pi value: 3.141590تعیین تعداد رقم اعشار
در واقع، در این کد با تعریف .2 عدد اعشاری را تا دو رقم نمایش داده ایم.
print("Pi value: %.2f" % pi)
# Output: Pi value: 3.14تعیین عرض عدد
بنابراین نمایش اعداد با استفاده از کد زیر خوانایی خوبی ندارد زیر یکان و دهگان و هزارگان هر کدام، زیر یکدیگر قرار ندارند.
print(1)
print(20)
print(300)
print(4)
print(50)
print(6000)
# Output:
# 1
# 20
# 300
# 4
# 50
# 6000همچنین، اکنون با استفاده از کد زیر، میتوانیم یک نظم خوبی به نوع نمایش آنها بدهیم.
print("%5d" % 1)
print("%5d" % 20)
print("%5d" % 300)
print("%5d" % 4)
print("%5d" % 50)
print("%5d" % 6000)
# Output:
# 1
# 20
# 300
# 4
# 50
# 6000به این ترتیب، عدد 5 که بین % و d قرار گرفته است، میگوید که طول عدد به همراه فاصله های قبلش باید ۵ واحد شود. یعنی اگر عدد تک رقمی باشد، ۴ تا فاصله و اگر عدد دو رقمی باشد، ۳ فاصله و … قبل از آن اضافه میکند تا این فرمت خوانا ایجاد شود.
New-style string formatting
علاوه بر این، روش قالببندی رشته با استفاده از str.format() که با عنوان New-Style String Formatting شناخته میشود، بهصورت رسمی با معرفی Python 3.0 وارد زبان پایتون شد. این روش امکان جایگذاری مقادیر درون رشتهها را با استفاده از آکولادها ({}) فراهم میکند و نسبت به روش قدیمی % خواناتر، منعطفتر و قدرتمندتر است. این شیوه در PEP 3101 معرفی شد و بهعنوان جایگزین رسمی روش قدیمی قالببندی رشتهها در پایتون مطرح گردید و تا پیش از معرفی f-stringها در PEP 498، روش استاندارد و توصیهشده برای قالببندی رشتهها بهشمار میرفت.
در نهایت، مثال زیر یک نمونه ساده از کاربرد این تابع است.
name = "Mohammadreza"
age = 30
formatted_string = "My name is {} and I'm {} years old.".format(name, age)
print(formatted_string) # خروجی: "My name is Mohammadreza and I'm 30 years old."در واقع، در مثال بالا، اولین ورودی در موقعیت اولین آکولاد و دومین ورودی در موقعیت دومین آکولاد قرار میگیرد.
بنابراین اکنون به مثال زیر توجه کنید.
name = "Mohammadreza"
age = 30
formatted_string = "His name is {} and He's {} years old. {} is a programmer".format(name, age, name)
print(formatted_string)
# Output: His name is Mohammadreza and He's 30 years old. Mohammadreza is a programmerهمچنین، مشکلی که در مثال بالا داریم این است که نام را دو بار در تابع فرمت استفاده کرده ایم. برای اینکه کد بالا کمی خوانا تر شود میتوان آن را به شکل زیر بهبود داد.
name = "Mohammadreza"
age = 30
formatted_string = "His name is {0} and He's {1} years old. {0} is a programmer".format(name, age)
print(formatted_string)
# Output: His name is Mohammadreza and He's 30 years old. Mohammadreza is a programmerبه این ترتیب، عدد صفر به اولین ورودی format و عدد یک به دومین ورودی آن اشاره میکند. اکنون از شما میخواهم به این فکر کنید که اگر ابتدا age و سپس name را به format پاس میدادیم چه اعدادی در آکولاد ها باید مینوشتیم که خروجی همچنان به درستی کار میکرد؟
علاوه بر این، پاسخ این سوال را در تکه کد زیر ببینید.
name = "Mohammadreza"
age = 30
formatted_string = "His name is {1} and He's {0} years old. {1} is a programmer".format(age, name)
print(formatted_string)
# Output: His name is Mohammadreza and He's 30 years old. Mohammadreza is a programmerدر نهایت، اگر تعداد ورودی هایی که به format ارسال میکنید زیاد بود، برای حفظ خوانایی کد از روش زیر استفاده کنید.
name = "Mohammadreza"
age = 30
formatted_string = "His name is {name} and He's {age} years old. {name} is a programmer".format(name=name, age=age)
print(formatted_string)
# Output: His name is Mohammadreza and He's 30 years old. Mohammadreza is a programmerدر واقع، کد بالا را با استفاده از دیکشنری هم میتوان نوشت. این روش بیشتر زمانی کاربرد دارد که مقدار متغیر args به طریقی خودش پر خواهد شد و شما صرفا نیاز است تا آن را به تابع format ارسال کنید.
args = {
"name": "Mohammadreza",
"age": 30
}
formatted_string = "His name is {name} and He's {age} years old. {name} is a programmer".format(**args)
print(formatted_string)
# Output: His name is Mohammadreza and He's 30 years old. Mohammadreza is a programmerکار با اعداد
بنابراین تعیین تعداد رقم اعشار
print("{:.2f}".format(3.14159))
# Output: 3.14همچنین، تعیین عرض عدد
print("{:5d}".format(42))
# Output: 42به این ترتیب، تراز عدد در عرض مشخص از چپ
print("{:<5d}".format(42))
# Output: 42 علاوه بر این، تراز عدد در عرض مشخص وسط
print("{:^5d}".format(42))
# Output: 42 در نهایت، تراز عدد در عرض از راست
print("{:>5d}".format(42))
# Output: 42در واقع، پر کردن فضای خالی با کارکتر دلخواه
print("{:0>5d}".format(42))
# Output: 00042بنابراین جداکننده هزارگان
print("{:,}".format(1000000))
# Output: 1,000,000همچنین، نمایش عدد اعشاری به صورت درصدی
print("{:.1%}".format(0.875))
# Output: 87.5%F-strings
f-string که مخفف Formatted String Literal است، روشی برای قالببندی رشتههاست که در آن میتوان متغیرها و حتی عبارات پایتونی را مستقیماً داخل رشته قرار داد. این قابلیت از Python 3.6 به بعد اضافه شده است.
name = "John"
age = 30
formatted_string = f"My name is {name} and I'm {age} years old."
print(formatted_string) # خروجی: "My name is John and I'm 30 years old."به این ترتیب، یکی از قدرتهای f-string امکان استفاده از محاسبات و توابع است.
x = 10
y = 3
print(f"جمع: {x + y}")
print(f"توان: {x ** y}")علاوه بر این، حتی میتوان یک تابع را مستقیم در آن فراخوانی کرد.
def say_hello(name):
return f"hello {name}"
print(f"{say_hello('Amir')}")کار با اعداد
در نهایت، تعیین تعداد رقم اعشار
value = 3.14159
print(f"{value:.2f}")
# Output: 3.14در واقع، تعیین عرض عدد
value = 42
print(f"{value:5d}")
# Output: 42بنابراین تراز عدد در عرض مشخص از چپ
value = 42
print(f"{value:<5d}")
# Output: 42 همچنین، تراز عدد در عرض مشخص از وسط
value = 42
print(f"{value:^5d}")
# Output: 42 به این ترتیب، تراز عدد در عرض مشخص از راست (پیش فرض)
value = 42
print(f"{value:>5d}")
# Output: 42علاوه بر این، پر کردن فضای خالی با کارکتر دلخواه
value = 42
print(f"{value:0>5d}")
# Output: 00042در نهایت، جدا کننده هزارگان
value = 1000000
print(f"{value:,}")
# Output: 1,000,000در واقع، نمایش عدد اعشاری به صورت درصدی
value = 0.875
print(f"{value:.1%}")
# Output: 87.5%حفظ نکنید!
در این بخش با انواع زیادی از string formatting آشنا شدید. هیچکدام را حفظ نکنید. فقط در حدی بلد باشید که اگر کدشان را دیدید تعجب نکنید.
بنابراین برای مطالعهی بیشتر میتوانید به مستندات رسمی پایتون سر بزنید.
در مجموع، اگر این مطلب را خوب یاد گرفته باشید، حالا میتوانید قالب بندی رشته در پایتون را در برنامههای واقعی به کار ببرید. با این حال بهترین راه تثبیت این مفهوم، تمرین کردن است؛ بنابراین پیشنهاد میکنیم پس از این درس، تمرینهای مربوط به آن را هم حل کنید. به این ترتیب هم مطلب برایتان ماندگار میشود و هم در نوشتن کد سریعتر عمل میکنید.