Python Best Practices
साफ़ code क्यों ज़रूरी है
Code लिखे जाने से कहीं ज़्यादा पढ़ा जाता है – साथियों द्वारा, interviewers द्वारा, और छह महीने बाद ख़ुद आपके द्वारा। साफ़ code में bugs कम होते हैं, बदलना आसान होता है और GitHub portfolio तथा machine-coding rounds में अच्छी छाप छोड़ता है।
पहले और बाद: एक program, दो style
import json
def f(d,t=[]):
for i in range(len(d)):
if d[i]['m']>=40 and d[i]['m']!=None:
t.append(d[i]['n'])
return t
x=json.loads('[{"n":"Asha","m":91},{"n":"Ravi","m":35}]')
print(f(x))
print(f(x))Output की दूसरी line देखिए: दूसरी call पर list ["Asha", "Asha"] हो गई। यह मशहूर mutable default argument bug है – t=[] एक बार बनता है और हर call में साझा होता है। f, d, t, m, n जैसे नाम भी code का मतलब छिपाते हैं।
"""Find students who passed an exam."""
import json
PASS_MARKS = 40
def passed_students(results: list[dict], pass_marks: int = PASS_MARKS) -> list[str]:
"""Return names of students whose marks are at least pass_marks."""
return [r["name"] for r in results if r.get("marks") is not None and r["marks"] >= pass_marks]
def main() -> None:
results = json.loads('[{"name": "Asha", "marks": 91}, {"name": "Ravi", "marks": 35}]')
print(passed_students(results))
print(passed_students(results))
if __name__ == "__main__":
main()| बदलाव | क्यों |
|---|---|
अर्थपूर्ण नाम (passed_students, results) | Code ख़ुद समझाता है |
Constant PASS_MARKS | “Magic numbers” नहीं; बदलने की एक जगह |
| Mutable default नहीं; नई list बनाएँ | छिपा bug ठीक |
range(len()) की जगह comprehension | छोटा और साफ़ |
is not None | None से तुलना का सही तरीका |
| Type hints और docstring | Editors और साथी जानते हैं क्या जाता और आता है |
main() + if __name__ == "__main__" | File import हो सके बिना चले |
PEP 8 naming और layout
| चीज़ | Style | उदाहरण |
|---|---|---|
| Variable, function | snake_case | total_fees, send_email() |
| Class | PascalCase | StudentReport |
| Constant | UPPER_SNAKE | MAX_RETRIES = 3 |
| Private helper | शुरू में underscore | _clean_name() |
| Indentation | 4 spaces, tabs कभी नहीं | |
| Line length | 79–100 characters (team तय करे) | |
| Imports | File के ऊपर: standard library, third-party, आपके modules |
Pythonic आदतें
students = ["Asha", "Ravi", "Neha"]
marks = [91, 58, 76]
# 1. enumerate instead of range(len())
for rank, name in enumerate(students, start=1):
print(rank, name)
# 2. zip to walk two lists together
report = {name: m for name, m in zip(students, marks)}
print(report)
# 3. f-strings with formatting
fee = 12500.5
print(f"Fee: ₹{fee:,.2f} | Pass rate: {2/3:.0%}")
# 4. truthiness instead of len(x) == 0
pending = []
if not pending:
print("No pending fees")
# 5. dict.get with a default
print(report.get("Kabir", "absent"))
# 6. unpacking
first, *others = students
print(first, others)Resources: हमेशा with इस्तेमाल करें
# bad: file stays open if an error happens before close()
f = open("notes.txt", "w", encoding="utf-8")
f.write("Revise loops\n")
f.close()
# good: closed automatically, even on errors
with open("notes.txt", "a", encoding="utf-8") as f:
f.write("Practise functions\n")
with open("notes.txt", encoding="utf-8") as f:
print(f.read().strip())Errors को ख़ास तौर पर पकड़ें
def read_age(text):
try:
age = int(text)
except ValueError: # catch only what you expect
return None
if not 5 <= age <= 100:
raise ValueError(f"age {age} out of range")
return age
print(read_age("15"), read_age("fifteen"))
try:
read_age("150")
except ValueError as e:
print("Error:", e)except: या except Exception: pass असली bugs छिपा देता है (typos और Ctrl+C भी)। सिर्फ़ वही exception पकड़ें जो संभाल सकते हैं, बाक़ी को log या re-raise करें।
एक काम वाले छोटे functions
- Function एक काम करे और एक वाक्य में समझाया जा सके।
- Function के अंदर print करने से बेहतर value लौटाना – लौटाई values test और दोबारा इस्तेमाल हो सकती हैं।
- Global variables से बचें; data arguments से दें।
- 4–5 से ज़्यादा parameters? उन्हें dataclass या dict में रखें।
- साफ़ता के लिए keyword arguments:
send(to="riya", retry=True)।
from dataclasses import dataclass
@dataclass
class Order:
item: str
price: float
qty: int = 1
@property
def total(self) -> float:
return self.price * self.qty
o = Order("Kaju Katli", 900, 2)
print(o)
print(o.total)Tools से style जँचवाएँ
| Tool | काम | Command |
|---|---|---|
| ruff | बहुत तेज़ linter: unused imports, bugs, style गड़बड़ी | ruff check . |
| black / ruff format | Code अपने-आप format | ruff format . |
| mypy | Type hints जाँचता है | mypy app.py |
| pytest | Tests चलाता है | pytest |
“before” program पर ruff चलाने से समस्याएँ अपने-आप मिलती हैं:
import json
def f(d,t=[]):
for i in range(len(d)):
if d[i]['m']>=40 and d[i]['m']!=None:
t.append(d[i]['n'])
return t
x=json.loads('[{"n":"Asha","m":91},{"n":"Ravi","m":35}]')
print(f(x))
print(f(x))Code review checklist
- नाम उद्देश्य बताएँ; छोटे loops के अलावा single letters नहीं।
- दोहराया code नहीं – दोहराया logic function में।
- Magic numbers नहीं – नाम वाले constants।
- Errors ख़ास तौर पर संभाले; खाली except नहीं।
- Files और connections
withसे खुले। - Functions छोटे, values लौटाएँ, public के लिए docstrings।
- ज़रूरी नियमों के tests हों।
- ruff कोई warning न दिखाए; code formatted हो।
अभ्यास
- अपना कोई पुराना program लेकर हर variable को अर्थपूर्ण नाम दें।
- Items जमा करने वाले function में mutable default argument ढूँढकर ठीक करें।
- venv में ruff install करके project पर
ruff check .चलाएँ और हर warning ठीक करें। - Dictionary वाले record को computed property वाली dataclass में बदलें।
सारांश
- PEP 8 नाम: snake_case, PascalCase, UPPER_SNAKE।
[]या{}जैसा mutable default argument कभी नहीं।- enumerate, zip, f-strings, with, comprehensions और specific exceptions।
- छोटे functions, type hints, docstrings,
main()guard। - Style ruff/black से और सही होना pytest से automate करें।
