Skip to main content

Python in the AI Era: एक crash course

17 अवधारणाएँ · लिखने से पहले पढ़ें

आप पहले ही Agentic Coding कोचिंग कोर्स में AI coding agent चलाना सीख चुके हैं। आप एक सत्र को open कर सकते हैं, Claude Code या OpenCode को एक निर्देश दे सकते हैं, और इसे files और run command को संपादित करते हुए देख सकते हैं। तो यहाँ एक ईमानदार प्रश्न है जिसका उत्तर देने के लिए यह पाठ्यक्रम मौजूद है:

यदि agent Python लिखता है, तो आपको कोई Python सीखने की आवश्यकता क्यों है?

क्योंकि किसी को तो इसे पढ़ना ही होगा. agent सेकंड में कामकाजी दिखने वाली code की सैकड़ों लाइनें तैयार करता है। और "कामकाजी-दिखना" ही जाल है। AI प्रशंसनीय के लिए अनुकूलन करता है, सही के लिए नहीं। code जो चुपचाप गलत नंबर लौटाता है, रिकॉर्ड छोड़ देता है, या आपकी API key को लीक कर देता है, बिल्कुल code की तरह दिखता है जो काम करता है। एकमात्र व्यक्ति जो अंतर बता सकता है वह वह है जो agent ने जो लिखा है उसे पढ़ सकता है और साबित कर सकता है कि उसका मतलब वही है।

अब सारा काम यही है. किसी रिक्त पृष्ठ से loop टाइप नहीं करा। agent ऐसा करता है। आपका काम वह हिस्सा है जिसके लिए अभी भी एक इंसान की आवश्यकता है: यह तय करा कि सही का क्या अर्थ है, और यह सत्यापित करा कि उत्पन्न code इसे पूरा करता है।

जहां यह कोर्स बैठता है

यह AI युग में मेगा का प्रवेश द्वार है। पुस्तक का वह भाग एक Project (स्मार्टनोट्स) के आसपास बनाया गया 3-5 महीने का गहन पाठ्यक्रम है। यह crash course 80%-इन-वन-रीड संस्करण है: आज agent code पढ़ना शुरू करे के लिए पर्याप्त Python साक्षरता। यह आता है बाद agentcodeing और पहले AI agenting का निर्माण करें, AI पोस्टग्रेज के लिए, और एक डिजिटल शीट का निर्माण, जिनमें से तीनों मानते हैं कि आप Python को पढ़ सकते हैं और agent उत्पन्न करते हैं। यहां किसी भी विषय के संपूर्ण उपचार के लिए, उस पाठ्यक्रम के link का अनुसरण करें।

एक विचार जो नीचे दी गई हर चीज़ को व्यवस्थित करता है: पुरानी दुनिया में, आपने Python को लिखकर सीखा था। यहां आप इसे पढ़कर सीखते हैं: भविष्यवाणी करा कि code क्या करता है, इसे चलाना, क्यों की जांच करा, फिर इसे बदलना और अंत में अपना खुद का निर्माण करा। हमारे पास उस loop के लिए एक नाम है, और यह पूरे पाठ्यक्रम की रीढ़ है।

इस पाठ्यक्रम में सब कुछ कुछ ऐसा है जो आप Claude Code सत्र के अंदर करते हैं, न कि केवल उसके बारे में पढ़ते हैं। terminal open को claude के साथ चालू रखें और जैसे ही आप उस तक पहुंचें, प्रत्येक विचार को आज़माएं।

इस पाठ्यक्रम में सब कुछ कुछ ऐसा है जो आप OpenCode सत्र के अंदर करते हैं, न कि केवल उसके बारे में पढ़ते हैं। terminal open को opencode के साथ चालू रखें और जैसे ही आप उस तक पहुंचें, प्रत्येक विचार को आज़माएं। यदि आप लागत देख रहे हैं, तो इसे नियमित run के लिए deepseek-v4-flash जैसे सस्ते model पर इंगित करें (agent coding पाठ्यक्रम देखें)।


अपना परिवेश सेट करें (एक बार)

इस कोर्स का एक छोटा सा साथी है जिसे आप एक बार download कहते हैं: कोर्स बेस। आपको इसे साथ में पढ़ने की सख्त ज़रूरत नहीं है, लेकिन यह हर चीज़ को पाठ्यक्रम के अनुसार व्यवहार करे योग्य बनाता है। यह एक संक्षिप्त नियम file, AGENTS.md भेजता है, जो आपके agent को अनुशासित ट्यूटर में बदल देता है जिस पर यह पाठ्यक्रम निर्भर करता है: यह प्रकट होने से पहले भविष्यवाणी करता है, उत्तर के बजाय संकेत देता है, और इसे पारित करे के लिए test को कभी भी चुपचाप कमजोर नहीं करता है। आपका agent हर बार प्रारंभ होने पर file को automatically पढ़ता है, यही कारण है कि आपका prompts यहां छोटा रह सकता है। आधार में practice Project स्टार्टर्स और एक उत्तर key भी होती है जिसके आधार पर आप अपने स्वयं के परीक्षणों की जांच कर सकते हैं।

downloadpython-crash-course-base.zip

इसे अनज़िप करें, फिर open अपने agent को folder के अंदर रखें:

cd python-crash-course
claude
cd python-crash-course
opencode

बेस जहाजों पर ध्यान दें अभी तक कोई Python परियोजना नहीं, जानबूझकर। शून्य से अपना स्वयं का कार्यक्षेत्र बनाना पहला वास्तविक Skill है, और यह आपके द्वारा किया जाने वाला अगला कार्य है, संकल्पना 3। अभी के लिए, बस open अपने agent को folder में डालें और पुष्टि करें कि इसने नियम लोड किए हैं:

इस सत्र के लिए आप किन नियमों का पालन कर रहे हैं?

इसमें लिखने से पहले पढ़ने की प्रक्रिया method और सत्यापित करे के लिए परीक्षण चलाने की आदत का वर्णन होना चाहिए। हो गया जब आपका agent उन नियमों के साथ उत्तर देता है। (इसके बजाय खाली folder से शुरुआत करा पसंद करें? यह भी काम करता है; जैसे-जैसे आप आगे बढ़ेंगे, आप खुद ही अनुशासन निर्धारित करते जाएंगे।)


भाग 1: नई मानसिकता

1. आपने code पढ़ा; agent इसे लिखता है

पारंपरिक Python पाठ्यक्रमों में, प्रशिक्षित किया जाने वाला Skill उत्पादन है: function टाइप करें, loop टाइप करें, class टाइप करें। AI ने उस बाधा को हटा दिया। अब जो Skill मायने रखता है वह है दिशा और सत्यापन

पुराना कार्य (अब अधिकतर automatic)नई नौकरी (अभी भी आपकी)
किसी रिक्त पृष्ठ से कार्यान्वयन टाइप करेंआप जो चाहते हैं उसका सटीक वर्णन करें, शब्दों में agent उस पर कार्य कर सकता है
वाक्यविन्यास याद रखेंइसे आलोचनात्मक रूप से पढ़ने के लिए पर्याप्त रूप से पहचानें वाक्यविन्यास
code से run प्राप्त करेंसिद्ध करें कि code सही है, केवल चलाने योग्य नहीं

यह प्रोग्रामिंग पर लागू 10-80-10 नियम है। आप पहले 10% (यह तय करते हुए कि क्या build करा है और "सही" का क्या अर्थ है) और अंतिम 10% (इसे सत्यापित करा) के मालिक हैं। agent मध्य में 80% का मालिक है (code उत्पन्न करता है)। धाराप्रवाह पढ़ना आपको दोनों छोर रखने में सक्षम बनाता है।

