Intermediate Python 📂 Class and Object · 7 of 10 249 min read

Python OOP — Abstraction with ABC

Master abstraction — OOP's principle of showing what a class does while hiding how it does it. Learn Python's abc module, ABC, and @abstractmethod, understand why abstract classes can't be instantiated directly, and see how one abstract interface lets many concrete implementations coexist. Includes a coffee-machine analogy, three animated SVG diagrams (contract, blocked instantiation, polymorphic dispatch), Payment Gateway and Shape hierarchy examples, plus 10 golden rules.

🌐
SectionSection第 01 节

The Story That Explains Abstraction ☕Abstraction समझाने वाली कहानी ☕一个讲清抽象(Abstraction)的故事 ☕

The Coffee Machine — Press a Button, Get CoffeeCoffee Machine — बटन दबाओ, coffee पाओ咖啡机 — 按一下按钮,咖啡就来了
You walk up to a coffee machine and press "Espresso". A minute later, espresso appears. You never had to:

Grind the beans. Measure 18 grams. Tamp with 30 pounds of force. Heat the water to 93 °C. Time the extraction to 25 seconds. Clean the group head afterwards.

All of that happens behind one button. What you use is the interface — Espresso, Latte, Cappuccino, Off. What actually runs is the implementation — pumps, sensors, heaters and timers.

Now buy a different machine — a drip coffee-maker, a French press or a capsule machine. Same idea: "press this, get coffee." Each machine brews in a completely different way, but for you they all offer the same simple action.

That is abstraction. Show what a class does; hide how it does it. Coffee machines, payment methods, database drivers and file-format handlers in software all work this way.
आप coffee machine के पास जाते हैं और "Espresso" दबाते हैं। एक मिनट में espresso तैयार। आपको कभी यह नहीं करना पड़ा:

बीज पीसना। 18 ग्राम नापना। 30 pound के ज़ोर से दबाना। पानी 93 °C तक गर्म करना। 25 second तक extraction करना। बाद में group head साफ़ करना।

यह सब एक बटन के पीछे होता है। आप जो इस्तेमाल करते हैं वह interface है — Espresso, Latte, Cappuccino, Off। जो असल में चलता है वह implementation है — pumps, sensors, heaters और timers।

अब दूसरी machine ख़रीदिए — drip coffee-maker, French press या capsule machine। विचार वही: "यह दबाओ, coffee पाओ।" हर machine बिल्कुल अलग तरीक़े से coffee बनाती है, पर आपके लिए सब एक ही आसान काम देती हैं।

यही abstraction है। Class क्या करती है वह दिखाओ; कैसे करती है वह छिपाओ। Software में coffee machines, payment methods, database drivers और file-format handlers सब ऐसे ही काम करते हैं।
你走到咖啡机前,按下 "Espresso"。一分钟后,浓缩咖啡就出来了。你从来不需要:

磨豆子。称 18 克。用 30 磅的力压粉。把水加热到 93 °C。把萃取时间控制在 25 秒。事后清洗冲煮头。

这一切都发生在一个按钮的 背后。你使用的是 接口(interface) — Espresso、Latte、Cappuccino、Off。真正运行的是 实现(implementation) — 水泵、传感器、加热器和计时器。

现在换一台机器 — 滴滤咖啡机、法压壶或胶囊机。道理一样:"按这里,出咖啡。" 每台机器的冲煮方式完全不同,但对你来说,它们都提供同一个简单的动作。

这就是 抽象(abstraction)。展示类 做什么,隐藏它 怎么做。软件中的咖啡机、支付方式、数据库驱动和文件格式处理器都是这样工作的。
🔬
The Core Insightमूल बात核心要点

Abstraction is one of the four pillars of OOP, together with encapsulation, inheritance and polymorphism. It says: write a contract that says what an object must do, and let each concrete class fill in the details. Python enforces this contract with Abstract Base Classes (ABC) and the @abstractmethod decorator.

Abstraction OOP के चार स्तंभों में से एक है — encapsulation, inheritance और polymorphism के साथ। यह कहता है: एक contract लिखो जो बताए कि object को क्या करना है, और हर concrete class को details भरने दो। Python यह contract Abstract Base Classes (ABC) और @abstractmethod decorator से लागू करता है।

抽象 是 OOP 四大支柱之一,另外三个是封装、继承和多态。它的意思是:写一份契约,说明对象必须做什么,让每个具体类去补充细节。Python 用 抽象基类(ABC)和 @abstractmethod 装饰器来强制执行这份契约。

▶️
This Tutorial Has Six Simulators and a Quizइस Tutorial में छह Simulators और एक Quiz है本教程有六个模拟器和一个小测验

Look for the interactive boxes: the ABC Gate Lab (Section 05), Abstract or Concrete? (06), the Payment Router (08), describe() Step by Step and the Shape Studio (09) and the Bug Doctor (11). Every result comes from real Python runs.

Interactive डिब्बे खोजें: ABC Gate Lab (Section 05), Abstract या Concrete? (06), Payment Router (08), describe() क़दम-दर-क़दम और Shape Studio (09) और Bug Doctor (11)। हर नतीजा असली Python runs से है।

请留意这些互动框:ABC 关卡实验室(第 05 节)、抽象还是具体?(06)、支付路由器(08)、describe() 逐步演示 和 图形工作室(09),以及 Bug 医生(11)。每个结果都来自真实的 Python 运行。


SectionSection第 02 节

Interface vs Implementation 🎛️Interface बनाम Implementation 🎛️接口 vs 实现 🎛️

Every abstraction has two sides. The interface is the promise: "if you are a Shape, you must be able to tell me your area." The implementation is how each concrete class keeps that promise — a circle uses π·r², a rectangle uses w × h.

हर abstraction के दो पहलू होते हैं। Interface वादा है: "अगर तुम Shape हो, तो तुम्हें अपना area बताना ही होगा।" Implementation यह है कि हर concrete class वह वादा कैसे निभाती है — circle π·r² लेता है, rectangle w × h।

每个抽象都有两面。接口 是承诺:"如果你是一个 Shape,你就必须能告诉我你的面积。"实现 是每个具体类如何兑现这个承诺 — 圆用 π·r²,矩形用 w × h。

