2025, Oct 31 17:02
Python में अंकगणित का साफ कंसोल लेआउट: स्ट्रिंग/इटेरेबल गड़बड़ियाँ दूर करें
Python में कंसोल फॉर्मेटिंग क्यों बिगड़ती है? स्ट्रिंग में बदले कंटेनरों पर इटेरेट करने और डुप्लीकेट प्रिंट की गलती समझें, सही लेआउट व टिकाऊ एलाइनमेंट से फिक्स करें.
जब आप अंकगणितीय ऑपरेशनों के इर्द-गिर्द कंसोल फॉर्मेटिंग बनाते हैं, तो एक छोटी-सी चूक भी आउटपुट को गड़बड़ा सकती है। इस मामले में, एक वैज्ञानिक कैलकुलेटर इधर-उधर भटके हुए कॉमा और कोष्ठक छाप देता है, और अंतिम परिणाम दो बार दिखाई देता है। वजह गणित नहीं, बल्कि लेआउट के दौरान स्ट्रिंग्स और इटेरेबल्स को हैंडल करने का तरीका है।
समस्या को पुनः उत्पन्न करना
नीचे दिया गया स्निपेट ठीक वही व्यवहार दिखाता है: आउटपुट के बीच में अप्रत्याशित चिन्ह और डुप्लीकेट रिजल्ट लाइन।
class CalcPretty:
def __init__(self, *vals):
self.vals = vals
def render(self, nums, op, outcome):
w = max(len(str(x)) for x in (list(nums) + list(outcome))) + 2
rows = []
rows.append(f"{str(nums[0]).rjust(w)}")
for ch in str(nums[1:]):
rows.append(f"{op}{ch.rjust(w-1)}")
dashes = '-' * w
rows.append(dashes)
rows.append(f"{str(outcome).rjust(w)}")
return "\n".join(rows)
def sumup(self, *args):
total = sum(self.vals)
s_total = str(total)
print(self.render(self.vals, '+', s_total))
return s_total
obj = CalcPretty(23, 2, 3)
print(obj.sumup())
गलती कहाँ हो रही है और क्यों
आउटपुट दो जगह पटरी से उतरता है। पहले, बाद वाली वैल्यूज़ को लेआउट करने वाला एक्सप्रेशन ट्यूपल स्लाइस को स्ट्रिंग में बदल देता है। str(nums[1:]) कॉल करने पर ट्यूपल का लिटरल रूप बनता है, जैसे "(2, 3)", और उस स्ट्रिंग पर इटरेट करने से हर कैरेक्टर अलग-अलग मिलता है—कोष्ठक, कॉमा और स्पेस सहित। यही वजह है कि “(”, “,” और “)” ऑपरेटर के साथ अलग-अलग पंक्तियों में दिखते हैं।
डुप्लीकेट कुल इसलिए आता है क्योंकि जिम्मेदारियाँ मिल गई हैं: मेथड फॉर्मेटेड ब्लॉक को प्रिंट भी करता है और एक वैल्यू लौटाता भी है, और कॉलर उस रिटर्न वैल्यू को फिर से प्रिंट कर देता है। अंदर और बाहर दोनों जगह प्रिंट करने से परिणाम वाली दो पंक्तियाँ बन जाती हैं।
एक डिजाइन बारीकी भी है। बेहतर है कि नंबर ऑपरेशन मेथड को पास किए जाएँ, उन्हें इंस्टेंस पर स्टोर न किया जाए। इससे फ्लो साफ रहता है और बासी स्टेट से बचाव होता है। अंत में, लेआउट कोड को यह मानकर नहीं चलना चाहिए कि ऑपरेटर एक अक्षर का है; उसकी वास्तविक लंबाई के आधार पर एलाइनमेंट करना फॉर्मेटिंग को टिकाऊ बनाता है।
फॉर्मेटिंग और फ्लो को दुरुस्त करना
सुधारा गया संस्करण केवल असली नंबरों को फॉर्मेट करता है, ऑपरेटर की चौड़ाई का हिसाब रखता है, और पूरा ब्लॉक बनाकर लौटाता है ताकि प्रिंट करने का फैसला कॉलर करे। f-strings एलाइनमेंट को अभिव्यक्तिपूर्ण और कॉम्पैक्ट दोनों बनाती हैं।
class CalcOps:
def layout_block(self, seq: tuple[int|float, ...], op: str, out_str: str) -> str:
opw = len(op)
span = max(len(str(v)) for v in (list(seq) + [out_str])) + opw + 1
lines = [f"{seq[0]:>{span}}"]
for v in seq[1:]:
lines.append(f"{op}{v:>{span - opw}}")
lines.append('-' * span)
lines.append(f"{out_str:>{span}}")
return "\n".join(lines)
def plus(self, *vals: int|float) -> str:
res = str(sum(vals))
return self.layout_block(vals, "+", res)
print(CalcOps().plus(23, 2, 3))
आउटपुट:
23
+ 2
+ 3
----
28
उत्पादन-स्तर के कोड में यह क्यों मायने रखता है
ट्यूपल या लिस्ट जैसे कंटेनरों को स्ट्रिंग में बदलकर उन पर इटरेट करना एक महीन जाल है: आप मूल्यों पर नहीं, अक्षरों पर इटरेट करने लगते हैं। फॉर्मेटेड कंसोल या लॉग आउटपुट में इससे ऐसे भ्रामक चिन्ह आ सकते हैं जो स्टैक के ऊपर की लॉजिक त्रुटियों जैसे लगें। डेटा गणना को प्रस्तुति से अलग रखना भी फायदेमंद है। फॉर्मेटेड ब्लॉक लौटाना और उसे कॉल साइट पर प्रिंट करना डुप्लीकेट आउटपुट से बचाता है और टेस्टिंग आसान करता है।
मुख्य सीख
साफ-सुथरे संख्यात्मक लेआउट के लिए स्ट्रिंग में बदले कंटेनरों पर नहीं, वास्तविक मानों पर इटरेट करें। एलाइनमेंट वास्तविक चौड़ाइयों—खुद ऑपरेटर सहित—के आधार पर निकालें ताकि ऑपरेटर बदलने पर भी फॉर्मेटTING नहीं टूटे। प्रिंटिंग को किनारों पर रखें: ऑपरेशन मेथड एक स्ट्रिंग तैयार करे, और उसे कॉल साइट पर प्रिंट करें। ये छोटे अभ्यास शोर भरे आउटपुट को खत्म करते हैं और CLI टूल्स में अंकगणितीय फॉर्मेटिंग को भरोसेमंद और मेंटेनेबल बनाते हैं।