قالب بندی رشته ها – String formatting

Please login to bookmark Close

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

در برنامه‌نویسی نیز گاهی لازم داریم تا الگو های مشابهی در متن ها داشته باشیم. بدین ترتیب قسمت هایی که بین همه الگو ها یکسان است را به عنوان یک قالب تعریف کرده و قسمت هایی که متغیر هستند را با استفاده از string formatting مقدار دهی می‌کنیم.

Old-style string formatting


روش قالب‌بندی رشته با عملگر % که به Old-Style String Formatting معروف است، از همان نسخه‌های اولیه پایتون و به‌طور مشخص از Python 1.0 معرفی شد. این روش که الهام‌گرفته از تابع printf در زبان C است، با استفاده از مشخص‌کننده‌هایی مانند %s و %d و %f مقادیر متغیرها را داخل رشته جایگزین می‌کند. با وجود اینکه این شیوه هنوز در پایتون پشتیبانی می‌شود، امروزه به دلیل خوانایی کمتر، احتمال بروز خطا و محدودیت در قالب‌بندی‌های پیچیده، برای کدنویسی‌های جدید توصیه نمی‌شود و جای خود را به روش‌های مدرن‌تری مانند str.format و f-string داده است.

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 است)

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

Named Placeholders

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

product = "Laptop"
price = 1250
buyer = "Ali"
seller = "TechStore"
discount = 150
final_price = price - discount
warranty_years = 2

report = (
    "Purchase Report:\n"
    "Buyer: %s\n"
    "Seller: %s\n"
    "Product: %s\n"
    "Original Price: %d USD\n"
    "Discount: %d USD\n"
    "Final Price: %d USD\n"
    "Warranty: %d years\n\n"
    "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)s\n"
    "Seller: %(seller)s\n"
    "Product: %(product)s\n"
    "Original Price: %(price)d USD\n"
    "Discount: %(discount)d USD\n"
    "Final Price: %(final_price)d USD\n"
    "Warranty: %(warranty)d years\n\n"
    "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%
Please login to bookmark Close
پیشرفت شما در «دوره آموزش پایتون مقدماتی» (20%)
نظرات

دیدگاهتان را بنویسید

20%
پیشرفت

سرفصل دوره

فهرست مطالب

سرفصل دوره

تمرین

این قسمت تمرین ندارد!

پاسخ تمرین ها

هنوز برای تمرین‌های این قسمت پاسخی ثبت نشده است!

اشتراک گذاری

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

من همه ویدئو ها و پادکست های کُدباز رو توی یوتیوب و ساندکلود و پلتفرم هایی آپلود می‌کنم که اغلب فیلتر هستند.

اغلب آموزش‌ها ویدئو و پادکست دارند. پس اگر می‌خواهید از محتوای سایت بیشترین استفاده رو ببرید نیاز به فیلتر شکن دارید.

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

تنظیمات

انتخاب زبان
تغییر تم