🏠 Interface (Abstract)Interface (Abstract)接口(抽象)
Says what must be doneबताता है क्या करना है说明必须做 什么
Declares method names and parametersMethod के नाम और parameters घोषित करता है声明方法名和参数
Does not say howकैसे, यह नहीं बताता不 说明怎么做
Cannot be instantiated directlyसीधे object नहीं बना सकते不能直接实例化
Written once — reused by every implementationएक बार लिखा — हर implementation दोबारा इस्तेमाल करता है只写一次 — 所有实现共用
🛠️ Implementation (Concrete)Implementation (Concrete)实现(具体)
Says how it is doneबताता है कैसे होता है说明 怎么 做
Fills in every abstract methodहर abstract method भरता है补全每一个抽象方法
Free to use any algorithm insideअंदर कोई भी algorithm लगाने की आज़ादी内部可以使用任何算法
Can be instantiated and usedObject बनाकर इस्तेमाल कर सकते हैं可以实例化并使用
Many concrete classes can share one interfaceकई concrete classes एक ही interface share कर सकती हैं多个具体类可以共用一个接口
One Button Outside, Six Steps Insideबाहर एक बटन, अंदर छह क़दम外面一个按钮,里面六个步骤
Coffee machine interface and hidden implementationINTERFACE — YOU SEEINTERFACE — जो दिखता है接口 — 你看到的EspressoLatteCappuccinoOffIMPLEMENTATION — HIDDENIMPLEMENTATION — छिपा हुआ实现 — 隐藏的⚙️Grind the beansबीज पीसो磨豆子⚖️Measure 18 g18 g नापो称 18 克🔩Tamp — 30 lb of forceदबाओ — 30 lb ज़ोर压粉 — 30 磅力🔥Heat water to 93 °Cपानी 93 °C तक गर्म把水加热到 93 °C⏱️Extract for 25 s25 s extraction萃取 25 秒🧽Clean the group headGroup head साफ़ करो清洗冲煮头☕ESPRESSOESPRESSO浓缩咖啡

You press one button on the interface. The six-step implementation stays hidden behind it.

आप interface का एक बटन दबाते हैं। छह क़दम वाला implementation उसके पीछे छिपा रहता है।

你只按接口上的一个按钮,六个步骤的实现都藏在它后面。

Why It Mattersयह क्यों ज़रूरी है为什么这很重要

Without abstraction, callers must know which exact class they are dealing with. With abstraction, callers depend only on the interface — and a new implementation slots in without changing a single line of caller code. This is a short sketch to compare the two styles (it is not meant to be run):

Abstraction के बिना callers को पता होना चाहिए कि वे किस class से बात कर रहे हैं। Abstraction के साथ callers सिर्फ़ interface पर निर्भर होते हैं — और नया implementation caller के code की एक भी line बदले बिना जुड़ जाता है। दोनों तरीक़ों की तुलना के लिए यह छोटा sketch है (इसे चलाने के लिए नहीं लिखा गया):

没有抽象时,调用方必须知道自己面对的是哪个具体类。有了抽象,调用方只依赖接口 — 新的实现可以直接接入,调用方代码一行都不用改。下面是比较两种写法的简短示意(不用于运行):

# Without abstraction - the caller must handle every payment type itself
def process(payment_type, data, amount):
    if payment_type == "credit":
        # Do card-specific stuff
        ...
    elif payment_type == "upi":
        # Do UPI-specific stuff
        ...
    elif payment_type == "crypto":
        # Do crypto-specific stuff
        ...
    # A new payment method -> edit this function -> risk breaking callers

# WITH abstraction - the caller just talks to the interface
def process(payment: PaymentMethod, amount):
    payment.authenticate()
    payment.charge(amount)
    # A new payment method? Just implement PaymentMethod. No changes here.

SectionSection第 03 节

Meet ABC and @abstractmethod 🧩ABC और @abstractmethod से मिलिए 🧩认识 ABC 和 @abstractmethod 🧩

Python's abc module ("Abstract Base Classes") gives you two tools: ABC, a base class to inherit from, and @abstractmethod, a decorator that marks a method as must be overridden.

Python का abc module ("Abstract Base Classes") दो औज़ार देता है: ABC, जिससे inherit करते हैं, और @abstractmethod, एक decorator जो method को override करना ज़रूरी बताता है।

Python 的 abc 模块("抽象基类")提供两样工具:ABC,一个用来继承的基类;以及 @abstractmethod,一个把方法标记为 必须重写 的装饰器。

from abc import ABC, abstractmethod

class Shape(ABC):                     # inherit from ABC -> this class is abstract
    # -- Abstract methods: no body needed, just a signature --
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass


# Try to instantiate the abstract class directly -> error
try:
    s = Shape()
except TypeError as e:
    print("Blocked:", e)
OUTPUT
Blocked: Can't instantiate abstract class Shape without an implementation for abstract methods 'area', 'perimeter'
🐍
Fixed: The Error Text Depends on Your Python Versionसुधार: Error का text Python version पर निर्भर है已修正:错误信息取决于 Python 版本

The original tutorial showed Can't instantiate abstract class Shape with abstract methods area, perimeter. That is the Python 3.11-and-older wording. Since Python 3.12 it says without an implementation for abstract methods 'area', 'perimeter'. The error type — TypeError — is the same. All outputs here are real runs on Python 3.13.16.

मूल tutorial में Can't instantiate abstract class Shape with abstract methods area, perimeter दिखाया गया था। यह Python 3.11 और पुराने versions का text है। Python 3.12 से यह without an implementation for abstract methods 'area', 'perimeter' कहता है। Error का प्रकार — TypeError — वही है। यहाँ सारे outputs Python 3.13.16 पर असली runs हैं।

原教程显示的是 Can't instantiate abstract class Shape with abstract methods area, perimeter。这是 Python 3.11 及更早版本的措辞。从 Python 3.12 起,它显示 without an implementation for abstract methods 'area', 'perimeter'。错误类型 — TypeError — 没变。这里所有输出都是在 Python 3.13.16 上真实运行的结果。

💡
Two Small Rules to Rememberयाद रखने के दो छोटे नियम两条要记住的小规则

A class that inherits from ABC and has at least one @abstractmethod is abstract. An abstract class cannot be instantiated until every abstract method has a real implementation. Those two rules are the whole enforcement system.

जो class ABC से inherit करती है और जिसमें कम से कम एक @abstractmethod है, वह abstract है। Abstract class का object नहीं बन सकता जब तक हर abstract method का असली implementation न हो। पूरा नियंत्रण इन्हीं दो नियमों से चलता है।

继承自 ABC 并且至少有一个 @abstractmethod 的类就是抽象类。在每个抽象方法都有真正的实现之前,抽象类 不能被实例化。整个强制机制就是这两条规则。


SectionSection第 04 节