The 10-80-10 rule: you own the first 10% (decide what's correct) and the last 10% (verify); the agent owns the 80% in the middle (generate the code).

आपको कुछ भी याद रखने की जरूरत नहीं है

पढ़ना लिखने से कहीं अधिक आसान है। आपको यह याद दिलाने की आवश्यकता नहीं है कि list वर्गाकार कोष्ठक का use करता है। जब आप इसे देखें तो आपको केवल ["a", "b"] को list के रूप में पहचानने की आवश्यकता है। इस पूरे पाठ्यक्रम के लिए यही बाधा है: मान्यता, स्मरण नहीं।

2. PRIMM-AI+ method

PRIMM-AI+ इस प्रकार है कि आप किसी खाली पृष्ठ को देखे बिना code पढ़ना सीखते हैं। Python का प्रत्येक नया टुकड़ा पाँच चरणों से होकर गुजरता है, और agent हर चरण में आपका भागीदार है:

कदमपत्रआप क्या करते हैंagent की भूमिका
भविष्यवाणी करापीकुछ भी चलने से पहले, अनुमान लगाएं कि code क्या करेगाचुप रहता है - यह आपका अनुमान है
दौड़नाआरइसे चलाएँ और वास्तविक आउटपुट देखेंआपके लिए code निष्पादित करता है
जाँच करामैंअपने अनुमान की वास्तविकता से तुलना करें; क्यों पूछना*माँगने पर पंक्ति दर पंक्ति समझाता है
संशोधित करेंएमएक चीज़ बदलें, फिर से भविष्यवाणी करें, run फिर सेआपके द्वारा वर्णित संपादन करता है
बनानाएमआरंभ से अपना स्वयं का संस्करण निर्दिष्ट करें; चलो agent build इसे; सत्यापित करेंआपकी विशिष्टता के विरुद्ध उत्पन्न होता है

The PRIMM-AI+ loop: Predict, Run, and Investigate build reading fluency; Modify and Make direct the agent; the loop repeats. AI+ वह हिस्सा है जो इसे पुराने शिक्षण method का AI era संस्करण बनाता है। classic PRIMM के शीर्ष पर दो चीजें स्तरित हैं: agent हमेशा एक रीडिंग पार्टनर के रूप में उपलब्ध है ("पंक्ति 3 को समझाएं," "इसे क्या तोड़ेगा?"), और विश्वास पर कुछ भी स्वीकार नहीं किया जाता है। predict-run-investigate आपके पढ़ने के प्रवाह को बनाता है; मॉडिफाई-मेक वह जगह है जहां आप agent को निर्देशित करा शुरू करते हैं। अंत में, मेक उतना ही स्वाभाविक लगता है जितना अब प्रेडिक्ट लगता है।

जहां परीक्षण फिट बैठता है: हर जगह। वह इंजन जो जांच, संशोधित, और बनाने को शक्ति प्रदान करता है वह test है: एक छोटी जांच जो "सही" का अर्थ बताती है, ताकि कंप्यूटर agent के काम को सत्यापित कर सके बजाय इसके कि आप उस पर नजर रखें। यह ऐसा कदम नहीं है जो आप अंत में एक बार करते हैं। आपके द्वारा पढ़े जाने वाले अगले function से शुरू करते हुए, एक छोटा test चलता है: पहले एक एकल assert पंक्ति (संकल्पना 5) के रूप में, फिर वस्तुओं पर (संकल्पना 8) और सत्यापन नियम (संकल्पना 11), और अंत में पूर्ण Test-Driven Generation loop के रूप में जहां आप test पहले लिखते हैं और agent इसे पारित करे के लिए code लिखते हैं (संकल्पना 16)। आपके हाथ में आए code के agent के प्रत्येक टुकड़े को तब तक अविश्वसनीय मानें जब तक कि आपके द्वारा लिखा गया test कुछ और न कहे।

भविष्यवाणी वैकल्पिक नहीं है

सहज प्रवृत्ति सीधे run पर जाने की है: बस उत्तर देखें। नहीं। आपकी भविष्यवाणी और वास्तविक आउटपुट के बीच का अंतर वह जगह है जहां सीखना होता है। एक गलत भविष्यवाणी आपको सटीक रूप से बताती है कि आपके मानसिक model का कौन सा हिस्सा टूटा हुआ है, एक सही भविष्यवाणी से कहीं बेहतर। ज़ोर से, लिखित रूप में, या agent पर भविष्यवाणी करें। फिर run.

3. पांच मिनट में आपका कार्यक्षेत्र

ठंड आ रही है? पहले agent प्राप्त करें

यह कोर्स मानता है कि आपने Agentic Coding कोचिंग कोर्स किया है, जहां आप install करते हैं और agent चलाना सीखते हैं। यदि आप सीधे यहां पहुंच गए हैं और अभी तक कुछ भी install नहीं किया है, तो आगे जाने से पहले एक coding agent सेट करें। वह एकल tool आपके लिए बाकी सब कुछ install कर देगा:

  • Claude Code: docs.claude.com/en/docs/claude-code पर आधिकारिक गाइड का पालन करें (WSL के माध्यम से macOS, Linux और Windows पर काम करता है)।
  • OpenCode (open-source विकल्प): opencode.ai
  • uv (Python स्वयं + package): docs.astral.sh/uv; या बस अगले चरण में इसे आपके लिए agent install करे दें।

आपको इनमें से किसी भी tools को गहराई से समझने की आवश्यकता नहीं है। एक agent, open इसे folder में install करें, और जारी रखें। इस अनुभाग के शेष भाग में agent और setup हैं।

आपको तीन चीज़ों की ज़रूरत है: run Python का एक रास्ता, कुछ गुणवत्ता वाले tools, और आपका agent। एक installer पहले दो को कवर करता है: uv, एक तेज़ package प्रबंधक जो Python को स्वयं install करता है और आपके Project का प्रबंधन करता है।

इन्हें स्मृति से हाथ से install न करें - यह बिल्कुल उसी प्रकार का विचित्र setup है जिसमें agent अच्छा है। folder में जहां आपने अपना agent खोला है, उसे एक निर्देश दें:

uv का use करके यहां एक नया Python Project सेट करें। परीक्षणों के लिए pytest, प्रकार की जाँच के लिए pyright और फ़ॉर्मेटिंग के लिए ruff जोड़ें। एक hello.py बनाएं जो "रेडी" प्रिंट करे। फिर इसे run करें और मुझे आउटपुट दिखाएं।

agent run को uv command देगा, files और run को script बनाएगा। आप प्रत्येक चरण को देखें और अनुमोदित करें। वह आपका कार्यक्षेत्र है। आपने एक भी command याद नहीं किया.

इन्हें स्मृति से हाथ से install न करें - यह बिल्कुल उसी प्रकार का विचित्र setup है जिसमें agent अच्छा है। folder में जहां आपने अपना agent खोला है, उसे एक निर्देश दें:

uv का use करके यहां एक नया Python Project सेट करें। परीक्षणों के लिए pytest, प्रकार की जाँच के लिए pyright और फ़ॉर्मेटिंग के लिए ruff जोड़ें। एक hello.py बनाएं जो "रेडी" प्रिंट करे। फिर इसे run करें और मुझे आउटपुट दिखाएं।

OpenCode run को uv command देगा, files और run को script बनाएगा। आप प्रत्येक चरण को देखें और अनुमोदित करें। वह आपका कार्यक्षेत्र है। आपने एक भी command याद नहीं किया.

वह वास्तव में कैसा दिखता है

आप चुपचाप मत देखें. agent प्रत्येक चरण का वर्णन करता है और कुछ भी चलाने से पहले पूछता है। एक वास्तविक सत्र लगभग इस तरह दिखता है (Claude Code दिखाया गया है; OpenCode लगभग समान है):

> Set up a new Python project here using uv. Add pytest, pyright, ruff.
Create a hello.py that prints "ready", run it, and show the output.

● I'll initialize the project with uv.
$ uv init . ← the agent proposes a command
Allow? (y/n) y ← you approve
Initialized project

● $ uv add --dev pytest pyright ruff
Allow? (y/n) y
+ pytest + pyright + ruff

● Created hello.py:
print("ready")

● $ uv run hello.py ← this is how a Python file gets run
ready ← the output prints right here

Done. Your workbench is ready.

ध्यान देने योग्य तीन बातें, क्योंकि वे शारीरिक loop हैं जिन्हें आप सभी पाठ्यक्रम में दोहराएंगे:

  • code file (hello.py) में रहता है, चैट विंडो में नहीं।
  • आप run को file के साथ uv run hello.py: वह एक command इस पाठ्यक्रम में प्रत्येक script और उदाहरण को निष्पादित करता है।
  • agent प्रत्येक command से पहले अनुमति मांगता है, फिर नीचे आउटपुट प्रिंट करता है। आप अनुमोदन करें, आप परिणाम पढ़ें।

So whenever an example below says "run यह," you have two easy options: paste the code into a file and tell the agent "run यह file और मुझे आउटपुट दिखाओ," or simply paste the snippet into the chat and say "run यह और मुझे दिखाओ कि यह क्या प्रिंट करता है।" Either way, you never type Python by hand.

If setup fails — you don't debug it, the agent does

If any step throws a red error, you do not need to understand it. Copy the red text, paste it back, and say: "यह विफल रहा. त्रुटि पढ़ें और उसे ठीक करें." If the agent reports that uv isn't installed, ask it to install uv first. Getting unstuck is the agent's job; noticing that you're stuck is yours.

Here is what each tool does, in one line. You will see all four mentioned constantly from here on:

ToolWhat it does for you
uvInstalls Python and your project's packages, fast
pytestRuns your tests and reports which passed and which failed
PyrightReads the type labels in the code and flags mismatches before you ever run it
RuffChecks style and formatting — a spell-checker for code
Why this matters for reading

Pyright and Ruff are reading machines. When the agent generates code, these tools read it for you and catch a whole class of mistakes instantly: a wrong type, an unused variable, a typo'd name. They are your first line of verification, before you even read a line yourself. (Full setup walkthrough: Programming in the AI Era, Phase 1: The Workbench.)

देखें कि आपकी पढ़ने वाली मशीनें कुछ पकड़ती हैं

ये tools अमूर्त नहीं हैं। agent को एक छोटा function लिखने के लिए कहें और फिर इसे गलत प्रकार के मान से कॉल करें:

def total_with_tax(price: float, tax_rate: float) -> float:
return price + (price * tax_rate)

total_with_tax("100", 0.15) # oops — "100" is text, not a number

इस पर pyright चलाएँ और आपको यह code निष्पादित होने से पहले मिल जाएगा:

error: Argument of type "Literal['100']" cannot be assigned to
parameter "price" of type "float" (reportArgumentType)

Pyright ने type hints पढ़ा, देखा कि पाठ वहां पारित किया गया जहां float का वादा किया गया था, और बेमेल को तुरंत पकड़ लिया। Ruff स्लिप का एक अलग class पकड़ता है: बचा हुआ अव्यवस्था agent कभी-कभी पीछे छूट जाता है:

F401  `os` imported but unused

आप इन संदेशों को याद नहीं रखते. आप उन्हें वैसे ही पढ़ते हैं जैसे आप किसी वर्तनी-जांचकर्ता की रेखांकित पंक्ति को पढ़ते हैं: यहां कुछ फिट नहीं बैठता है, और यह सटीक रेखा की ओर इशारा कर रहा है। जब agent सौ पंक्तियां उत्पन्न करता है, तो ये दो tools एक सेकंड के भीतर इसे पूरा पढ़ लेते हैं, यही कारण है कि वे run इससे पहले कि आप स्वयं पढ़ना शुरू करें।


भाग 2: वे आकृतियाँ जो आपको हर जगह दिखाई देंगी

ये मूल आकृतियाँ हैं जो संभवतः आपके द्वारा पढ़े गए सभी Python का 70% बनाती हैं। भविष्यवाणी → चलाएँ → जांच के साथ प्रत्येक के माध्यम से आगे बढ़ें: इसे पढ़ें, आउटपुट का अनुमान लगाएं, फिर जांचने के लिए इसे अपने सत्र में run करें।

4. मान, चर और चार प्रकार

A variable एक लेबल वाला बॉक्स है जिसमें एक मान होता है। = चिह्न का अर्थ है "दाईं ओर के मान को बाईं ओर के बॉक्स में डालें": यह गणित के अर्थ में "बराबर" नहीं है। प्रत्येक मान का एक प्रकार होता है, और अभी केवल चार मानों को आपको पहचानने की आवश्यकता है। हम नाम के ठीक बाद प्रकार लिखते हैं, name: type, ताकि आप और agent दोनों एक नज़र में देख सकें कि प्रत्येक बॉक्स में क्या रखा जाना है:

name: str = "Ayesha"        # str   — text, always in quotes
age: int = 30 # int — a whole number
price: float = 19.99 # float — a number with a decimal point
is_active: bool = True # bool — only ever True or False

: str, : int, : float, : bool भाग type hints हैं। वे Python में वैकल्पिक हैं, लेकिन इस पूरे पाठ्यक्रम में हम उन्हें हमेशा शामिल करते हैं: आंशिक रूप से क्योंकि वे code को पढ़ना आसान बनाते हैं, और आंशिक रूप से क्योंकि, जैसा कि आप संकल्पना 10 में देखेंगे, वे इस तरह हैं कि आप agent को बताते हैं कि build को वास्तव में क्या करा है। अभी के लिए, name: str को सामान्य अंग्रेजी के रूप में पढ़ें: "बॉक्स name में टेक्स्ट है।"

भविष्यवाणी: आपको क्या लगता है कि यह क्या छापता है?

age: int = 30
age = age + 1
print(age)

इसे चलाएँ। आउटपुट 31 है। जांच करें: यदि आप = को "बराबर" के रूप में पढ़ते हैं तो पंक्ति age = age + 1 असंभव लगती है: 30, 31 के बराबर नहीं हो सकता। लेकिन = का अर्थ है असाइन: age (30) का वर्तमान मान लें, 1 जोड़ें, और परिणाम (31) को वापस बॉक्स में डालें। दाहिनी ओर पहले चलता है, फिर बॉक्स को update किया जाता है। (ध्यान दें कि हमने केवल टाइप संकेत : int तब लिखा था जब पहली बार age प्रदर्शित हुआ था; एक बार बॉक्स में टाइप हो जाने के बाद, आप इसे हर पुन: असाइनमेंट पर नहीं दोहराते हैं।) यह विचार शुरुआत में लगभग सभी को पसंद आता है, यही कारण है कि आपने पहले इसकी भविष्यवाणी की थी।

पढ़ने की चाल

जब आप x = something देखें, तो इसे दाएं से बाएं पढ़ें: "something की गणना करें, फिर इसे x में संग्रहीत करें।" बायीं ओर का नाम सिर्फ एक लेबल है।

5. कार्य और उनके हस्ताक्षर

A function एक नाम के साथ code का पुन: प्रयोज्य ब्लॉक है। आप इसे इनपुट देते हैं (जिन्हें तर्क कहा जाता है), यह आपको आउटपुट देता है। पहली पंक्ति, हस्ताक्षर, सबसे महत्वपूर्ण पंक्ति है जिसे आप पढ़ना सीखेंगे, क्योंकि यह एक अनुबंध है:

def total_with_tax(price: float, tax_rate: float) -> float:
return price + (price * tax_rate)

हस्ताक्षर को टुकड़े-टुकड़े करके पढ़ें:

  • def: "मैं function को परिभाषित कर रहा हूं।"
  • total_with_tax: इसका नाम.
  • (price: float, tax_rate: float): इसमें दो इनपुट लगते हैं, दोनों दशमलव। : float भाग एक प्रकार का संकेत है (संकल्पना 10 में इनके बारे में अधिक जानकारी)।
  • -> float: यह एक दशमलव देता है।

एक सांस में: "मुझे मूल्य और कर की दर, दोनों दशमलव दें, और मैं आपको दशमलव वापस दे दूंगा।" आप समझ सकते हैं कि function क्या वादा करता है इसके मुख्य भाग की एक भी पंक्ति पढ़े बिना। इसीलिए जब आप AI code का सत्यापन कर रहे हों तो हस्ताक्षर बहुत मायने रखते हैं। शरीर ग़लत हो सकता है; हस्ताक्षर आपको बताता है कि उसे क्या करा चाहिए था।

भविष्यवाणी करें, फिर run:

def total_with_tax(price: float, tax_rate: float) -> float:
return price + (price * tax_rate)

print(total_with_tax(100.0, 0.15))

आउटपुट: 115.0. यदि आपने 115.0 की भविष्यवाणी की है, तो आप पहले से ही function पढ़ सकते हैं।

इसे test से पिन करें

function पहली चीज़ है जिसे आप सही साबित कर सकते हैं, क्योंकि इसका एक स्पष्ट अनुबंध है: इन इनपुटों को देखते हुए, इसका आउटपुट return होना चाहिए। आप इसे assert से बंद कर देते हैं: एक पंक्ति का दावा जो सच होने पर कुछ नहीं करता है और गलत होने पर जोर से क्रैश हो जाता है:

assert total_with_tax(100.0, 0.15) == 115.0   # "I claim this must equal 115.0"
assert total_with_tax(0.0, 0.15) == 0.0 # a free item costs nothing

उन दो पंक्तियों को चलाएँ और आपको कुछ नहीं दिखाई देगा। मौन का मतलब है हर दावा बरकरार। 115.0 को 999.0 में बदलें और यह तुरंत क्रैश हो जाता है। परीक्षण के पीछे का पूरा विचार यही है: आप एक बार सही मतलब लिखते हैं, और कंप्यूटर हर बार आपके लिए इसे दोबारा जांचता है। ये दो पंक्तियां पहले से ही एक छोटी विशिष्टता हैं। उन्हें पकड़ो. संकल्पना 16 में आप इन सटीक दावों को agent को सौंपेंगे और उन्हें संतुष्ट करे के लिए function लिखेंगे। (यह कोई दुर्घटना नहीं है: वही कर function पूर्ण TDG चक्र के रूप में पुनः प्रकट होता है।)

6. संग्रह: समूहीकरण data

वास्तविक code में एकल मान दुर्लभ हैं। अधिकांश data समूहों में आते हैं, और चार कंटेनर हैं जिन्हें आप बार-बार देखेंगे:

notes: list[str] = ["buy milk", "call Sara", "finish report"]   # list  — ordered, can change
note: dict[str, str | bool] = {"title": "Meeting", "done": False} # dict — labeled pairs (key: value)
tags: set[str] = {"work", "urgent"} # set — unique items, no duplicates
point: tuple[int, int] = (3, 5) # tuple — ordered, cannot change

Hints बताते हैं कि container के अंदर क्या है: list[str] “text की list” है, dict[str, str | bool] “ऐसा dict है जिसकी keys text हैं और values या तो text या true/false हैं” (| का मतलब “or” है), set[str] “text का set” है, और tuple[int, int] “पूरे numbers की pair” है। आपको इन्हें memory से लिखना नहीं है। आपको इन्हें पढ़ना है।

आप जिन दो से सबसे अधिक मिलेंगे वे हैं list (एक अनुक्रम जिसे आप जोड़ सकते हैं और पुनः व्यवस्थित कर सकते हैं) और dict (लेबल किए गए मानों का एक सेट: data के लगभग हर टुकड़े की रीढ़ AI agent चारों ओर से गुजरती है, क्योंकि यह सीधे JSON पर मैप होता है)।

भविष्यवाणी करें, फिर run:

note: dict[str, str | bool] = {"title": "Meeting", "done": False}
print(note["title"])
note["done"] = True
print(note)

आउटपुट:

Meeting
{'title': 'Meeting', 'done': True}

जांच करें: note["title"] निर्देशांक में पहुंचता है और "title" लेबल वाला मान निकालता है। दूसरी पंक्ति "done" लेबल वाले मान को बदलती है। एक निर्देश यह है कि agent आपको एक नोट, एक user, एक API response: नामित फ़ील्ड के साथ कुछ भी देगा।

7. प्रवाह और समझ को नियंत्रित करें

code if के साथ निर्णय लेता है, और for के साथ दोहराता है। इंडेंटेशन (एक पंक्ति के आरंभ में रिक्त स्थान) से Python को पता चलता है कि if या for के अंदर क्या है। यह सजावट नहीं, संरचना है।

prices: list[int] = [10, 250, 50, 400]

for price in prices: # do this once for each price in the list
if price > 100: # decision
print(f"{price} is expensive")
else:
print(f"{price} is fine")

भविष्यवाणी करें आपके run से पहले कौन सी लाइनें "महंगी" प्रिंट करती हैं। (उत्तर: 250 और 400.)

उनमें से दो पंक्तियाँ एक f-string: टेक्स्ट का use करती हैं जिसके सामने f है, जहां {...} के अंदर कुछ भी उसके मान से बदल दिया जाता है। तो f"{price} is expensive" वर्तमान price को वाक्य में छोड़ देता है। आप लगातार f-strings देखेंगे; बस यह पहचानें कि {name} का अर्थ है "इस मान का टेक्स्ट यहां रखें।"

जब किसी निर्णय के दो से अधिक परिणाम होते हैं, तो elif ("और यदि" का संक्षिप्त रूप) उन्हें श्रृंखलाबद्ध करता है। Python प्रत्येक branch को ऊपर से नीचे तक जाँचता है और पहला चलाता है जो सत्य है:

def grade_for(score: int) -> str:
if score >= 90:
return "A"
elif score >= 70:
return "B"
elif score >= 50:
return "C"
else:
return "F"

भविष्यवाणी grade_for(72), फिर run. यह "B" है: 72 >= 90 गलत है, इसलिए यह अगले branch पर आ जाता है, 72 >= 70 सत्य है, और यह वहीं रुक जाता है। if/elif/else श्रृंखला को इस प्रकार पढ़ें "इन्हें क्रम से जांचें; पहला मिलान लें।" आप and और or के साथ संयुक्त स्थितियाँ भी देखेंगे - if score >= 70 and attended: का अर्थ है कि दोनों सत्य होने चाहिए - आपको "एकाधिक मानदंड" निर्णयों को पढ़ने के लिए बस इतना ही चाहिए।

एक बार जब आप for loop पढ़ सकते हैं, तो आप Python में सबसे आम एक-पंक्ति पढ़ सकते हैं: समझ। यह सिर्फ एक for loop है जो एक लाइन पर build पर मुड़ा हुआ एक नया list है:

prices: list[int] = [10, 250, 50, 400]

# The long way:
expensive: list[int] = []
for price in prices:
if price > 100:
expensive.append(price)

# The comprehension — exactly the same result:
expensive = [price for price in prices if price > 100]

लंबे संस्करण में .append(price) price को list के अंत में जोड़ता है; वह thing.action() आकार वह method कॉल है जो आपको कॉन्सेप्ट 8 में मिलेगी। समझ को बाएं से दाएं पढ़ें: "मुझे prices में प्रत्येक price के लिए price दें, यदि price > 100।" दोनों [250, 400] उत्पन्न करते हैं। आप AI code में हर जगह समझ देखेंगे क्योंकि data सफाई और पुन: आकार देना अधिकांश काम है। इस आकृति को पहचानने में सहज हो जाएं और आप बड़ी मात्रा में वास्तविक Python पढ़ सकते हैं।

रीडिंग पार्टनर के रूप में agent का use करें

कोई भी पंक्ति जो आपको समझ में न आए उसे अपने सत्र में चिपकाएँ: "इस पंक्ति को ऐसे समझाएँ जैसे कि मैंने कभी code नहीं किया है: [n['text'] for n in notes if n['done']]।" यह माँग पर PRIMM-AI+ का जांच चरण है। इसे लगातार प्रयोग करें. यह किसी भी संदर्भ से तेज़ है.

8. कक्षाएं और वस्तुएं - एक खाका पढ़ना

अब तक आपका data ढीला रहा है: note एक निर्देश था, price एक फ्लोट था। A class आपको संबंधित data और क्रियाओं को एक नामित आकार में बंडल करे देता है। class को blueprint के रूप में और object (जिसे इंस्टेंस भी कहा जाता है) को उस blueprint से निर्मित चीज़ के रूप में सोचें: एक Note blueprint, उससे निर्मित कई वास्तविक नोट।

यहाँ एक class है जो models एक एकल नोट है:

class Note:
def __init__(self, title: str, body: str) -> None:
self.title = title # an attribute — data this note carries
self.body = body
self.done = False

def mark_done(self) -> None: # a method — an action this note can perform
self.done = True

इसे टुकड़ों में पढ़ें:

  • class Note:, blueprint को परिभाषित करता है, जिसका नाम Note है।
  • __init__: setup method। जब आप एक नया नोट build करते हैं, तो यह एक बार automatically चलता है, और शुरुआती data को संग्रहीत करता है। (-> None का अर्थ है कि यह कुछ भी वापस नहीं देता; यह केवल object को configure करता है।)
  • self: यह विशेष object। blueprint के अंदर, self.title का अर्थ है "यह नोट का शीर्षक।" प्रत्येक method पहले self लेता है ताकि उसे पता चले कि वह किस object पर काम कर रहा है।
  • self.title, self.body, self.done - features: प्रत्येक नोट में data होता है।
  • mark_done, एक method: एक function जो class के अंदर रहता है और object पर कार्य करता है।

अब build एक और इसका use करें। इससे पहले कि आप आउटपुट का अनुमान लगाएं इसे run करें:

n: Note = Note(title="Groceries", body="milk, eggs")
print(n.done)
n.mark_done()
print(n.done)

आउटपुट:

False
True

Investigate: Note(title="Groceries", body="milk, eggs") runs __init__ and hands back a finished object, stored in n. n.done reads an attribute; n.mark_done() calls a method that changes it. The dot (.) always means the same thing: "reach into this object for the thing named after it."

वह एक पैटर्न - object.attribute को पढ़ने के लिए data और object.method() को object को कुछ करे के लिए कहने के लिए - सबसे वास्तविक Python को अनलॉक करता है। agent code में आप जो कुछ भी पढ़ेंगे वह लगभग सब कुछ object है: एक Pydantic model एक class है, एक agent एक object है, एक database कनेक्शन एक object है। जब आप agent.run(task) या db.save(note) देखते हैं, तो आप पढ़ रहे होते हैं "इस object को run से इसके तरीकों में से एक पूछें।" (पूरा object model AI युग में संगम, चरण 5 है।)

इसे test से पिन करें

आप object को बिल्कुल वैसे ही सत्यापित करते हैं जैसे आपने संकल्पना 5 में function को सत्यापित किया था: assert method चलने से पहले और बाद में इसकी स्थिति क्या होनी चाहिए:

n: Note = Note(title="Groceries", body="milk, eggs")
assert n.done is False # a fresh note starts unfinished
n.mark_done()
assert n.done is True # ...and is finished after mark_done()

वही चाल, नया लक्ष्य: method सिर्फ function है जो object से जुड़ा हुआ है, इसलिए वही एक-पंक्ति assert यह साबित करती है कि यह व्यवहार करता है। जब agent आपके लिए class लिखता है, तो आप इस प्रकार जाँचते हैं कि यह वही करता है जो आपका मतलब था।

आप अभी तक कक्षाएं नहीं लिखते हैं - आप उन्हें पढ़ते हैं

इस पाठ्यक्रम की हर चीज़ की तरह, यहाँ भी लक्ष्य मान्यता है। जब agent एक class उत्पन्न करता है, तो आप उस पर इंगित करे में सक्षम होना चाहते हैं और कहते हैं "यह setup method है, ये इसके गुण हैं, यह एक method है जो इसकी स्थिति बदलता है।" यह सत्यापित करे के लिए पर्याप्त है कि यह वही करता है जो आपने पूछा था।

9. उत्पन्न code में आपको अधिक आकृतियाँ मिलेंगी: while, स्लाइसिंग, try/except, और input()

आप शायद ही कभी इन चारों को लिखेंगे, लेकिन agent इनका लगातार use करता है, इसलिए जब आप पढ़ रहे हों और इसके आउटपुट को सत्यापित कर रहे हों तो आपको उन्हें पहचानने की आवश्यकता है। एक त्वरित भविष्यवाणी → चलाएँ → प्रत्येक पर जाँच करा पर्याप्त है।

while: स्थिति बदलने तक दोहराएँ। जहाँ एक for loop संग्रह में प्रति आइटम एक बार चलता है, एक while loop तब तक चलता रहता है जब तक उसकी स्थिति सही रहती है:

count: int = 3
while count > 0: # keep looping while this is true
print(count)
count = count - 1
print("done")

भविष्यवाणी करें, फिर run. आउटपुट: 3, 2, 1, done। इसे इस प्रकार पढ़ें "count > 0 के दौरान ऐसा करते रहें।" उत्पन्न code में पहचानने लायक एक खतरा: यदि स्थिति कभी झूठी नहीं होती है, तो loop हमेशा के लिए चलता है, इसलिए जब आप while देखते हैं, तो उस पर नज़र डालें जो अंततः इसे बंद कर देता है।

स्लाइसिंग: list या string का एक टुकड़ा लें। वर्गाकार कोष्ठक के अंदर एक कोलन का अर्थ है "स्थितियों की एक श्रृंखला":

letters: list[str] = ["a", "b", "c", "d", "e"]
print(letters[1:3]) # from position 1 up to (not including) 3
print(letters[:2]) # the first two
print(letters[-1]) # the last one

भविष्यवाणी करें, फिर run. आउटपुट: ['b', 'c'], ['a', 'b'], e। गिनती 0 से शुरू होती है; [1:3] "1 से लेकर 3 तक नहीं" है; -1 का अर्थ है "आखिरी वाला।" पाठ पर समान वाक्यविन्यास काम करता है: "hello"[:3] "hel" है।

try / except: कुछ ऐसा प्रयास करें जो विफल हो सकता है। कुछ ऑपरेशन विफल हो सकते हैं: शून्य से विभाजित करा, गायब file को पढ़ना, नेटवर्क कॉल का समय समाप्त होना। try/except जोखिम भरा code चलाता है और क्रैश होने के बजाय त्रुटि पकड़ता है:

def safe_divide(a: float, b: float) -> float:
try:
return a / b
except ZeroDivisionError: # if dividing by zero is attempted...
return 0.0 # ...do this instead of crashing

भविष्यवाणी safe_divide(10.0, 2.0) और safe_divide(10.0, 0.0), फिर run. आउटपुट: 5.0 और 0.0। इसे इस प्रकार पढ़ें "इसे आज़माएं; यदि यह इस विशिष्ट तरीके से विफल हो जाता है, तो इसके बजाय ऐसा करें।" आप try/except को किसी भी चीज़ के चारों ओर लपेटा हुआ देखेंगे जो agent code में विफल हो सकता है।

input(): रुकें और पढ़ें कि user क्या टाइप करता है। इंटरैक्टिव scripts और command line tools व्यक्ति से प्रश्न पूछने और उत्तर की प्रतीक्षा करे के लिए input() का use करें:

name: str = input("What's your name? ")   # waits here until the user types and presses Enter
print(f"Hello, {name}!")

पहचानने वाली एक बात, और उत्पन्न होने वाली code अक्सर फिसल जाती है, वह यह है कि input() हमेशा टेक्स्ट लौटाता है, तब भी जब user कोई नंबर टाइप करता है। इसके साथ गणित करे के लिए, code को पहले इसे परिवर्तित करा होगा:

age_text: str = input("Your age? ")   # "30" comes back as text, not a number
age: int = int(age_text) # int(...) converts text to a whole number
print(f"Next year you'll be {age + 1}")

यदि आप कभी भी input() को बिना int(...) या float(...) के सीधे अंकगणित में फीड करते हुए देखते हैं, तो यह एक bug है जिसे चिह्नित किया जाना चाहिए: प्रोग्राम या तो टेक्स्ट को क्रैश कर देगा या जोड़ने के बजाय उसे एक साथ चिपका देगा।

इसे test से पिन करें

त्रुटि का मामला बिल्कुल उसी तरह का है जो पिन करे लायक है: assert कि खतरनाक इनपुट को नियंत्रित किया जाता है, क्रैश नहीं किया जाता है:

def test_safe_divide() -> None:
assert safe_divide(10.0, 2.0) == 5.0
assert safe_divide(10.0, 0.0) == 0.0 # handled, not a crash
सत्यापन के लिए ये क्यों मायने रखते हैं?

उत्पन्न code के सूक्ष्म रूप से गलत होने के लिए प्रत्येक एक सामान्य स्थान है: एक while जो कभी समाप्त नहीं होता है, एक टुकड़ा जो एक से अलग होता है ([1:3] आपको दो आइटम देता है, तीन नहीं), एक except जो चुपचाप उस त्रुटि को निगल जाता है जिसके बारे में आपको जानना आवश्यक है, या एक input() जिसका पाठ कभी भी गणित से पहले किसी संख्या में परिवर्तित नहीं होता है। आकृति को पहचानने से आप रुक सकते हैं और बिल्कुल उन स्थानों को करीब से देख सकते हैं।


भाग 3: AI era की शक्ति अवधारणाएँ

ये अवधारणाएँ वे हैं जो "हैलो वर्ल्ड" Python को Python से अलग करती हैं जिन्हें आप वास्तव में agent और ML code में देखेंगे। उनमें से अधिकांश को आप अभी तक शुरू से नहीं लिखेंगे; agent ऐसा करता है, और आपका लक्ष्य शुद्ध पहचान है: जब कोई आता है, तो आप जानते हैं कि यह किस लिए है और मोटे तौर पर यह क्या करता है। एक अपवाद पहला है, type hints (अवधारणा 10): वे जो आप लिखना सीखते हैं, क्योंकि वे इस प्रकार हैं कि आप agent को बिल्कुल वही बताते हैं जो build को है। (कई सीधे उस उत्पादन से लिए गए हैं जिसका use AI इंजीनियर प्रतिदिन करते हैं।)

केवल पढ़ने योग्य क्षेत्र - घबराएं नहीं

जानबूझ कर यहां गति तेज हो जाती है। दो पेज पहले आप पढ़ रहे थे age = age + 1; अब आप जनरेटर, सत्यापनकर्ता और async देखेंगे। वह ठीक है। आपसे इसमें से कुछ भी लिखने की अपेक्षा नहीं की जाती है। अवधारणाओं 11-15 के लिए आपका एकमात्र काम प्रत्येक आकृति को पहचानना और स्पष्ट अंग्रेजी में बताना है कि यह किस लिए है। यदि कोई ब्लॉक सघन दिखता है, तो एक-पंक्ति "इसे इस रूप में पढ़ें..." सारांश पढ़ें और आगे बढ़ें। इन्हें कोई याद नहीं रखता; आप उन्हें पहचानना सीखें.

10. संकेत टाइप करें - लेबल जो agent को संचालित करते हैं

आप संकल्पना 5 में एक से पहले ही मिल चुके हैं: price: floatप्रकार का संकेत एक लेबल है जो बताता है कि variable या function किस प्रकार की data की अपेक्षा करता है। Python को उनकी आवश्यकता नहीं है, लेकिन AI युग में वे आपके सबसे शक्तिशाली tool हैं, एक कारण से:

प्रकार के संकेत agent के लिए निर्देश हैं। जब आप इस तरह का हस्ताक्षर लिखते हैं पहले agent को इसे भरने के लिए कहते हैं -

def summarize_notes(notes: list[dict], max_words: int) -> str:
... # the agent writes this part
  • आपने इसे सटीक और स्पष्ट रूप से बताया है, कि इनपुट डिक्ट्स का list है, एक शब्द सीमा है जो एक पूर्ण संख्या है, और आउटपुट एक एकल string है। agent अब अधिक बार सही चीज़ उत्पन्न करता है, क्योंकि आपने अनुमान हटा दिया है। और Pyright इन लेबलों को पढ़ता है और code के चलने से पहले किसी भी बेमेल को चिह्नित करता है।

TDG शब्दों में (AI युग में प्रोग्रामिंग में पूरी तरह से कवर किया गया), प्रकार लिखना विनिर्देश लिखने का हिस्सा है। यह पहला 10% है जो आपका है।

एक अच्छे "इसे उत्पन्न करें" की शारीरिक रचना request

चूंकि प्रकार निर्देश हैं, सबसे मजबूत code request agent को तीन चीजें सौंपते हैं और चौथा मांगते हैं:

  1. हस्ताक्षर, प्रकार सहित: summarize_notes(notes: list[dict], max_words: int) -> str। यह इनपुट और आउटपुट को पिन करता है ताकि कोई अनुमान न लगे।
  2. इनपुट → आउटपुट के एक या दो उदाहरण। (ये आपके परीक्षणों से दोगुने हैं।)
  3. कोई भी बाधा: "खाली list को संभालना होगा," "नेटवर्क पर कॉल न करें," "इसे 20 लाइनों के नीचे रखें।"
  4. इसे सत्यापित करे के लिए कहें: "फिर run pytest और pyright और मुझे परिणाम दिखाओ।"

एक अस्पष्ट request ("नोट्स को सारांशित करे के लिए कुछ लिखें") अस्पष्ट code हो जाता है। एक टाइप किए गए हस्ताक्षर और एक उदाहरण से code मिलता है जिसे आप वास्तव में जांच सकते हैं। और जब परिणाम गलत हो, केवल पुनः प्रयास न करें: paste विफल आउटपुट और कहें कि क्या गलत है: "यह एक खाली list पर क्रैश हो जाता है। उसे संभालें।" एक सूचित सुधार दस ब्लाइंड री-रोल को मात देता है।

11. dataclass और Pydantic - संरचित, मान्य data

एक कच्चा निर्देश ({"learning_rate": 0.001}) लचीला है लेकिन खतरनाक है: टाइप की गई key या गलत प्रकार चुपचाप गुजरता है और डाउनस्ट्रीम में सब कुछ दूषित कर देता है। दो tools इसे ठीक करें।

पहले एक install

Pydantic को Python में नहीं बनाया गया है, इसलिए नीचे दिए गए उदाहरणों में इसे आपके Project में एक बार जोड़ने की आवश्यकता है: अपने agent को बताएं "इस Project में पाइडेंटिक जोड़ें" (यह uv add pydantic चलाता है)। dataclass अंतर्निर्मित है और उसे किसी चीज़ की आवश्यकता नहीं है।

एक dataclass आपके data को एक परिभाषित आकार देता है। यह कॉन्सेप्ट 8 से वही Note है। लेकिन ध्यान दें कि कोई __init__ नहीं है: @dataclass लाइन आपके लिए setup method *लिखती है, इसलिए आप केवल list features और उनके प्रकार लिखते हैं।

from dataclasses import dataclass

@dataclass
class Note:
title: str
body: str
done: bool = False # default value

Pydantic आगे बढ़ता है: यह runtime पर data को मान्य करता है और जो भी फिट नहीं बैठता है उसे अस्वीकार कर देता है:

from pydantic import BaseModel, Field

class ModelConfig(BaseModel):
learning_rate: float = Field(gt=0.0, lt=1.0) # must be between 0 and 1
batch_size: int = Field(gt=0) # must be positive

यदि आप build को learning_rate=-0.05 के साथ ModelConfig करे का प्रयास करते हैं, तो Pydantic एक स्पष्ट त्रुटि उत्पन्न करता है तुरंत बजाय टूटे हुए मूल्य को run घंटे बाद प्रशिक्षण में जहर देने के लिए। यही कारण है कि Pydantic agent code में हर जगह है: यह JSON स्कीमा को भी स्वतः उत्पन्न करता है जिसका use LLMs tool कॉलिंग के लिए करता है। जैसे ही आप शुरू करेंगे आप उससे दोबारा मिलेंगे building agents

इसे test से पिन करें

एक Pydantic model अनिवार्य रूप से एक test है जो हर बार आपके प्रोग्राम के चलने पर चलता है। लेकिन आपको अभी भी उस व्यवहार को पिन करा चाहिए जिसकी आप परवाह करते हैं, जिसमें त्रुटि मामले भी शामिल हैं। अब तक आपने दावा किया है कि कुछ सत्य है; यहां आप assert हैं कि खराब इनपुट को pytest.raises का use करके अस्वीकार किया जाना चाहिए:

import pytest
from pydantic import ValidationError

def test_rejects_negative_learning_rate() -> None:
with pytest.raises(ValidationError): # the block below MUST raise this error
ModelConfig(learning_rate=-0.05, batch_size=32)

यह test तभी पास होता है जब ख़राब कॉन्फिगरेशन अस्वीकार कर दिया जाता है। विफलताओं का परीक्षण करा उतना ही मायने रखता है जितना कि सफलताओं का परीक्षण करा: agent ख़ुशी से सत्यापन उत्पन्न करेगा जो सख्त दिखता है लेकिन चुपचाप खराब data को जाने देता है, और test को "बढ़ाना होगा" यह वह तरीका है जिसे आप पकड़ते हैं।

@dataclass लाइन एक डेकोरेटर है

function या class के ऊपर की रेखा पर वह @ प्रतीक एक डेकोरेटर है: एक लेबल जो उसके बाद आने वाली चीज़ों में व्यवहार जोड़ता है, बिना उस व्यवहार को लिखे। @dataclass automatically class को एक कंस्ट्रक्टर और एक पठनीय प्रिंटआउट देता है। आपको अभी तक डेकोरेटर लिखने की आवश्यकता नहीं है; बस यह पहचानें कि @something का अर्थ है "अगली चीज़ को अतिरिक्त शक्तियों से लपेटें।"

12. जेनरेटर और yield - मेमोरी ख़त्म हुए बिना स्ट्रीमिंग

जब code को एक लाख रिकॉर्ड संसाधित करे की आवश्यकता होती है, तो उन सभी को एक बार में list में लोड करे से आपके कंप्यूटर की मेमोरी समाप्त हो सकती है। एक जनरेटर मांग पर एक समय में एक आइटम वापस सौंपकर इसका समाधान करता है। देखने लायक संकेत return के बजाय कीवर्ड yield है:

from collections.abc import Iterator

def stream_notes(lines: list[str]) -> Iterator[str]:
for line in lines:
yield line.strip().lower() # hand back one item, then pause

return प्रकार Iterator[str] एक जनरेटर का स्पष्ट संकेत है: यह list[str] (एक तैयार ढेर) का वादा नहीं करता है। यह एक इटरेटर का वादा करता है, एक स्ट्रीम जिसे आप एक समय में एक आइटम से खींचते हैं।

return के साथ एक सामान्य function संपूर्ण परिणाम बनाता है और इसे एक गांठ में सौंप देता है। yield वाला जनरेटर प्रत्येक आइटम के बाद रुक जाता है और पूछे जाने पर ही अगला कार्य करता है। भुगतान वास्तविक है: एक बड़े dataset को list में लोड करे के बजाय जनरेटर के माध्यम से स्ट्रीम करे से चरम मेमोरी में नाटकीय रूप से कटौती हो सकती है, क्योंकि आप कभी भी पूरी चीज़ को एक साथ नहीं रखते हैं। जब आप yield देखें, तो इसे इस प्रकार पढ़ें: "यह एक धारा उत्पन्न करता है, ढेर नहीं।"

13. with — open और चीजों को सुरक्षित रूप से बंद करें

files, database कनेक्शन, नेटवर्क सत्र - कुछ भी जिसे खोला जाना चाहिए और फिर विश्वसनीय रूप से बंद किया जाना चाहिए, भले ही बीच में कुछ क्रैश हो जाए - with कथन का use करता है:

with open("notes.txt") as file:
contents: str = file.read()
# the file is automatically closed here, even if an error happened above

प्रबंधित की जा रही चीज़ (यहाँ, file) को इंडेंटेड ब्लॉक समाप्त होने पर साफ़ करे की गारंटी दी जाती है। AI code में आप with को GPU स्थिति, model मूल्यांकन मोड और टाइमर के चारों ओर लपेटा हुआ देखेंगे। जब आप with देखें, तो इसे इस प्रकार पढ़ें: "कुछ install करें, इसे इस ब्लॉक के अंदर use करें, और चाहे कुछ भी हो, इसे सुरक्षित रूप से फाड़ दें।"

14. async / await - एक साथ कई चीज़ें

जब एक agent 20 API कॉल करता है, तो उन्हें एक के बाद एक करे का अर्थ है 20 बार प्रतीक्षा करा। एसिंक्रोनस code प्रोग्राम को सभी requests को सक्रिय करे देता है और प्रतिक्रियाएँ आते ही उन्हें संभालने देता है: एक-एक करके 20 कतारों में खड़े होने और एक साथ सभी 20 में शामिल होने के बीच का अंतर। संकेत कीवर्ड async और await हैं:

async def query_llm(prompt: str) -> str:
response = await call_the_api(prompt) # pause here, let other work proceed
return response

एक उदाहरण के रूप में: यदि 20 API कॉलों में प्रत्येक को लगभग 0.1 सेकंड लगते हैं, तो उन्हें एक के बाद एक चलाने में लगभग 2 सेकंड लगते हैं, जबकि उन्हें async के साथ समवर्ती रूप से चलाने पर सबसे धीमी एकल कॉल के समय में समाप्त हो सकती है, क्योंकि कुल को सबसे धीमी कॉल द्वारा सीमित किया जाता है, योग से नहीं। आपको अभी तक async code लिखने की आवश्यकता नहीं है। बस पहचानें: async/await का अर्थ है "यह code एक ही समय में कई धीमी गति से काम करे के लिए बनाया गया है।" जब आप build agents होंगे तो आप इस पर बहुत अधिक भरोसा करेंगे।

15. डंडर विधियाँ - model(x) क्यों काम करती हैं

सबसे अजीब दिखने वाली चीज़ जो आप पढ़ेंगे वह एक method है जिसके प्रत्येक तरफ डबल अंडरस्कोर है, जैसे __init__ या __call__। इनका उपनाम "डंडर्स" (डबल-अंडरस्कोर) है, और आप पहले ही एक से मिल चुके हैं: कॉन्सेप्ट 8 का __init__ setup method एक डंडर है। वे विशेष विधियाँ हैं जो आपकी अपनी वस्तुओं को अंतर्निहित वस्तुओं की तरह व्यवहार करे देती हैं।

class Pipeline:
def __init__(self, factor: float) -> None: # runs when you create the object
self.factor = factor

def __call__(self, x: float) -> float: # runs when you "call" the object like a function
return x * self.factor

pipeline = Pipeline(2.5)
print(pipeline(10.0)) # prints 25.0 — the object is called like a function

__init__ एक नया object सेट करता है; __call__ वह है जो pipeline(10.0) को ऐसे काम करता है जैसे कि object एक function हो। यही कारण है कि, PyTorch और समान पुस्तकालयों में, आप model(x) लिखते हैं, न कि model.forward(x): framework चलने से पहले महत्वपूर्ण setup करे के लिए __call__ को परिभाषित करता है। जब आप डंडर्स देखें, तो उन्हें इस प्रकार पढ़ें: "इस object को एक देशी Python चीज़ की तरह कार्य करा सिखाया जा रहा है।"

आपने अभी पढ़ना सीखा AI code

रुकें और ध्यान दें कि क्या हुआ। आप अभी तक किसी रिक्त पृष्ठ से जेनरेटर या async function लिख नहीं सकते। और आपको इसकी आवश्यकता नहीं है. लेकिन अब आप open a file agent उत्पन्न कर सकते हैं और पहचान सकते हैं: "यह अपनी विशेषताओं और विधियों के साथ एक class है, यह एक प्रकार का संकेत है, यह एक Pydantic model है जो tool स्कीमा को परिभाषित करता है, यह एक जनरेटर स्ट्रीमिंग data है, कि with ब्लॉक एक संसाधन का प्रबंधन करता है, ये डंडर एक कस्टम dataset बनाते हैं।" वह पहचान वह सत्यापन Skill है जिस पर पूरी पुस्तक निर्भर करती है।


भाग 4: TDG loop, अंत से अंत तक

आपने पूरे भाग 2 और 3 में predict-run-investigate कर लिया है। अब PRIMM-AI+ के अंतिम दो अक्षर, संशोधित करें और बनाएँ, जो एक साथ Test-Driven Generation (TDG) चक्र हैं: method जो AI युग में प्रोग्रामिंग को परिभाषित करता है।

16. एक पूर्ण चक्र, आपके tool में

TDG पुराने ऑर्डर को उलट देता है। इसके बजाय लिखें code → शायद test इसे, आप जाएं: एक असफल test लिखें जो "सही" को परिभाषित करता है → agent को code उत्पन्न करे दें → run को test सत्यापित करे के लिए। test कोई बाद का विचार नहीं है; यह विनिर्देश है। और यह आपकी ओर से आना चाहिए, क्योंकि यदि आप agent को code और test दोनों लिखने देते हैं, तो आप AI के कार्य को AI की अपनी अपेक्षाओं के विरुद्ध जाँच रहे हैं: कोई स्वतंत्र संकेत नहीं।

यहां संकल्पना 5 से कर function पर चक्र दिया गया है। अपने सत्र में इसका पालन करें। The Test-Driven Generation loop: you write a failing test, the agent generates the code, you run the tests and verify; if a test is red you refine and repeat, if green you ship.

चरण 1: आप आवश्यकता को असफल परीक्षणों के रूप में लिखते हैं। test_tax.py बनाएं:

from tax import total_with_tax

def test_basic() -> None:
assert total_with_tax(100.0, 0.15) == 115.0

def test_zero_price() -> None:
assert total_with_tax(0.0, 0.15) == 0.0

आपने ये सटीक दावे पहले भी देखे हैं। वे दो पंक्तियाँ हैं जो आपने अवधारणा 5 में लिखी थीं, अब test_*.py file में स्थानांतरित हो गई हैं ताकि pytest उन्हें automatically run कर सकें। assert X == Y का अर्थ है "मैं घोषणा कर रहा हूं कि X को Y के बराबर होना चाहिए; यदि ऐसा नहीं होता है तो ज़ोर से विफल हो जाएं।" किसी code के अस्तित्व में आने से पहले ये दो पंक्तियाँ परिभाषित करती हैं कि क्या सही अर्थ है। अभी pytest चलाएँ और यह विफल हो जाता है: अभी तक कोई tax.py नहीं है। वह विफलता ही मुख्य बात है। आपके पास पूर्ण की एक सटीक, निष्पादन योग्य परिभाषा है।

केवल एक चीज जो यहां नई है वह क्रम है: अवधारणाओं 5, 8, और 11 में आपने code के लिए test लिखा है जो पहले से मौजूद है। सही TDG में आप असफल test पहले लिखते हैं, फिर इसे पास करे के लिए agent को code उत्पन्न करते हैं। test बाद में आपके लिए run की जांच करा बंद कर देता है और विनिर्देश बन जाता है जिसके विरुद्ध agent बनाता है।

चरण 2: agent कार्यान्वयन उत्पन्न करता है। अब अपने tool को निर्देश दें:

test_tax.py पढ़ें. total_with_tax(price: float, tax_rate: float) -> float function के साथ tax.py बनाएं जो दोनों परीक्षणों को पास कर दे। फिर run pytest और मुझे परिणाम दिखाओ।

Claude Code आपके परीक्षण पढ़ता है, tax.py लिखता है, और pytest चलाता है। क्योंकि आपने ने परीक्षण लिखे थे, आपके पास इस बात की स्वतंत्र जांच है कि इससे क्या हुआ।

test_tax.py पढ़ें. total_with_tax(price: float, tax_rate: float) -> float function के साथ tax.py बनाएं जो दोनों परीक्षणों को पास कर दे। फिर run pytest और मुझे परिणाम दिखाओ।

OpenCode आपके परीक्षण पढ़ता है, tax.py लिखता है, और pytest चलाता है। क्योंकि आपने ने परीक्षण लिखे थे, आपके पास इस बात की स्वतंत्र जांच है कि इससे क्या हुआ।

चरण 3: आप सत्यापित करें और पुनरावृत्त करें। pytest आउटपुट पढ़ें। दो हरे चेक (2 passed) का मतलब है कि code आपके द्वारा परिभाषित विनिर्देश को पूरा करता है। यदि यह लाल है, तो आप विफलता (अगली अवधारणा) पढ़ते हैं, फिर परिष्कृत करते हैं। आप आँख बंद करके आशा करते हुए नहीं बस re-prompt करते हैं। और एक चीज़ को ध्यान से देखें: यदि agent code के बजाय test को संपादित करके असफल test पास बनाता है, तो इसे रोकें। test आपकी विशिष्टता है; इसे कमजोर करके हरा बनाना केवल bug को छुपाता है।

वह संपूर्ण loop है, और यह PRIMM-AI+ और 10-80-10 नियम पर स्पष्ट रूप से मैप करता है:

TDG कदमकौन नेतृत्व करता हैPRIMM-AI+
आवश्यकता + असफल परीक्षण लिखेंआप (पहले 10%)बनाना
कार्यान्वयन उत्पन्न करेंagent (80%)
परीक्षण चलाएँ, सत्यापित करें, पुनरावृत्त करेंआप (अंतिम 10%)जांच/संशोधन करें
उन किनारे के मामलों को जोड़ें जिनके बारे में आप सोच सकते हैं

agent आपके छूटे हुए परीक्षणों का सुझाव देने में अच्छा है, इससे पूछें, "कर गणना के लिए मुझे किन प्रमुख मामलों में test करा चाहिए?"। लेकिन कौन से मामले "सही" परिभाषित करते हैं, इसका निर्णय आपका रहता है। नकारात्मक कीमतें? शून्य कर? बहुत बड़ी संख्या? आपके द्वारा जोड़ा गया प्रत्येक एक अधिक स्पष्ट विशिष्टता है।

हर चीज़ पर इस loop का use करें - यह default है, अंतिम नहीं

TDG बड़ी विशेषताओं के लिए आरक्षित समारोह नहीं है। इसे agent द्वारा उत्पादित प्रत्येक इकाई पर चलाएं जिसका एक जांच योग्य अनुबंध है: प्रत्येक function, प्रत्येक method, प्रत्येक सत्यापन नियम। अवधारणा 5, 8, और 11 से एक-पंक्ति asserts बीज थे; उनमें से एक बढ़ता हुआ tests/ folder आपको किसी Project पर भरोसा बनाए रखने देता है क्योंकि agent उसे बदलता है। एक व्यावहारिक नियम: यदि आप किसी चीज़ के लिए test नहीं लिख सकते हैं, तो आप अभी तक यह नहीं समझ पाए हैं कि इसके लिए "सही" का क्या अर्थ है। और न ही agent. test लिखने से आप पता लगाते हैं। जैसे-जैसे आपकी परियोजनाएँ बढ़ती हैं, यह आपको प्रतिगमन से भी बचाता है: agent एक चीज़ को ठीक करता है और चुपचाप दूसरी चीज़ को तोड़ देता है। आपका test सुइट वह अलार्म है जो इसे पकड़ता है।

ट्रेसबैक पढ़ना (जब वह टूट जाए)

जब Python विफल हो जाता है, तो यह एक ट्रेसबैक प्रिंट करता है: लाल पाठ की एक दीवार जो डरावनी लगती है और वास्तव में एक उपहार है। इसे पढ़ें नीचे से ऊपर: अंतिम पंक्ति त्रुटि का नाम देती है, और उसके ऊपर की पंक्तियाँ यह बताती हैं कि यह कहाँ हुआ।

Traceback (most recent call last):
File "tax.py", line 2, in total_with_tax
return price + (price * tax_rate)
TypeError: can't multiply sequence by non-int of type 'float'

लब्बोलुआब यह है कि पूरी कहानी है: कुछ string (str) था जबकि इसे एक संख्या होना चाहिए था: एक price 100.0 के बजाय "100" (पाठ) के रूप में आया। आपको इसे स्वयं ठीक करे की आवश्यकता नहीं है; आपको agent को यह बताने के लिए पर्याप्त रूप से पढ़ने की आवश्यकता है कि क्या गलत है: "कीमत पाठ के रूप में आ रही है, संख्या के रूप में नहीं। इसे संभालें।" एक सटीक विवरण से एक सटीक समाधान मिलता है। (debugging को अपना स्वयं का चरण मिलता है: AI युग में जुनून, चरण 4।)

कभी भी आंख मूंदकर re-prompt न करें

AI coding में सबसे महंगी आदत उस विफलता पर "पुनः प्रयास करें" मारना है जिसे आपने नहीं पढ़ा है। agent ख़ुशी-ख़ुशी एक अलग ग़लत उत्तर उत्पन्न करेगा। ट्रेसबैक पढ़ें, वास्तविक समस्या को समझें, फिर उसका वर्णन करें। एक सूचित prompt दस अंधों को पीटता है।

मुट्ठी भर त्रुटियाँ आपको वास्तव में मिलेंगी

आप सुधार याद नहीं रखते. आप उस अंतिम पंक्ति से श्रेणी को पहचानते हैं और उसका वर्णन agent तक करते हैं। ये छह लगभग वह सब कुछ कवर करते हैं जो एक नौसिखिया दौड़ते समय देखता है, उत्पन्न code:

अंतिम पंक्ति कहती है...आमतौर पर इसका क्या मतलब होता हैक्या बताएं agent
ModuleNotFoundError / ImportErrorpackage स्थापित नहीं है, या नाम गलत लिखा गया है"X स्थापित नहीं है - इसे uv के साथ जोड़ें"
NameErrorएक ऐसे नाम का use किया गया है जिसे कभी परिभाषित नहीं किया गया था (अक्सर एक टाइपो त्रुटि)"y का use किया जाता है लेकिन कभी परिभाषित नहीं किया गया - टाइपो?"
TypeErrorगलत प्रकार का मान - वह पाठ जहाँ किसी संख्या की अपेक्षा की गई थी, आदि।"एक संख्या टेक्स्ट के रूप में आ रही है - इसे रूपांतरित करें"
AttributeErrorobject से किसी ऐसी चीज़ के लिए पूछना जो उसके पास नहीं है (note.titel)"इस object में कोई विशेषता titel नहीं है - संभवतः एक टाइपो त्रुटि"
KeyErrorकिसी ऐसी key के लिए निर्देश माँगना जो उसमें नहीं है"key 'x' निर्देश में नहीं है - गुम मामले को संभालें"
IndexErrorlist से उसके अंत के बाद की स्थिति के लिए पूछना"list मान लिए गए code से छोटा है"

meta-Skill setup (अवधारणा 3) के समान है: आप वह नहीं हैं जो त्रुटि को ठीक करते हैं, आप वह हैं जो इसे पढ़ता है और इसे सटीक रूप से नाम देता है। एक सटीक नाम को एक सटीक समाधान मिलता है; "यह टूट गया" से एक और अनुमान मिलता है।

17. अस्पष्ट लक्ष्य से निर्दिष्ट टुकड़ों तक

संकल्पना 16 में दिखाया गया कि एक इकाई की विशिष्टता और सत्यापन कैसे किया जाए। लेकिन आपके अपने Project एक सुव्यवस्थित function के रूप में नहीं आते हैं। वे एक अस्पष्ट वाक्य के रूप में आते हैं: "build me a tool जो मेरे नोट्स का सारांश देता है।" आप उसके लिए एक भी test नहीं लिख सकते। वह Skill जो एक वाक्य को उत्पन्न code में बदल देता है वह है विघटन: लक्ष्य को छोटे-छोटे टुकड़ों में तोड़ना, प्रत्येक इतना छोटा कि एक टाइप किया हुआ हस्ताक्षर और एक test दे सके। यह वह हिस्सा है जो agent आपके लिए नहीं कर सकता, क्योंकि यहीं पर आप तय करते हैं कि चीज़ वास्तव में क्या है।

यहाँ चाल है, और यह हर बार समान है।

Decomposition: a one-sentence goal breaks into several small units, each given a typed signature and a failing test, which are then generated, verified, and wired together. 1. लक्ष्य को एक वाक्य में बताएं। "मेरे नोट्स पढ़ें और प्रिंट करें कि कितने पूरे हुए और कितने नहीं।"

2. उन चरणों की list बनाएं जिन्हें आप हाथ से करेंगे। क्रियाओं को लिखें: नोट्स को लोड करें → किए गए को गिनें → लंबित शीर्षकों को ढूंढें → उन्हें एक पंक्ति में संक्षेपित करें → इसे प्रिंट करें। प्रत्येक क्रिया एक अभ्यर्थी इकाई है।

3. प्रत्येक इकाई को एक टाइप किया हुआ हस्ताक्षर दें: इनपुट से आउटपुट तक। यह विशेषता है। अभी तक कोई शव नहीं; agent उन्हें लिखता है।

def load_notes(path: str) -> list[Note]: ...      # text file -> list of notes
def count_done(notes: list[Note]) -> int: ... # notes -> how many are done
def pending_titles(notes: list[Note]) -> list[str]: ... # notes -> titles not done
def summarize(notes: list[Note]) -> str: ... # notes -> one summary line

**4. TDG प्रत्येक इकाई, क्रम में। ** ऊपर की प्रत्येक पंक्ति अब बिल्कुल एक अवधारणा 16 चक्र है: असफल test लिखें, agent से बॉडी बनाएं, सत्यापित करें। उदाहरण के लिए, summarize छोटा और परीक्षण योग्य है:

def test_summarize() -> None:
notes = [Note(title="groceries", done=True), Note(title="call sara", done=False)]
assert summarize(notes) == "1 of 2 done; pending: call sara"

**5. उन्हें एक साथ तार दें और पूरे प्रवाह को test करें। ** agent को एक main() लिखने के लिए कहें जो टुकड़ों को क्रम में बुलाता है, फिर अंत-से-अंत परिणाम के लिए एक test लिखें। हो गया।

ध्यान दें कि क्या हुआ: एक अस्पष्ट वाक्य चार छोटे, स्वतंत्र रूप से सत्यापन योग्य अनुबंध बन गया। agent ने वास्तविक code की प्रत्येक पंक्ति लिखी। लेकिन आपने टुकड़ों को ढूंढ लिया और परिभाषित किया कि प्रत्येक क्या वादा करता है। वह फ्रंट-एंड अपघटन मानव 10% है जो agent को 80% भरोसेमंद बनाता है।

टुकड़ों पर विचार-मंथन करे के लिए agent का use करें - लेकिन अनुबंधों का स्वामी बनें

आप इकाइयों को ढूंढने में मदद के लिए agent से पूछ सकते हैं: "मैं build एक tool चाहता हूं जो मेरे नोट्स को सारांशित करता है। मुझे उनके इनपुट और आउटपुट के साथ 3-5 functions की क्या आवश्यकता होगी?" यह एक शानदार शुरुआत है list। लेकिन आप अंतिम हस्ताक्षर तय करते हैं और आप परीक्षण लिखते हैं। कभी भी agent दोनों को समस्या को विघटित न करे दें और न ही अपने स्वयं के उत्तर को सत्यापित करें, अन्यथा आप अपना स्वतंत्र चेक खो देंगे।

एक विश्वसनीय अनुमान: यदि किसी इकाई के लिए test लिखना कठिन है, तो यह बहुत अधिक कार्य कर रही है। इसे विभाजित करें। एक function जिसे आप test नहीं कर सकते, वह एक function है जिसे आप सत्यापित नहीं कर सकते, जिसका अर्थ यह है कि न तो आप इस पर भरोसा कर सकते हैं कि इसके लिए agent ने क्या उत्पन्न किया है। परीक्षणशीलता और अच्छा अपघटन एक ही Skill हैं।

यह "मैं एक function को सत्यापित कर सकता हूं" से "मैं AI के साथ एक संपूर्ण चीज़ build कर सकता हूं" तक का पुल है। यह बिल्कुल इसी तरह है कि पुस्तक का स्मार्टनोट्स Project बढ़ता है: एक समय में एक विघटित, परीक्षण किया हुआ टुकड़ा। आप इसका अभ्यास Project 5 मिनी-कैपस्टोन में करेंगे, फिर Project 6 में बिना किसी मचान के शुरुआत से करेंगे।

एक prompt आप किसी भी Project के लिए पुन: use कर सकते हैं

एक बार जब आप किसी लक्ष्य को विघटित कर लेते हैं, तो यह एक ऐसा टेम्पलेट है जिसे आप हर बार paste को Claude Code या OpenCode में बदल सकते हैं। यह इस पाठ्यक्रम के संपूर्ण अनुशासन में निहित है: पहले परीक्षण, code से पहले आपकी स्वीकृति, अंत में सत्यापन:

I want to build: [your one-sentence goal]

First, break it into 3–5 small functions or classes.
For each unit, propose ONLY:
1. a typed signature (inputs and output)
2. expected behavior in one line
3. edge cases to consider
4. pytest tests

Do NOT write any implementation yet. Wait for me to approve the tests.

After I approve, generate the implementation to pass those tests.
Then run pytest, pyright, and ruff, and show me only the
changed files and the test results.

दो भार वहन करे वाले शब्द केवल और नहीं हैं: वे agent को आगे बढ़ने और code (और अपने स्वयं के परीक्षण) लिखने से रोकते हैं, इससे पहले कि आप यह तय कर लें कि "सही" का क्या अर्थ है। आप विशिष्टता के नियंत्रण में रहते हैं; agent टाइपिंग करता है।


भाग 5: निर्णय

AI पर कब निर्भर नहीं रहना है - और जो आप पूरी तरह से नहीं पढ़ सकते हैं उसे कैसे सत्यापित करें

धाराप्रवाह पढ़ने की एक सीमा होती है, और इसके प्रति ईमानदार होना अपने आप में एक Skill है।

  • सुरक्षा-संवेदनशील code पर समझौता नहीं किया जा सकता। पासवर्ड, API keys, भुगतान, या user data को छूने वाली कोई भी चीज़ ध्यान से पढ़ी जाती है और, आदर्श रूप से, डोमेन को जानने वाले किसी व्यक्ति द्वारा समीक्षा की जाती है। AI आत्मविश्वास से असुरक्षित code लिखता है। यदि आप इसे सत्यापित नहीं कर सकते, तो इसे शिप न करें। (सुरक्षा समीक्षा के लिए देखें AI युग में बटालियन, चरण 8)
  • जब आप वास्तव में इसे नहीं पढ़ सकते हैं, तो विश्वास पर नहीं, बल्कि परीक्षणों पर अधिक जोर दें। यदि उत्पन्न function आपके वर्तमान स्तर से परे है, तो आपके pytest चेक अधिक महत्वपूर्ण हो जाते हैं, कम नहीं: वे वह हिस्सा हैं जिन्हें आप सत्यापित कर सकते हैं। आपके द्वारा चुने गए इनपुट पर हरित परीक्षण वास्तविक प्रमाण हैं; "यह सही लग रहा है" नहीं है।
  • छोटे, स्पष्ट परिवर्तन कभी-कभी हाथ से तेजी से होते हैं। एक variable का नाम बदलना या एक संख्या को ठीक करा वर्णन करे की तुलना में स्वयं करा अधिक तेज़ हो सकता है। इन क्षणों को पहचानना अभ्यास से आता है।

अपने स्वयं के परीक्षण रेड-टीम करें

आपके परीक्षण ही एकमात्र सत्यापन है जिसे आप पूरी तरह से नियंत्रित करते हैं, इसलिए एक कमजोर test test न होने से भी बदतर है, क्योंकि यह गलत आत्मविश्वास देता है। जब agent code उत्पन्न करता है तो आप पूरी तरह से नहीं पढ़ सकते हैं (एक मुश्किल Pydantic सत्यापनकर्ता, एक async ब्लॉक), आपके परीक्षण पूरे भार को वहन करते हैं। उन्हें प्रतिकूल बनाएं:

  • कभी भी agent को वे परीक्षण लिखने न दें जिनके लिए code को उत्तीर्ण होना चाहिए। यह एक ऐसा विरोधी पैटर्न है जो चुपचाप इस पाठ्यक्रम में बाकी सभी चीज़ों को हरा देता है: यदि AI code और चेक दोनों लिखता है, तो आपके पास कोई स्वतंत्र संकेत नहीं है: केवल agent स्वयं से सहमत है। आप परीक्षण लिखते हैं, या कम से कम आप पढ़ते हैं और प्रत्येक दावे को अपनाते हैं। हर हाल में पूछें "मुझे कौन से किनारे वाले मामले याद आ रहे हैं?"। फिर स्वयं तय करें कि कौन सा महत्वपूर्ण है।
  • कभी भी agent को test को पास करे के लिए कमजोर न होने दें। जब test विफल हो जाता है, तो agent कभी-कभी code के बजाय test को बदलकर इसे "ठीक" कर देगा: एक दावे को ढीला करा, एक किनारे के मामले को हटाना, एक अपेक्षित मूल्य को कम करा। bug को उसकी जगह पर छोड़ते समय वह लाल से हरे रंग में बदल जाता है। इस पर नजर रखें, और इसकी अनुमति तब तक न दें जब तक आप यह तय न कर लें कि test स्वयं वास्तव में गलत था। test विशिष्टता है; agent को अपने code के अनुरूप विशिष्टता को फिर से लिखने का मौका नहीं मिलता है।
  • असफलताओं का परीक्षण करें, न कि केवल सुखद पथ का। प्रत्येक इकाई से पूछें: कौन सा इनपुट इसे तोड़ देगा? खाली list, शून्य, एक नकारात्मक संख्या, एक गुम key, पाठ जहां एक संख्या अपेक्षित थी। Project 4 में bug ठीक उसी स्थिति में छिपा था, जिसका किसी ने परीक्षण नहीं किया।
  • यदि आप इसके लिए एक भी test के बारे में नहीं सोच सकते हैं, तो आप इसे अभी तक नहीं समझ पाए हैं। और आप निश्चित रूप से agent के संस्करण को सत्यापित नहीं कर सकते। यह आपका संकेत है कि आप इसे और अधिक विघटित करें (संकल्पना 17) या इसे स्वीकार करे से पहले agent को code को एक-एक करके समझाने के लिए कहें।

रखने के लिए एक अस्पष्ट अनुमान: हरे परीक्षण साबित करते हैं कि आपका code वही करता है जो आपके परीक्षण कहते हैं। अब और नहीं। आपके सत्यापन की गुणवत्ता बिल्कुल आपके परीक्षणों की गुणवत्ता है। (files, मानक library, package पारिस्थितिकी तंत्र, गहन debugging, और वास्तविक सुरक्षा समीक्षा जानबूझकर AI युग में विभाग पर छोड़ दी जाती हैं। यह crash course आपको निर्णय देता है; वह भाग आपको गहराई देता है।)

इसे स्वीकार करे से पहले अंतर की समीक्षा करें

जब आप Claude Code या OpenCode में काम करते हैं, तो agent केवल उत्तर नहीं देता है। यह files को बदल देता है। code को पढ़ना आधा काम है; बाकी आधा पढ़ रहा है क्या बदल गया। इससे पहले कि आप उत्पन्न परिवर्तनों के किसी भी बैच को स्वीकार करें, run को इस list से नीचे करें:

  1. कौन सा files बदल गया? एक function को ठीक करे के लिए request को चुपचाप पांच files को नहीं छूना चाहिए।
  2. क्या इससे परीक्षण बदल गए? यदि आपके परीक्षण संपादित किए गए थे, तो किसी भी अन्य चीज़ से पहले इसका कारण पता करें (ऊपर प्रति-पैटर्न देखें)।
  3. क्या इसने निर्भरताएँ जोड़ीं? नए packages का मतलब है नया code जिसे आपने अपनी मशीन पर चलाना नहीं लिखा। सुनिश्चित करें कि प्रत्येक वास्तविक और आवश्यक है।
  4. क्या इसने किसी संवेदनशील चीज़ को छुआ? रहस्य, keys, प्राधिकरण, भुगतान, user data: इन्हें ध्यान से पढ़ा जाता है या डोमेन को जानने वाले किसी व्यक्ति द्वारा समीक्षा की जाती है।
  5. क्या pytest, Pyright, और Ruff सभी पास हो गए? तीनों के पार हरा फर्श है, छत नहीं।
  6. क्या आप मुख्य function या class को सादे अंग्रेजी में समझा सकते हैं? यदि आप नहीं कर सकते, तो आप इसे सत्यापित नहीं कर सकते: स्वीकार करे से पहले agent को लाइन दर लाइन इसके बारे में बताने के लिए कहें।

यह एक त्वरित आदत है, कोई समारोह नहीं. लेकिन अंतर को पढ़े बिना "सभी को स्वीकार करें" यह है कि कैसे एक छोटा सा गलत परिवर्तन किसी कार्यशील परियोजना में किसी का ध्यान नहीं जाता है।

इस संपूर्ण पाठ्यक्रम की संपूर्ण पंक्ति: **agent code लाता है; आप निर्णय लेते हैं कि यह सही है या नहीं। ** यह निर्णय धाराप्रवाह पढ़ने और आपके द्वारा स्वयं लिखे गए परीक्षणों पर निर्भर करता है। एक बार जब आप loop का अभ्यास कर लें तो न तो वैकल्पिक है और न ही कठिन है।


भाग 6: परियोजनाओं का अभ्यास करें

loop के बारे में पढ़ना इसे चलाने के समान नहीं है। ये छह परियोजनाएं आपको क्रम में PRIMM-AI+ के माध्यम से ले जाती हैं: पढ़ने से code तक, इसे परीक्षण करे के लिए, *अपना खुद का बनाने तक, वास्तविक agent-style code को इसमें छिपे bug के साथ *सत्यापित करे के लिए, एक छोटे एंड-टू-एंड tool का निर्माण करे के लिए जो एक ही बार में हर अवधारणा का use करता है, और अंत में बिना किसी मचान के एक-वाक्य लक्ष्य से एक का निर्माण करा। उन्हें अपने Claude Code या OpenCode सत्र में क्रम से करें; प्रत्येक व्यक्ति पहले वाले से Skill ग्रहण करता है।

प्रत्येक Project आपको लक्ष्य और उसमें प्रयुक्त Skill बताता है, फिर आपको एक स्टार्टर सौंपता है। पहले इसे स्वयं आज़माएँ: अपनी भविष्यवाणी लिखें, अपने परीक्षण लिखें, prompt the agent। और तभी open समाधान। copy के लिए समाधान मौजूद नहीं हैं: agent वैसे भी आपके लिए code उत्पन्न कर सकता है। वे वहां हैं ताकि आप जांच सकें कि आपका विवरण और आपके परीक्षण सही थे। इसी Skill को वर्गीकृत किया जा रहा है।

समाधानों का use कैसे करें

संदर्भ code प्रत्येक समाधान का सबसे कम महत्वपूर्ण हिस्सा है। क्या मायने रखता है: क्या आपके परीक्षणों ने "सही" का अर्थ पकड़ लिया? क्या आपने आउटपुट का सही अनुमान लगाया? क्या आप परिणाम पढ़ सकते हैं और बता सकते हैं कि यह सही था? यदि आपके परीक्षण संदर्भ code के विरुद्ध उत्तीर्ण होते हैं, तो आपने समस्या को अच्छी तरह से निर्दिष्ट किया है। वही जीत है.

Project 1 - पढ़ें और भविष्यवाणी करें (भविष्यवाणी करें · चलाएँ · जाँच करें)

Skills: पढ़ना functions, समझ, और len; चलने से पहले आउटपुट की भविष्यवाणी करा।

स्टार्टर। इसे अभी तक run न करें। इसे पढ़ें और लिखें कि तीन print पंक्तियों में से प्रत्येक क्या उत्पन्न करेगी:

def shout(text: str) -> str:
return text.upper() + "!"

names: list[str] = ["ada", "alan", "grace"]
greetings: list[str] = [shout(n) for n in names if len(n) > 3]

print(len(names))
print(greetings)
print(shout("hi"))

अब इसे अपने सत्र में run करें और तुलना करें। जहां आपकी भविष्यवाणी गलत थी, वहां agent से पूछें "पंक्ति X ने ऐसा क्यों उत्पन्न किया?"। वह अंतर ही सबक है.

समाधान
3
['ALAN!', 'GRACE!']
HI!
  • len(names)3: list में तीन आइटम।
  • greetings → केवल 3 अक्षरों से अधिक लंबे नाम ही if len(n) > 3 फ़िल्टर पास करते हैं। "ada" बिल्कुल 3 (विफल) है, "alan" 4 है और "grace" 5 (पास) है। प्रत्येक को ['ALAN!', 'GRACE!'] देते हुए चिल्लाया जाता है।
  • shout("hi")"HI!": अपरकेस, ! के साथ जोड़ा गया।

यदि आप समझ को इस प्रकार पढ़ते हैं "नामों में प्रत्येक नाम के लिए, यदि यह 3 अक्षरों से अधिक लंबा है, तो प्रत्येक नाम चिल्लाएँ," आपने इसे सही ढंग से पढ़ा है।

Project 2 — function पर आपका पहला TDG चक्र (बनाएँ)

Skills: assert परीक्षणों को एक विशिष्टता के रूप में लिखना, agent को प्रेरित करा, pytest से सत्यापन करा।

लक्ष्य। एक function initials(full_name: str) -> str बनाएं जो नाम के बड़े अक्षरों को लौटाता है: "ada lovelace""AL"

स्टार्टर. किसी भी कार्यान्वयन के मौजूद होने से पहले परीक्षण पहले, test_initials.py में लिखें। सामान्य केस और कम से कम दो किनारे वाले केस (एक ही नाम; अतिरिक्त स्थान) को कवर करें। फिर prompt आपका agent:

test_initials.py पढ़ें. initials.py को initials(full_name: str) -> str function के साथ बनाएं जो प्रत्येक test को पास करता है। फिर run pytest और मुझे परिणाम दिखाओ।

हरे चेक पर भरोसा करे से पहले इसे उत्पन्न होने वाले code को पढ़ें।

समाधान

आपके परीक्षण (महत्वपूर्ण भाग) इस तरह दिख सकते हैं:

from initials import initials

def test_two_names() -> None:
assert initials("ada lovelace") == "AL"

def test_many_names() -> None:
assert initials("grace brewster murray hopper") == "GBMH"

def test_single_name() -> None:
assert initials("alan") == "A"

def test_extra_spaces() -> None:
assert initials(" extra spaces ") == "ES"

एक संदर्भ कार्यान्वयन जो उन सभी को पास करता है:

def initials(full_name: str) -> str:
return "".join(part[0].upper() for part in full_name.split())

full_name.split() पाठ को रिक्त स्थान पर तोड़ता है (और अतिरिक्त को अनदेखा करता है), part[0] प्रत्येक टुकड़े का पहला अक्षर लेता है, .upper() इसे बड़े अक्षरों में लिखता है, और "".join(...) उन्हें एक साथ चिपका देता है। यदि आपने extra_spaces test लिखा है, तो आपने पेचीदा मामले को स्वयं सत्यापित किया है: यह बिल्कुल वही निर्णय है जो agent प्रदान नहीं कर सकता है।

Project 3 — TDG class पर (बनाएँ)

Skills: class को पढ़ना और निर्दिष्ट करा, object स्थिति को बदलने वाली विधियाँ, object व्यवहार का परीक्षण करा।

लक्ष्य। एक छोटा TaskList बनाएं: पुस्तक के स्मार्टनोट्स जैसा कुछ का बीज। यह कार्यों को जोड़ सकता है, एक को पूर्ण चिह्नित कर सकता है और report कर सकता है कि कितने अभी भी अधूरे हैं।

स्टार्टर. पहले परीक्षण लिखें. तय करें कि विधियों को क्या कहा जाता है और वे क्या हैं return। वह design है। एक प्रारंभिक बिंदु:

def test_task_flow() -> None:
tasks = TaskList()
tasks.add("write tests")
tasks.add("call agent")
assert tasks.remaining() == 2
tasks.complete("write tests")
assert tasks.remaining() == 1

फिर prompt agent को TaskList class लागू करे के लिए जो test को पास कराता है, और सत्यापित करता है।

समाधान

एक संदर्भ कार्यान्वयन:

class TaskList:
def __init__(self) -> None:
self.tasks: dict[str, bool] = {} # task name -> done?

def add(self, name: str) -> None:
self.tasks[name] = False

def complete(self, name: str) -> None:
if name in self.tasks: # only complete a task that exists
self.tasks[name] = True

def remaining(self) -> int:
return sum(1 for done in self.tasks.values() if not done)

class कार्यों को प्रत्येक नाम को done ध्वज में मैप करते हुए संग्रहीत करता है। remaining() उन लोगों को गिनता है जो अभी भी False पर सेट हैं। ध्यान दें कि test ने design को कैसे संचालित किया: इसने किसी code के अस्तित्व में आने से पहले, method नाम और remaining() क्या लौटाता है, यह तय किया।

खामोश bug को स्वयं पकड़ें। complete("a task I never added") को क्या करा चाहिए? agent का पहला संस्करण अक्सर if name in self.tasks गार्ड के बिना self.tasks[name] = True लिखता है, जो चुपचाप एक बिल्कुल नया कार्य 'पूरा' के रूप में जोड़ देता है, और data का आविष्कार करता है जिसे किसी ने नहीं मांगा था। यह बिल्कुल प्रशंसनीय-लेकिन-गलत व्यवहार है जिसे test उजागर करता है:

def test_completing_unknown_task_does_nothing() -> None:
tasks = TaskList()
tasks.add("real task")
tasks.complete("typo task") # not a real task
assert tasks.remaining() == 1 # still one; nothing was invented

एक्सटेंशन: अपने agent को प्रत्येक कार्य को created_at टाइमस्टैम्प के साथ Pydantic Task model बनाने के लिए कहें, फिर एक test जोड़ें कि बिल्कुल नए TaskList में remaining() == 0 है।

Project 4 — agent code में bug ढूंढें (जांच करें · संशोधित करें)

Skills: पावर अवधारणाओं (Pydantic, जेनरेटर) को पहचानना, आलोचनात्मक रूप से पढ़ना, एक test लिखना जो एक वास्तविक bug पकड़ता है।

यह आपकी वास्तविक नौकरी के सबसे करीब है: agent आपको विश्वसनीय दिखने वाला code सौंपता है, और आपको पकड़ना होगा कि क्या गलत है। नीचे दिया गया function केवल उन नोट्स के शीर्षकों के लिए माना जाता है जो पूरे हो चुके हैं। लेकिन इसमें एक bug है.

from collections.abc import Iterator
from pydantic import BaseModel

class Note(BaseModel):
title: str
done: bool

def completed_titles(notes: list[Note]) -> Iterator[str]:
for note in notes:
yield note.title

आपका कार्य, क्रम में:

  1. जांच करें। स्पष्ट अंग्रेजी में कहें कि प्रत्येक पंक्ति का क्या मतलब है। (Note model क्या है? Iterator[str] आपको क्या बताता है? yield क्या करता है?)
  2. परीक्षण। एक pytest test लिखें जो इच्छित व्यवहार को पिन करता है: केवल पूर्ण किए गए नोट ही वापस आते हैं। इसे चलाने के लिए। bug को पकड़ने में इसे विफल होना चाहिए।
  3. संशोधित करें। अब जब आपका test सही परिभाषित करता है, prompt agent को completed_titles को ठीक करे के लिए, और run को तब तक re-run करें जब तक कि आपका test हरा न हो जाए।
समाधान

bug: function प्रत्येक नोट का शीर्षक देता है, done को पूरी तरह से अनदेखा करता है। यह कभी भी झंडे की जांच नहीं करता.

एक test जो इसे पकड़ता है:

def test_only_completed() -> None:
notes = [Note(title="a", done=True), Note(title="b", done=False)]
assert list(completed_titles(notes)) == ["a"]

छोटी गाड़ी code के विरुद्ध यह विफल हो जाता है, क्योंकि यह ["a", "b"] लौटाता है: यह प्रमाणित करता है कि bug वास्तविक है, कोई अनुमान नहीं।

समाधान एक पंक्ति है: उपज देने से पहले एक done जांच:

def completed_titles(notes: list[Note]) -> Iterator[str]:
for note in notes:
if note.done:
yield note.title

इस परियोजना का मुद्दा: bug एक नज़र में अदृश्य था और test के लिए स्पष्ट था। "यह सही लग रहा है" इसे भेज दिया होगा। आपके द्वारा लिखे गए test ने इसे पकड़ लिया। यह एक अभ्यास में संपूर्ण पाठ्यक्रम है।

Project 5 - मिनी-कैपस्टोन: एक नोट्स tool, अंत से अंत तक (संपूर्ण loop)

Skills: सबकुछ, एक Pydantic model, राज्य के साथ एक class, एक जनरेटर, type hints, एक f-string सारांश, और एक test सुइट, जिसे एक TDG चक्र के रूप में बनाया गया है। यह पुस्तक के स्मार्टनोट्स का एक छोटा-सा रिहर्सल है।

लक्ष्य। एक छोटा NoteBook बनाएं जो नोट्स रखता हो (प्रत्येक में एक शीर्षक, मुख्य भाग और पूर्ण ध्वज के साथ), आपको नोट्स जोड़ने और उन्हें पूर्ण चिह्नित करे की सुविधा देता है, अभी भी लंबित लोगों को स्ट्रीम करता है, और 2 notes, 1 done, pending: call sara जैसे एक-पंक्ति सारांश प्रिंट करता है।

स्टार्टर: इसे परीक्षणों के माध्यम से design करें। यह वास्तविक अभ्यास है: किसी भी कार्यान्वयन को लिखने या उत्पन्न करे से पहले, एक test_notebook.py लिखें जो आपके इच्छित व्यवहार को पिन करता है। method नाम तय करें और summary() को क्या कहना चाहिए। प्रतिक्रिया करे के लिए एक कंकाल:

from notebook import NoteBook

def test_summary_flow() -> None:
nb = NoteBook()
nb.add("groceries", "milk, eggs")
nb.add("call sara", "about the trip")
assert nb.summary() == "2 notes, 0 done, pending: groceries, call sara"
nb.complete("groceries")
assert nb.summary() == "2 notes, 1 done, pending: call sara"

def test_pending_is_a_stream() -> None:
nb = NoteBook()
nb.add("a", "x")
nb.add("b", "y")
nb.complete("a")
assert [n.title for n in nb.pending()] == ["b"] # pending() yields, like a generator

फिर run पूरा loop:

  1. pytest चलाएँ। यह विफल रहता है (अभी तक कोई notebook.py नहीं है)। अच्छा: यह आपकी कल्पना है, जानबूझकर असफल होना।
  2. अपने agent को संकेत दें: "test_notebook.py पढ़ें। एक Note Pydantic model (शीर्षक, मुख्य भाग, हो गया) और एक NoteBook class के साथ notebook.py बनाएं जो प्रत्येक test को पास कराता है: add, complete, एक pending() जनरेटर, और एक summary() जो परीक्षण की अपेक्षा के अनुसार सटीक string लौटाता है। फिर run pytest और मुझे परिणाम दिखाओ।"
  3. पढ़ें कि इससे क्या उत्पन्न हुआ। क्या आप Pydantic model, class स्थिति, pending() में yield और summary() में f-string को इंगित कर सकते हैं? यदि हां, तो आपने agent code का वास्तविक अंश पढ़ा है। इस पर pyright और ruff भी चलाएँ।
  4. किसी भी विफलता पर उसे पढ़कर दोहराएँ, न कि आँख मूँदकर दोबारा संकेत देना।
समाधान

एक संदर्भ कार्यान्वयन जो दोनों परीक्षण पास करता है:

from collections.abc import Iterator
from pydantic import BaseModel

class Note(BaseModel):
title: str
body: str
done: bool = False

class NoteBook:
def __init__(self) -> None:
self.notes: list[Note] = []

def add(self, title: str, body: str) -> None:
self.notes.append(Note(title=title, body=body))

def complete(self, title: str) -> None:
for note in self.notes:
if note.title == title:
note.done = True

def pending(self) -> Iterator[Note]: # a generator: yields one note at a time
for note in self.notes:
if not note.done:
yield note

def summary(self) -> str:
total = len(self.notes)
done = sum(1 for n in self.notes if n.done)
pending_titles = [n.title for n in self.pending()]
return f"{total} notes, {done} done, pending: {', '.join(pending_titles)}"

पाठ्यक्रम की प्रत्येक अवधारणा यहां दिखाई देती है: एक Pydantic model (Note) जिसमें type hints और एक default, एक class (NoteBook) होल्डिंग स्थिति, एक method जो object की विशेषता (complete) को परिवर्तित करता है, एक जनरेटर (pending) जो yields, एक समझ और sum(...), और एक f-string सारांश का निर्माण।

इसे वास्तविक CLI बनाएं (AI युग पाठ्यक्रम में प्रोग्रामिंग के लिए पुल)। ऊपर परीक्षण किया गया कोर कठिन हिस्सा है; इसे command line tool में बदलना शीर्ष पर एक पतला खोल है। अपने agent को एक main() जोड़ने के लिए कहें जो terminal से add, done, और list जैसे command पढ़ता है और इन विधियों को कॉल करता है। फिर इसे किसी भी नए तर्क के लिए एक और test लिखने के लिए कहें। वह अंतिम चरण, एक कार्यशील CLI जिसके पीछे एक पासिंग test सुइट है, बिल्कुल स्मार्टनोट्स के आकार का है, बस छोटा है।

किसी किनारे के मामले का निर्णय स्वयं करें। जब कुछ भी लंबित न हो तो summary() को क्या कहना चाहिए? संदर्भ एक अनुगामी pending: छोड़ता है। क्या वह सही है? एक test लिखें जो आपके निर्णय को encode करता है, फिर agent को उसे संतुष्ट करें। यहां "सही" का क्या अर्थ है, यह तय करें और इसे test के साथ पिन करा, पूरा काम है।

Project 6 - अपने दम पर: कोई स्टार्टर नहीं, कोई परीक्षण नहीं (इसे स्वयं विघटित करें)

Skills: प्रशिक्षण पहियों के बंद होने के साथ संकल्पना 17। अब तक प्रत्येक परियोजना ने आपको एक test कंकाल या एक हस्ताक्षर सौंपा है। यह आपको केवल एक वाक्य देता है।

लक्ष्य। "एक tool बनाएं जो पाठ का एक पैराग्राफ लेता है और तीन सबसे सामान्य शब्दों को प्रिंट करता है।"

आपको बस इतना ही मिलता है. कोई हस्ताक्षर नहीं, कोई परीक्षण नहीं, टुकड़ों के बारे में कोई संकेत नहीं। आपका काम संपूर्ण मोर्चा 10% है:

  1. विघटित करें। आपके द्वारा किए जाने वाले चरणों को हाथ से लिखें, और प्रत्येक को एक टाइप किए गए हस्ताक्षर में बदल दें। (आप पाठ को शब्दों में कैसे विभाजित करते हैं? पट्टी विराम चिह्न? उन्हें गिनें? उन्हें रैंक करें?)
  2. विशेषता प्रत्येक टुकड़े के लिए, एक असफल pytest test लिखें जो "सही" को परिभाषित करता है: कुछ भी उत्पन्न करे से पहले
  3. उत्पन्न करें और सत्यापित करें। agent को अपने परीक्षणों के विरुद्ध प्रत्येक इकाई को लागू करे दें; run pytest, pyright, ruff; पुनरावृत्त करा
  4. इसे एक साथ तार दें पूरे प्रवाह को report() और test में।

कोई एक सही उत्तर नहीं है: केवल विघटन जहां प्रत्येक टुकड़ा छोटा और परीक्षण योग्य है। वह वह Skill है जिसे वर्गीकृत किया जा रहा है।

समाधान (एक वैध अपघटन - आपका भिन्न हो सकता है)

चार छोटी, स्वतंत्र रूप से परीक्षण योग्य इकाइयों में एक उचित विभाजन:

def clean(text: str) -> list[str]:
# lowercase, drop punctuation, split into words
cleaned = "".join(c.lower() if c.isalnum() or c.isspace() else " " for c in text)
return cleaned.split()

def tally(words: list[str]) -> dict[str, int]:
counts: dict[str, int] = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
return counts

def top_n(counts: dict[str, int], n: int) -> list[tuple[str, int]]:
return sorted(counts.items(), key=lambda pair: pair[1], reverse=True)[:n]

def report(text: str, n: int) -> str:
pairs = top_n(tally(clean(text)), n)
return ", ".join(f"{word} ({count})" for word, count in pairs)

और जिस प्रकार के परीक्षण आपको पहले लिखने चाहिए थे:

def test_clean_strips_punctuation() -> None:
assert clean("Hi, hi! Bye.") == ["hi", "hi", "bye"]

def test_tally_counts() -> None:
assert tally(["hi", "hi", "bye"]) == {"hi": 2, "bye": 1}

def test_report_picks_top_two() -> None:
assert report("the cat sat on the mat the cat", 2) == "the (3), cat (2)"

जानबूझकर लेने लायक एक निर्णय: जब दो शब्दों की गिनती समान हो, तो पहले कौन आता है? Python का sorted स्थिर है, इसलिए यहां संबंध प्रथम-प्रस्तुति क्रम में वापस आ जाते हैं। लेकिन आपको यह जानबूझकर तय करा चाहिए और इसे test से पिन करा चाहिए, इसे गलती से नहीं खोजना चाहिए। (यदि आपने संबंधों के बारे में बिल्कुल भी नहीं सोचा, तो यह एक अंतर है जो आपके परीक्षणों में सामने आना चाहिए था।)

यदि आपके अपघटन में अलग-अलग टुकड़े थे (मान लीजिए, एक word_frequencies function) लेकिन प्रत्येक टुकड़ा स्वतंत्र रूप से परीक्षण योग्य था और आपके परीक्षण पास हो गए, आपने इसे सही किया। ग्रेड इस code से मेल नहीं खा रहा है: यह है कि क्या आपने एक-वाक्य लक्ष्य को अपने दम पर परीक्षण योग्य अनुबंध में बदल दिया है। यह बिल्कुल वही Skill है जिस पर आप इसके बाद AI के साथ build प्रत्येक Project के लिए निर्भर रहेंगे।

कहाँ बड़ा जाना है

ये वार्म-अप हैं। वास्तविक अभ्यास परियोजना स्मार्टनोट्स है AI युग में ऑपरेशन। आप इस सटीक loop का use करके नौ चरणों में एक एप्लिकेशन विकसित करते हैं, फिर build एक दूसरा (क्विज़फोर्ज) बिना किसी मार्गदर्शन के यह साबित करे के लिए कि Skill आपका है।


आगे क्या होगा

अब आप उन मुख्य आकृतियों को पढ़ सकते हैं जो अधिकांश Python (मान, functions, संग्रह, नियंत्रण प्रवाह और वर्ग) बनाते हैं, पांच शक्ति अवधारणाओं को पहचान सकते हैं जो agent और ML code, run को Claude Code या OpenCode में पूर्ण Test-Driven Generation चक्र भरते हैं, एक अस्पष्ट लक्ष्य को निर्दिष्ट टुकड़ों में तोड़ सकते हैं, और आपने छह परियोजनाओं पर इसका अभ्यास किया है। बाकी किताब यही साक्षरता मानती है।

क्या आप पास हो गए? एक स्व-जांच

यदि आप अब इनमें से सभी सातों को बिना नोट्स के कर सकते हैं तो यह पाठ्यक्रम काम कर गया है। यदि कोई अस्थिर महसूस करता है, तो आगे बढ़ने से पहले कोष्ठक में दी गई अवधारणा पर दोबारा गौर करें:

  1. function हस्ताक्षर पढ़ें और इसके इनपुट और आउटपुट को सामान्य अंग्रेजी में समझाएं। (संकल्पना 5)
  2. किसी भी code के अस्तित्व में आने से पहले एक इकाई के लिए कम से कम तीन pytest परीक्षण लिखें। (अवधारणाएँ 5, 16)
  3. टाइप किए गए हस्ताक्षर का use करके, उन परीक्षणों के विरुद्ध code को लागू करे के लिए AI agent से पूछें। (अवधारणा 10, 16)
  4. pytest, Pyright, और Ruff चलाएँ, और पढ़ें कि प्रत्येक आपको क्या बताता है। (संकल्पना 3)
  5. ट्रेसबैक को नीचे से ऊपर तक पढ़ें और समस्या का सटीक वर्णन करें। (संकल्पना 16)
  6. AI-generated code में एक संभावित-लेकिन-गलत bug पकड़ें। (Project 4)
  7. एक अस्पष्ट, एक-वाक्य लक्ष्य को परीक्षण योग्य इकाइयों में विघटित करें। (संकल्पना 17, Project 6)

यदि आप सभी सात कर सकते हैं, तो आप Claude Code या OpenCode के साथ बैठ सकते हैं और एक छोटा, परीक्षण किया हुआ Python प्रोग्राम भेज सकते हैं जिसे आप वास्तव में समझते हैं। यही संपूर्ण लक्ष्य है.

यहाँ से:

  • AI agents का निर्माण करें: जहां Pydantic models, async/await, और type hints जिन्हें आपने अभी-अभी पहचानना सीखा है, वे agent code की रोजमर्रा की सामग्री बन जाते हैं।
  • AI पोस्टग्रेज के लिए: code को पढ़ना जो आपके agents' data को संग्रहीत और पुनर्प्राप्त करता है।
  • एक डिजिटल /docs/digital-fte-crash-course का निर्माण: एक कामकाजी AI कार्यकर्ता में सब कुछ इकट्ठा करा।
  • AI युग में अगल: पूर्ण गहन पाठ्यक्रम। आप नौ चरणों में build स्मार्टनोट्स बनाते हैं, रीडर से आर्किटेक्ट तक जाते हुए, प्रत्येक चरण में TDG चक्र के अधिक मालिक होते हैं।

आप code टाइप करा नहीं सीख रहे हैं। आप इसे लिखने वाली प्रणालियों को निर्देशित और सत्यापित करा सीख रहे हैं। पढ़ना हमेशा सबसे कठिन हिस्सा था। और आपने अभी शुरुआत की है.


60 सेकंड की शब्दावली

अवधिसादा अंग्रेजी
PRIMM-AI+भविष्यवाणी करें · चलाएं · जांच करें · संशोधित करें · बनाएं - इस पाठ्यक्रम का सबसे पहले पढ़ा जाने वाला method, agent को भागीदार के रूप में और परीक्षणों को सत्य के रूप में लें
टीडीडी → TDGपरीक्षण-संचालित विकास: असफल test लिखें, फिर code लिखें। AI युग में यह Test-Driven Generation हो जाता है - आप असफल test लिखते हैं, agent code लिखते हैं, आप सत्यापित करते हैं कि यह पास हो गया है
TDGTest-Driven Generation - पहले असफल test लिखें, agent code उत्पन्न करता है, आप सत्यापित करें
assertassert x == 5 जैसा एक पंक्ति का दावा - यदि सत्य है तो कुछ नहीं करता, यदि गलत है तो जोर से क्रैश हो जाता है। प्रत्येक test परमाणु से निर्मित होता है
प्रकार/प्रकार संकेतकोई चीज़ data किस प्रकार की है, इसके लिए एक लेबल (str, int, float, bool) - और agent के लिए एक सटीक निर्देश
कार्य/हस्ताक्षरएक नामित, पुन: प्रयोज्य ब्लॉक; इसकी पहली पंक्ति इनपुट और आउटपुट का अनुबंध है
list / dict / सेट / टुपलवे चार कंटेनर जो data समूह में हैं; डिक्ट (लेबल जोड़े) वह है जिसे आप सबसे अधिक पढ़ेंगे
कक्षा / objectA class एक खाका है; एक object (उदाहरण) इससे निर्मित एक चीज़ है। object.attribute इसका data पढ़ता है; object.method() इसे कार्य करे के लिए कहता है
self / विशेषता / methodself class के अंदर "यह object" है; एक विशेषता data है जो इसमें मौजूद है; method एक function है जो class में रहता है और object पर कार्य करता है
समझएक for loop को एक पंक्ति में मोड़कर build एक नया list बना दिया गया
f-stringसामने f लिखकर टेक्स्ट करें; {...} के अंदर कुछ भी उसके मान (f"{name}") से बदल दिया जाता है
जनरेटर / yieldस्मृति को समतल रखने के लिए वस्तुओं को एक-एक करके हाथ में लें - एक धारा, ढेर नहीं
with (context प्रबंधक)किसी चीज़ को खोलता है, उसका use करता है, और गलती होने पर भी उसे सुरक्षित रूप से बंद कर देता है
async / awaitएक ही समय में कई धीमे काम (जैसे API कॉल) करे के लिए code बनाया गया
डंडर (__call__, __init__)डबल-अंडरस्कोर विधियाँ जो आपके object को मूल Python चीज़ों की तरह कार्य कराती हैं
डेकोरेटर (@name)function या class के ऊपर एक लेबल जो इसमें व्यवहार जोड़ता है
Pydanticसंरचित data को मान्य करता है और tool कॉलिंग के लिए JSON स्कीमा LLMs use को स्वतः उत्पन्न करता है
pytest / Pyright / Ruff / uvआपका सत्यापन tools: run परीक्षण / प्रकार जांचें / शैली जांचें / प्रबंधित करें Python
वापस ट्रेस करेंPython की त्रुटि report - इसे नीचे से ऊपर तक पढ़ें; अंतिम पंक्ति समस्या का नाम देती है

फ़्लैशकार्ड अध्ययन सहायता


अपनी समझ का परीक्षण करें

Checking access...