The Contract and Its Implementations 📜Contract और उसके Implementations 📜契约与它的实现 📜

One abstract Shape contract sits at the top. It declares area() and perimeter() as promises. Three concrete classes below — Circle, Rectangle, Triangle — each keep the promise in their own way. The interface is the same; the implementations differ.

ऊपर एक abstract Shape contract है। यह area() और perimeter() को वादों के रूप में घोषित करता है। नीचे तीन concrete classes — Circle, Rectangle, Triangle — अपने-अपने तरीक़े से वादा निभाती हैं। Interface एक जैसा है; implementations अलग।

顶部是一个抽象的 Shape 契约,它把 area() 和 perimeter() 声明为承诺。下面三个具体类 — Circle、Rectangle、Triangle — 各自用自己的方式兑现承诺。接口相同,实现不同。

One Abstract Contract — Many Implementationsएक Abstract Contract — कई Implementations一份抽象契约 — 多种实现
Abstract contract with three implementationsABSTRACT (ABC)ABSTRACT (ABC)抽象(ABC)class Shape(ABC):@abstractmethod def area(self)@abstractmethod def perimeter(self)promises only — no formulasसिर्फ़ वादे — कोई formula नहीं只有承诺 — 没有公式CIRCLE(Shape)def area(self): π · r²def perimeter(self): 2π · r✓ contract kept✓ contract निभाया✓ 契约已兑现RECTANGLE(Shape)def area(self): w · hdef perimeter(self): 2(w + h)✓ contract kept✓ contract निभाया✓ 契约已兑现TRIANGLE(Shape)def area(self): √(s(s−a)(s−b)(s−c))def perimeter(self): a + b + c✓ contract kept✓ contract निभाया✓ 契约已兑现

The same two method names in every subclass, with three different formulas underneath. That is abstraction.

हर subclass में वही दो method नाम, और नीचे तीन अलग formulas। यही abstraction है।

每个子类都有同样的两个方法名,底下却是三种不同的公式。这就是抽象。


SectionSection第 05 节

Abstract Classes Cannot Be Instantiated 🚫Abstract Class का Object नहीं बनता 🚫抽象类不能被实例化 🚫

This guarantee is what makes abstract classes useful. Python refuses to create an object of an abstract class until every abstract method has a real implementation. If you try, you get a TypeError at creation time — before any of your methods can run.

यही guarantee abstract classes को काम का बनाती है। जब तक हर abstract method का असली implementation न हो, Python abstract class का object बनाने से मना कर देता है। कोशिश करें तो object बनते समय ही TypeError मिलता है — आपका कोई method चलने से पहले।

这个保证正是抽象类有用的原因。在每个抽象方法都有真正的实现之前,Python 拒绝 创建抽象类的对象。如果你尝试,在创建时就会得到 TypeError — 在你的任何方法运行之前。

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass


# -- Attempt 1: instantiate the abstract class directly -----
try:
    s = Shape()
except TypeError as e:
    print("Blocked:", e)


# -- Attempt 2: subclass but forget one abstract method -----
class HalfCircle(Shape):
    def area(self):
        return 42
    # perimeter() is still abstract - HalfCircle is still abstract too

try:
    h = HalfCircle()
except TypeError as e:
    print("Blocked:", e)


# -- Attempt 3: fully concrete - works ----------------------
class Square(Shape):
    def __init__(self, side):
        self.side = side
    def area(self):
        return self.side ** 2
    def perimeter(self):
        return 4 * self.side

sq = Square(5)                    # works - every abstract method is implemented
print(sq.area(), sq.perimeter())     # 25 20
OUTPUT
Blocked: Can't instantiate abstract class Shape without an implementation for abstract methods 'area', 'perimeter' Blocked: Can't instantiate abstract class HalfCircle without an implementation for abstract method 'perimeter' 25 20
Instantiation — Abstract Blocked, Concrete AllowedObject बनाना — Abstract रुका, Concrete चला实例化 — 抽象被拦,具体放行
Three instantiation attempts through the ABC gateATTEMPT 1प्रयास 1尝试 1Shape()the abstract class itselfख़ुद abstract class抽象类本身TypeErrormissing area,area,缺少 area、perimeterperimeter ग़ायबperimeterATTEMPT 2प्रयास 2尝试 2HalfCircle()missing perimeter()perimeter() ग़ायब缺少 perimeter()TypeErrormissingग़ायब:缺少perimeterATTEMPT 3प्रयास 3尝试 3Square(5)both methods writtenदोनों methods लिखे两个方法都写了Square #1contract metcontract पूरा契约满足object createdobject बना对象已创建PYTHON'S ABC GATEPYTHON का ABC GATEPython 的 ABC 关卡checks that everyजाँचता है कि हर检查每个@abstractmethodhas a real bodyका असली body है都有真正的实现contract check

Every creation passes the ABC gate. If any abstract method is still missing, the object is never created.

हर object बनाने की कोशिश ABC gate से गुज़रती है। कोई abstract method बाक़ी हो तो object कभी नहीं बनता।

每次创建对象都要经过 ABC 关卡。只要还缺一个抽象方法,对象就不会被创建。

🧪 Simulator: ABC Gate Lab🧪 Simulator: ABC Gate Lab🧪 模拟器:ABC 关卡实验室

Switch the pieces on and off. Remove (ABC), remove an @abstractmethod, forget a method in Square — then watch the gate. The code and output are checked against real Python for all 64 combinations.

हिस्सों को on/off कीजिए। (ABC) हटाइए, कोई @abstractmethod हटाइए, Square में कोई method भूल जाइए — फिर gate देखिए। Code और output सभी 64 combinations के लिए असली Python से जाँचे गए हैं।

把各个部分打开或关闭。去掉 (ABC)、去掉某个 @abstractmethod、在 Square 里漏掉一个方法 — 然后看关卡的反应。全部 64 种组合的代码和输出都已与真实 Python 对照。

ABC Gate LabABC Gate LabABC 关卡实验室64 combinations · real outputs64 combinations · असली outputs64 种组合 · 真实输出
Shape:Shape:Shape:
Square writes:Square लिखता है:Square 写了:
Create:बनाएँ:创建:
Generated codeबना हुआ code生成的代码
The contractContract契约
ABC GATE
OutputOutput输出

SectionSection第 06 节

Abstract and Concrete Methods Together 🤝Abstract और Concrete Methods साथ-साथ 🤝抽象方法与具体方法并存 🤝

An abstract class is not only abstract methods. It can also hold fully written methods that every subclass inherits for free. This is how you share common behaviour and still enforce the contract.

Abstract class में सिर्फ़ abstract methods नहीं होते। उसमें पूरे लिखे हुए methods भी हो सकते हैं, जो हर subclass को मुफ़्त में inherit होते हैं। इसी तरह आप साझा व्यवहार बाँटते हैं और contract भी लागू रखते हैं।

抽象类里不 只 有抽象方法。它也可以包含完整写好的方法,每个子类都能免费继承。这样你既能共享通用行为,又能强制执行契约。

Below, PaymentMethod has a concrete __init__ and log_transaction, plus two abstract methods. The last three lines (added so you can see real output) use the CreditCard subclass.

नीचे PaymentMethod में concrete __init__ और log_transaction हैं, साथ में दो abstract methods। आख़िरी तीन lines (ताकि आप असली output देख सकें) CreditCard subclass इस्तेमाल करती हैं।

下面的 PaymentMethod 有具体的 __init__ 和 log_transaction,外加两个抽象方法。最后三行(为了让你看到真实输出而添加)使用了 CreditCard 子类。

from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    def __init__(self, holder):
        self.holder = holder                # concrete - shared setup

    # -- ABSTRACT - every subclass must implement --
    @abstractmethod
    def authenticate(self):
        pass

    @abstractmethod
    def charge(self, amount):
        pass

    # -- CONCRETE - shared, but subclasses can still override --
    def log_transaction(self, action, amount):
        print(f"  [log] {self.holder}: {action} of ${amount}")


class CreditCard(PaymentMethod):
    def __init__(self, holder, number):
        super().__init__(holder)          # reuse the base setup
        self.number = number

    def authenticate(self):
        print(f"Verifying card ****{self.number[-4:]}")
        return True

    def charge(self, amount):
        print(f"Charging ${amount} to card")
        self.log_transaction("charge", amount)   # inherited from base - no duplication


card = CreditCard("Alice", "4111111111113456")
if card.authenticate():
    card.charge(500)
OUTPUT
Verifying card ****3456 Charging $500 to card [log] Alice: charge of $500
🔑
The Split You Wantसही बँटवारा你想要的划分

Mark a method abstract when every subclass really does it differently — the algorithm itself changes. Keep a method concrete when it would be copied unchanged into every subclass. You get enforcement where it matters and reuse where it is free.

Method को abstract तब बनाइए जब हर subclass उसे सच में अलग तरीक़े से करे — algorithm ही बदल जाए। Method को concrete तब रखिए जब वह हर subclass में बिना बदले copy होता। ज़रूरी जगह पर नियंत्रण, और बाक़ी जगह मुफ़्त reuse।

当每个子类的做法确实不同 — 算法本身会变 — 时,把方法标为 抽象。当方法会被原样复制到每个子类时,把它保留为 具体 方法。该强制的地方强制,能复用的地方免费复用。

🧠 Simulator: Abstract or Concrete?🧠 Simulator: Abstract या Concrete?🧠 模拟器:抽象还是具体?

Eight methods from this tutorial. For each one, ask: "Would every subclass write this exactly the same way?" Yes → concrete. No → abstract.

इस tutorial के आठ methods। हर एक के लिए पूछिए: "क्या हर subclass इसे बिल्कुल एक जैसा लिखेगी?" हाँ → concrete। नहीं → abstract।

本教程中的八个方法。对每一个问一句:"每个子类都会用完全一样的方式写它吗?" 是 → 具体。否 → 抽象。

Abstract or Concrete?Abstract या Concrete?抽象还是具体?
@abstractmethod
concrete (shared)concrete (साझा)具体(共享)

SectionSection第 07 节

Polymorphism Through Abstraction 🔀Abstraction के ज़रिए Polymorphism 🔀通过抽象实现多态 🔀

This is where abstraction pays off. One function, process(payment, amount), accepts any object that follows the PaymentMethod contract. Three different objects go through it. Each one runs its own charge() — same interface, different behaviour, no if/else.

यहीं abstraction का फ़ायदा मिलता है। एक function, process(payment, amount), ऐसा कोई भी object लेता है जो PaymentMethod contract मानता हो। तीन अलग objects इससे गुज़रते हैं। हर एक अपना charge() चलाता है — वही interface, अलग व्यवहार, कोई if/else नहीं।

这正是抽象的回报。一个函数 process(payment, amount) 接受 任何 遵守 PaymentMethod 契约的对象。三个不同的对象经过它,每个都运行 自己的 charge() — 接口相同,行为不同,没有 if/else。

One Interface · Many Implementations · Zero Branchesएक Interface · कई Implementations · शून्य Branches一个接口 · 多种实现 · 零分支
One generic function, three implementationsCreditCardalicecard ****3456CreditCard.charge()card gatewaycard gateway银行卡网关UPIPaymentbobbob@upiUPIPayment.charge()UPI debitUPI debitUPI 扣款CryptoWalletchandra0xabc123CryptoWallet.charge()blockchain broadcastblockchain broadcast区块链广播GENERIC FUNCTIONGENERIC FUNCTION通用函数def process(payment, amount): payment.charge(amount)

process() calls charge() once. Each object runs its own version. A fourth payment type means a new class — process() does not change.

process() एक बार charge() बुलाता है। हर object अपना version चलाता है। चौथा payment type = नई class — process() नहीं बदलता।

process() 只调用一次 charge(),每个对象运行自己的版本。第四种支付方式只需一个新类 — process() 不用改。


SectionSection第 08 节

Practical Example 1 — Payment Gateway 💳Practical Example 1 — Payment Gateway 💳实战示例 1 — 支付网关 💳

Three payment methods follow one abstract contract. The processor function does not know — or care — which one it holds.

तीन payment methods एक ही abstract contract मानते हैं। Processor function को पता नहीं — न परवाह — कि उसके पास कौन-सा है।

三种支付方式遵守同一份抽象契约。处理函数不知道 — 也不关心 — 自己拿到的是哪一种。

from abc import ABC, abstractmethod


class PaymentMethod(ABC):
    """Abstract base for every payment method."""

    def __init__(self, holder):
        self.holder = holder

    # == ABSTRACT - every payment method must implement =======
    @abstractmethod
    def authenticate(self) -> bool:
        """Verify the payer's identity."""
        ...

    @abstractmethod
    def charge(self, amount) -> None:
        """Deduct the amount from the payer."""
        ...

    @abstractmethod
    def refund(self, amount) -> None:
        """Return the amount to the payer."""
        ...

    # == CONCRETE - inherited by every payment method =========
    def log(self, action, amount):
        print(f"  [log] {self.holder}: {action} of {amount}")


class CreditCard(PaymentMethod):
    def __init__(self, holder, card_number):
        super().__init__(holder)
        self.card_number = card_number

    def authenticate(self):
        print(f"Verifying card ****{self.card_number[-4:]}")
        return True

    def charge(self, amount):
        print(f"Card charged ${amount}")
        self.log("card charge", amount)

    def refund(self, amount):
        print(f"Card refunded ${amount}")
        self.log("card refund", amount)


class UPIPayment(PaymentMethod):
    def __init__(self, holder, upi_id):
        super().__init__(holder)
        self.upi_id = upi_id

    def authenticate(self):
        print(f"UPI PIN check for {self.upi_id}")
        return True

    def charge(self, amount):
        print(f"Debiting ₹{amount} via UPI")
        self.log("UPI charge", amount)

    def refund(self, amount):
        print(f"Refunding ₹{amount} to UPI")
        self.log("UPI refund", amount)


class CryptoWallet(PaymentMethod):
    def __init__(self, holder, wallet_address):
        super().__init__(holder)
        self.wallet_address = wallet_address

    def authenticate(self):
        print("Verifying wallet signature")
        return True

    def charge(self, amount):
        print(f"Broadcasting {amount} to blockchain")
        self.log("crypto charge", amount)

    def refund(self, amount):
        print(f"Broadcasting refund of {amount}")
        self.log("crypto refund", amount)


# == Generic processor - does NOT know which method it holds ==
def process_purchase(payment: PaymentMethod, amount):
    print(f"\n▶ Processing for {payment.holder}:")
    if payment.authenticate():
        payment.charge(amount)


# One list of different concrete types, one uniform loop
payments = [
    CreditCard("Alice",   "4111111111113456"),
    UPIPayment("Bob",     "bob@upi"),
    CryptoWallet("Chandra", "0xabc123"),
]

for p in payments:
    process_purchase(p, 500)


# Trying to instantiate the abstract base is blocked
try:
    PaymentMethod("Anyone")
except TypeError as e:
    print("\nBlocked:", e)
OUTPUT
▶ Processing for Alice: Verifying card ****3456 Card charged $500 [log] Alice: card charge of 500 ▶ Processing for Bob: UPI PIN check for bob@upi Debiting ₹500 via UPI [log] Bob: UPI charge of 500 ▶ Processing for Chandra: Verifying wallet signature Broadcasting 500 to blockchain [log] Chandra: crypto charge of 500 Blocked: Can't instantiate abstract class PaymentMethod without an implementation for abstract methods 'authenticate', 'charge', 'refund'
🏆
The Real Payoffअसली फ़ायदा真正的回报

process_purchase has no if payment_type == anywhere. It receives "some PaymentMethod" and trusts the interface. Adding ApplePay next month means writing one new subclass and adding it to the list — nothing else changes. Try exactly that in the simulator below.

process_purchase में कहीं भी if payment_type == नहीं है। उसे "कोई PaymentMethod" मिलता है और वह interface पर भरोसा करता है। अगले महीने ApplePay जोड़ना = एक नई subclass लिखना और list में डालना — और कुछ नहीं बदलता। नीचे simulator में ठीक यही आज़माइए।

process_purchase 里任何地方都没有 if payment_type ==。它收到"某个 PaymentMethod",并信任接口。下个月加上 ApplePay,只需写一个新子类并放进列表 — 其他都不用改。在下面的模拟器里亲自试试。

💳 Simulator: Payment Router💳 Simulator: Payment Router💳 模拟器:支付路由器

Pick an object, an action and an amount. Watch which methods run, in order: the subclass's own versions, and the shared log() from the abstract base. ApplePay is a brand-new subclass — process_purchase was not touched.

Object, action और amount चुनिए। देखिए कौन-से methods किस क्रम में चलते हैं: subclass के अपने versions, और abstract base का साझा log()। ApplePay बिल्कुल नई subclass है — process_purchase को छुआ तक नहीं गया।

选择一个对象、一个操作和一个金额。观察哪些方法按什么顺序运行:子类自己的版本,以及抽象基类中共享的 log()。ApplePay 是全新的子类 — process_purchase 一点没改。

Payment RouterPayment Router支付路由器method calls recorded from real runsmethod calls असली runs से रिकॉर्ड方法调用来自真实运行记录
Object:Object:对象:
Action:Action:操作:
Amount:Amount:金额:
Method map — numbers show the call orderMethod map — नंबर call का क्रम दिखाते हैं方法地图 — 数字表示调用顺序
Your codeआपका code你的代码
The chosen classचुनी हुई class所选的类
OutputOutput输出

SectionSection第 09 节

Practical Example 2 — Shape Hierarchy 📐Practical Example 2 — Shape Hierarchy 📐实战示例 2 — 图形层次结构 📐

Here the abstract Shape also has a concrete describe(). It is written once, in the base class — yet it prints the right numbers for every shape, because it calls self.area() and self.perimeter(), and those run each subclass's own version.

यहाँ abstract Shape में एक concrete describe() भी है। यह base class में सिर्फ़ एक बार लिखा है — फिर भी हर shape के सही नंबर छापता है, क्योंकि यह self.area() और self.perimeter() बुलाता है, और वे हर subclass का अपना version चलाते हैं।

这里的抽象类 Shape 还有一个具体方法 describe()。它只在基类里写了一次 — 却能为每种图形打印正确的数字,因为它调用 self.area() 和 self.perimeter(),而这两个方法运行的是各个子类自己的版本。

from abc import ABC, abstractmethod
import math


class Shape(ABC):
    @abstractmethod
    def area(self):
        ...

    @abstractmethod
    def perimeter(self):
        ...

    # Concrete - shared by every shape
    def describe(self):
        name = type(self).__name__
        print(f"{name:10s}  area={self.area():7.2f}  perimeter={self.perimeter():7.2f}")


class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    def area(self):
        return math.pi * self.radius ** 2
    def perimeter(self):
        return 2 * math.pi * self.radius


class Rectangle(Shape):
    def __init__(self, w, h):
        self.w, self.h = w, h
    def area(self):
        return self.w * self.h
    def perimeter(self):
        return 2 * (self.w + self.h)


class Triangle(Shape):
    def __init__(self, a, b, c):
        self.a, self.b, self.c = a, b, c
    def area(self):
        s = (self.a + self.b + self.c) / 2
        return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
    def perimeter(self):
        return self.a + self.b + self.c


shapes: list[Shape] = [
    Circle(5),
    Rectangle(4, 6),
    Triangle(3, 4, 5),
]

for s in shapes:
    s.describe()   # inherited concrete method, uses each shape's own area/perimeter
OUTPUT
Circle area= 78.54 perimeter= 31.42 Rectangle area= 24.00 perimeter= 20.00 Triangle area= 6.00 perimeter= 12.00

👣 Simulator: describe() Step by Step👣 Simulator: describe() क़दम-दर-क़दम👣 模拟器:describe() 逐步演示

A shorter version of the code, recorded with sys.settrace. Watch the call stack: Shape.describe() (the shared concrete method) calls down into Circle.area() or Rectangle.area(). The abstract Shape.area() never runs.

Code का छोटा version, sys.settrace से रिकॉर्ड किया हुआ। Call stack देखिए: Shape.describe() (साझा concrete method) नीचे Circle.area() या Rectangle.area() को बुलाता है। Abstract Shape.area() कभी नहीं चलता।

这是代码的精简版,用 sys.settrace 录制。观察调用栈:Shape.describe()(共享的具体方法)向下调用 Circle.area() 或 Rectangle.area()。抽象的 Shape.area() 从未运行。

describe() Step by Stepdescribe() क़दम-दर-क़दमdescribe() 逐步演示recorded with sys.settracesys.settrace से रिकॉर्ड用 sys.settrace 录制
Object:Object:对象:
CodeCode代码
Call stack (newest at the bottom)Call stack (सबसे नया नीचे)调用栈(最新的在最下面)
The objectObject对象
OutputOutput输出

📐 Simulator: Shape Studio📐 Simulator: Shape Studio📐 模拟器:图形工作室

Change the sizes and watch the inherited describe() line update. Try a triangle whose sides cannot meet, such as 2, 3, 9 — the subclass's area() fails, not the contract. Checked against Python on 320 shapes.

Sizes बदलिए और inherited describe() की line बदलते देखिए। ऐसा triangle आज़माइए जिसकी भुजाएँ मिल न सकें, जैसे 2, 3, 9 — subclass का area() fail होता है, contract नहीं। 320 shapes पर Python से जाँचा गया।

改变尺寸,看继承来的 describe() 输出如何变化。试试三边无法围成三角形的情况,比如 2、3、9 — 出错的是子类的 area(),而不是契约。已在 320 个图形上与 Python 对照。

Shape StudioShape Studio图形工作室one describe() · three implementationsएक describe() · तीन implementations一个 describe() · 三种实现
Shape:Shape:图形:
OutputOutput输出

SectionSection第 10 节

Abstraction vs Encapsulation ⚖️Abstraction बनाम Encapsulation ⚖️抽象 vs 封装 ⚖️

Beginners often mix these two up. Both are about "hiding", but they hide different things.

Beginners अक्सर इन दोनों को मिला देते हैं। दोनों "छिपाने" के बारे में हैं, पर अलग-अलग चीज़ें छिपाते हैं।

初学者经常把这两个概念搞混。两者都与"隐藏"有关,但隐藏的东西不同。

🏛️ Abstraction
Hides complexity: what a class does vs howजटिलता छिपाता है: class क्या करती है बनाम कैसे隐藏 复杂性:类做什么 vs 怎么做
Tool: ABC + @abstractmethodऔज़ार: ABC + @abstractmethod工具:ABC + @abstractmethod
Answers: "which methods must every X have?"जवाब देता है: "हर X में कौन-से methods होने ही चाहिए?"回答:"每个 X 必须有哪些方法?"
Enforced at the class-design levelClass design के स्तर पर लागू在类设计层面强制
Example: Shape declares area(); Circle implements itउदाहरण: Shape area() घोषित करता है; Circle उसे लिखता है例子:Shape 声明 area(),Circle 实现它
🔒 Encapsulation
Hides data: private state behind a public APIData छिपाता है: public API के पीछे private state隐藏 数据:把私有状态藏在公共 API 后面
Tool: _x, __x naming + @propertyऔज़ार: _x, __x naming + @property工具:_x、__x 命名 + @property
Answers: "who can read or change this attribute?"जवाब देता है: "इस attribute को कौन पढ़ या बदल सकता है?"回答:"谁能读取或修改这个属性?"
Enforced at the attribute-access levelAttribute access के स्तर पर लागू在属性访问层面强制
Example: _balance changes only through a checked deposit()उदाहरण: _balance सिर्फ़ जाँच वाले deposit() से बदलता है例子:_balance 只能通过带检查的 deposit() 修改
🔮
Both Together in Real Codeअसली Code में दोनों साथ真实代码中两者并用

A well-designed class usually uses both. Abstraction sets the class's contract with the outside world (the public methods every subclass must write). Encapsulation hides its data (private attributes reached only through those methods). One controls the shape of your class; the other controls the doors and locks.

अच्छी तरह design की गई class आमतौर पर दोनों इस्तेमाल करती है। Abstraction बाहरी दुनिया से class का contract तय करता है (वे public methods जो हर subclass को लिखने ही हैं)। Encapsulation उसका data छिपाता है (private attributes जिन तक सिर्फ़ उन्हीं methods से पहुँचा जाता है)। एक class का आकार तय करता है; दूसरा दरवाज़े और ताले।

设计良好的类通常 两者 并用。抽象 规定类与外界的契约(每个子类必须编写的公共方法)。封装 隐藏它的数据(只能通过这些方法访问的私有属性)。一个控制类的 形状,另一个控制 门和锁。


SectionSection第 11 节

Common Mistakes (and Fixes) 🩹आम ग़लतियाँ (और उनके हल) 🩹常见错误(及修正)🩹

Mistakeग़लती错误What goes wrongक्या बिगड़ता है会出什么问题Fixहल修正
Forgetting to inherit from ABCABC से inherit करना भूलना忘记继承 ABC@abstractmethod is silently ignored — the class can be instantiated@abstractmethod चुपचाप अनदेखा — class का object बन जाता है@abstractmethod 被悄悄忽略 — 这个类可以被实例化Make sure the base class inherits from abc.ABCपक्का करें कि base class abc.ABC से inherit करे确保基类继承自 abc.ABC
Forgetting the @abstractmethod decorator@abstractmethod decorator भूलना忘记写 @abstractmethod 装饰器It is just a normal method; subclasses are not forced to override itयह बस सामान्य method है; subclasses पर override करने का दबाव नहीं它只是普通方法,子类不会被强制重写Add @abstractmethod above every method that must be overriddenहर उस method के ऊपर @abstractmethod लगाएँ जिसे override करना ज़रूरी है在每个必须重写的方法上方加 @abstractmethod
Trying to instantiate the abstract baseAbstract base का object बनाने की कोशिश试图实例化抽象基类TypeError at creation — often a surprise in test codeबनाते समय TypeError — test code में अक्सर चौंकाता है创建时 TypeError — 在测试代码中常常让人意外Never call PaymentMethod(...); create a concrete subclassPaymentMethod(...) कभी न बुलाएँ; concrete subclass का object बनाएँ永远不要调用 PaymentMethod(...);去实例化具体子类
Missing one abstract method in a subclassSubclass में एक abstract method छूट जाना子类漏掉一个抽象方法The subclass is still abstract; Subclass() raises TypeErrorSubclass अब भी abstract है; Subclass() पर TypeError子类仍是抽象的;Subclass() 抛出 TypeErrorWrite every abstract method — or keep the subclass abstract on purposeहर abstract method लिखें — या subclass को जान-बूझकर abstract रखें实现 每一个 抽象方法 — 或者有意让子类保持抽象
Changing an abstract method's parametersAbstract method के parameters बदलना修改抽象方法的参数Python does not check parameters, so the class is accepted — the call fails later with TypeErrorPython parameters नहीं जाँचता, इसलिए class मान ली जाती है — call बाद में TypeError से fail होती हैPython 不检查参数,所以这个类能通过 — 之后调用时才以 TypeError 失败Keep the same parameters. If new ones are needed, give them defaultsParameters वही रखें। नए चाहिए तो उन्हें default दें保持参数一致。需要新参数时给它默认值
Using an abstract class for just one implementationसिर्फ़ एक implementation के लिए abstract class只有一个实现却用抽象类Extra code with no benefit — one child, one boilerplate parentबिना फ़ायदे का अतिरिक्त code — एक child, एक खोखला parent多写代码却没好处 — 一个子类配一个样板父类Add an abstract base only when you have (or truly expect) two or more implementationsAbstract base तभी जोड़ें जब दो या ज़्यादा implementations हों (या सच में आने वाले हों)只有当你有(或确实预期会有)两个以上实现时才引入抽象基类
Treating @abstractmethod as a "TODO" marker@abstractmethod को "TODO" निशान समझना把 @abstractmethod 当作"待办"标记No subclass can be created until it fills the method in — half-finished work blocks everyoneजब तक method न भरा जाए कोई subclass नहीं बन सकती — अधूरा काम सबको रोक देता है在补上这个方法之前,任何子类都无法创建 — 半成品会阻塞所有人Use it as a design signal: "every subclass must provide this"इसे design संकेत की तरह इस्तेमाल करें: "हर subclass को यह देना ही है"把它当作设计信号:"每个子类都必须提供这个"

🩺 Simulator: Bug Doctor🩺 Simulator: Bug Doctor🩺 模拟器:Bug 医生

Five of these mistakes, run for real. Buggy code on the left, fixed code on the right, changed lines marked. Notice that two bugs give no error at all — only a quiet None.

इनमें से पाँच ग़लतियाँ, असली run में। बाईं ओर buggy code, दाईं ओर ठीक किया हुआ, बदली lines चिह्नित। ध्यान दें: दो bugs में कोई error नहीं आता — बस चुपचाप None।

其中五个错误的真实运行。左边是有 bug 的代码,右边是修正后的代码,改动的行已标出。注意有两个 bug 完全不报错 — 只是悄悄返回 None。

Bug DoctorBug DoctorBug 医生5 bugs · real outputs5 bugs · असली outputs5 个 bug · 真实输出
❌ BuggyBuggy有 bug
✅ Fixedठीक किया已修正

SectionSection第 12 节

Quick Reference 📋Quick Reference 📋速查表 📋

Taskकाम任务SyntaxSyntax语法Notesनोट说明
Import ABC supportABC support import करना导入 ABC 支持from abc import ABC, abstractmethodStandard library — nothing to installStandard library — कुछ install नहीं करना标准库 — 无需安装
Declare an abstract classAbstract class घोषित करना声明抽象类class Shape(ABC):Inherits from ABCABC से inherit करती है继承自 ABC
Declare an abstract methodAbstract method घोषित करना声明抽象方法@abstractmethod + def m(self): ...Body can be pass or ...Body pass या ... हो सकता है方法体可以是 pass 或 ...
Concrete method in an ABCABC में concrete methodABC 中的具体方法Define it normally — no decoratorसामान्य तरह लिखें — कोई decorator नहीं正常定义 — 不加装饰器Inherited by every subclassहर subclass को inherit होता है每个子类都会继承
Implement in a subclassSubclass में लिखना在子类中实现Override with the same parametersवही parameters रखकर override करें用相同参数重写All abstract methods must be presentसारे abstract methods होने चाहिए所有抽象方法都必须实现
Create a concrete objectConcrete object बनाना创建具体对象obj = ConcreteClass(...)Works once every abstract method is writtenहर abstract method लिखे जाने के बाद चलता है每个抽象方法都写好后才能成功
See what is still abstractक्या अब भी abstract है, देखना查看哪些仍是抽象的ClassName.__abstractmethods__A frozenset of unwritten names (empty when concrete)न लिखे गए नामों का frozenset (concrete हो तो ख़ाली)未实现名字的 frozenset(具体类为空)
Type-hint against the interfaceInterface के हिसाब से type hint按接口写类型提示def f(p: PaymentMethod):Callers can pass any subclassCallers कोई भी subclass दे सकते हैं调用方可以传入任何子类
Common patternआम pattern常见模式A concrete method calls abstract methodsConcrete method abstract methods बुलाता है具体方法调用抽象方法Template Method pattern — like describe()Template Method pattern — जैसे describe()模板方法模式 — 比如 describe()

The __abstractmethods__ row in action (sorted, because a frozenset has no fixed order):

__abstractmethods__ वाली row असल में (sorted, क्योंकि frozenset का कोई तय क्रम नहीं होता):

__abstractmethods__ 这一行的实际效果(用 sorted 排序,因为 frozenset 没有固定顺序):

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self): ...
    @abstractmethod
    def perimeter(self): ...

class HalfCircle(Shape):
    def area(self):
        return 42

class Square(Shape):
    def area(self):
        return 25
    def perimeter(self):
        return 20

print(sorted(Shape.__abstractmethods__))
print(sorted(HalfCircle.__abstractmethods__))
print(Square.__abstractmethods__)
OUTPUT
['area', 'perimeter'] ['perimeter'] frozenset()

SectionSection第 13 节

Golden Rules and Quiz 🏆सुनहरे नियम और Quiz 🏆黄金法则与小测验 🏆

🏦 Abstraction — Rules to RememberAbstraction — याद रखने वाले नियम抽象 — 必须记住的规则
1
Abstraction is about separating what from how. The abstract class defines the contract (what every subclass must be able to do). Each concrete class defines the implementation (how it does it).
Abstraction का मतलब है क्या को कैसे से अलग करना। Abstract class contract तय करती है (हर subclass को क्या करना आना चाहिए)। हर concrete class implementation तय करती है (वह कैसे करती है)।
抽象就是 把"做什么"和"怎么做"分开。抽象类定义契约(每个子类必须能做什么),每个具体类定义实现(它怎么做)。
2
To make a class abstract, inherit from abc.ABC and decorate at least one method with @abstractmethod. You need both — either one alone does not block instantiation.
Class को abstract बनाने के लिए abc.ABC से inherit करें और कम से कम एक method पर @abstractmethod लगाएँ। दोनों चाहिए — अकेला कोई भी object बनना नहीं रोकता।
要让类成为抽象类,继承 abc.ABC,并给至少一个方法加上 @abstractmethod。两者缺一不可 — 只有其中一个都拦不住实例化。
3
Abstract classes cannot be instantiated directly. Trying raises TypeError. That is the enforcement — and the whole point.
Abstract classes का सीधे object नहीं बनता। कोशिश पर TypeError आता है। यही नियंत्रण है — और पूरा मक़सद भी।
抽象类 不能直接实例化。尝试就会抛出 TypeError。这就是强制机制 — 也是全部意义所在。
4
A subclass must write every abstract method before it can be instantiated. Miss one and the subclass stays abstract too.
Object बनने से पहले subclass को हर abstract method लिखना होगा। एक भी छूटा तो subclass भी abstract रहती है।
子类必须实现 每一个 抽象方法才能被实例化。漏掉一个,子类也仍是抽象的。
5
Abstract classes can also hold concrete methods. Use them for behaviour that is the same in every subclass — a shared log(), describe() or setup. Reuse what you can; make abstract only what really differs.
Abstract classes में concrete methods भी हो सकते हैं। उन्हें उस व्यवहार के लिए इस्तेमाल करें जो हर subclass में एक जैसा है — साझा log(), describe() या setup। जो हो सके reuse करें; abstract सिर्फ़ वह बनाएँ जो सच में अलग है।
抽象类也可以包含 具体方法。用它们承载每个子类都相同的行为 — 共享的 log()、describe() 或初始化。能复用就复用;只把真正不同的部分设为抽象。
6
Write functions that accept the abstract type, not one concrete type: def process(p: PaymentMethod), not def process(p: CreditCard). Any subclass then slots in — polymorphism through abstraction.
Functions ऐसे लिखें जो abstract type लें, किसी एक concrete type को नहीं: def process(p: PaymentMethod), न कि def process(p: CreditCard)। तब कोई भी subclass फ़िट हो जाती है — abstraction के ज़रिए polymorphism।
编写 接受抽象类型 的函数,而不是某个具体类型:写 def process(p: PaymentMethod),而不是 def process(p: CreditCard)。这样任何子类都能接入 — 通过抽象实现多态。
7
Add an abstract base only when you have two or more real implementations (or will very soon). An ABC for a single subclass is ceremony with no payoff.
Abstract base तभी जोड़ें जब दो या ज़्यादा असली implementations हों (या बहुत जल्द होंगे)। एक ही subclass के लिए ABC बस दिखावा है।
只有当你有 两个以上真实实现(或很快就会有)时才引入抽象基类。只为一个子类建 ABC 只是形式,没有回报。
8
Keep abstract method parameters stable. Python does not compare them, so a mismatch is not caught when the class is built — it breaks later, when the method is called. If you need new parameters, give them defaults.
Abstract method के parameters स्थिर रखें। Python उनकी तुलना नहीं करता, इसलिए mismatch class बनते समय नहीं पकड़ा जाता — बाद में method call होने पर टूटता है। नए parameters चाहिए तो default दें।
保持抽象方法的参数 稳定。Python 不会比较参数,所以类创建时发现不了不一致 — 要到调用方法时才出错。需要新参数时,给它默认值。
9
Abstraction ≠ encapsulation. Abstraction hides complexity behind a contract. Encapsulation hides data behind an API. A good class uses both.
Abstraction ≠ encapsulation। Abstraction जटिलता को contract के पीछे छिपाता है। Encapsulation data को API के पीछे छिपाता है। अच्छी class दोनों इस्तेमाल करती है।
抽象 ≠ 封装。抽象把 复杂性 藏在契约后面,封装把 数据 藏在 API 后面。好的类两者都用。
10
When in doubt, ask: "Would every subclass write this method exactly the same way?" Yes → put it in the base as a concrete method. No → mark it @abstractmethod.
शक हो तो पूछिए: "क्या हर subclass यह method बिल्कुल एक जैसा लिखेगी?" हाँ → base में concrete method रखें। नहीं → @abstractmethod लगाएँ।
拿不准时就问:"每个子类写这个方法会完全一样吗?"是 → 放在基类里作为具体方法。否 → 标记为 @abstractmethod。

Quick Quiz — 8 Questionsछोटा Quiz — 8 सवाल小测验 — 8 道题

🏆 QuizPick an answer to see why.जवाब चुनें और कारण देखें।选一个答案,看看原因。
🎯
Key Takeawayमुख्य सीख关键要点

Abstraction separates what from how. Inherit from ABC and mark the must-have methods with @abstractmethod: Python then refuses to create any object until every one of them is written. Put shared behaviour in concrete methods of the base, and write callers against the abstract type — new subclasses then slot in without changing them.

Abstraction क्या को कैसे से अलग करता है। ABC से inherit करें और ज़रूरी methods पर @abstractmethod लगाएँ: तब Python तब तक कोई object नहीं बनने देता जब तक हर एक लिखा न जाए। साझा व्यवहार base के concrete methods में रखें, और callers abstract type के हिसाब से लिखें — नई subclasses उन्हें बदले बिना जुड़ जाती हैं।

抽象把 做什么 和 怎么做 分开。继承 ABC,用 @abstractmethod 标记必须有的方法:在它们全部实现之前,Python 拒绝创建任何对象。把共享行为放在基类的具体方法里,按抽象类型编写调用方 — 新子类无需改动调用方就能接入。

🐍 Try Python Yourself

Write, run and visualize Python step by step. No install needed.