The Story That Explains These Three Ideas 🚗इन तीन विचारों को समझाने वाली कहानी 🚗一个讲清这三个概念的故事 🚗
Step 1 — build the body. The factory line rolls out a steel body. It is a real car now, but empty inside. That is
__new__ — it creates the object.Step 2 — fit it out. Painters add colour, workers fit the seats and dashboard. That is
__init__ — it fills in the freshly created object.So every time you write
Car("Honda"), Python runs __new__ to build the empty car, then __init__ to fill in "Honda" as the brand.Two twists follow. First: some things exist only once — the Sun, the company CEO, the app settings. Ask for one a hundred times and you get the same one every time. That is the Singleton pattern — you customise
__new__ to always hand back the same object. Second: some objects act like verbs — you press them and they do something. A horn is an object, but horn() makes a sound. That is __call__ — it lets you call the object itself, just like a function.क़दम 1 — ढाँचा बनाओ। Factory line से steel का ढाँचा निकलता है। अब यह असली कार है, पर अंदर से ख़ाली। यही
__new__ है — यह object बनाता है।क़दम 2 — सजाओ। Painters रंग करते हैं, कारीगर seats और dashboard लगाते हैं। यही
__init__ है — यह अभी बने object को भरता है।तो जब भी आप
Car("Honda") लिखते हैं, Python पहले __new__ से ख़ाली कार बनाता है, फिर __init__ से brand में "Honda" भरता है।आगे दो मोड़ हैं। पहला: कुछ चीज़ें एक ही होती हैं — सूरज, company का CEO, app की settings। सौ बार माँगिए, हर बार वही एक मिलेगी। यही Singleton pattern है — आप
__new__ को ऐसा बनाते हैं कि वह हमेशा वही object लौटाए। दूसरा: कुछ objects क्रिया जैसे होते हैं — दबाओ तो वे कुछ करते हैं। Horn एक object है, पर horn() आवाज़ करता है। यही __call__ है — इससे आप object को ही function की तरह बुला सकते हैं।第 1 步 — 造车身。 生产线推出一个钢制车身。它已经是一辆真正的车了,但里面是空的。这就是
__new__ — 它 创建 对象。第 2 步 — 装配。 油漆工上色,工人安装座椅和仪表盘。这就是
__init__ — 它 填充 刚创建的对象。所以每次你写
Car("Honda"),Python 先运行 __new__ 造出空车,再运行 __init__ 把品牌填为 "Honda"。接下来有两个变化。第一:有些东西只有一个 — 太阳、公司 CEO、应用设置。要一百次,每次得到的都是同一个。这就是 单例模式(Singleton) — 你定制
__new__,让它总是返回同一个对象。第二:有些对象像动词 — 按一下就会 做 某事。喇叭是一个对象,但 horn() 会发出声音。这就是 __call__ — 它让你像调用函数一样调用对象本身。__new__ creates the object. __init__ fills it in. __call__ lets the object be called like a function. Combine them and you get singletons (one object, always reused) and callable objects (verbs in class form). Three tools, one connected family.
__new__ object बनाता है। __init__ उसे भरता है। __call__ object को function की तरह बुलाने देता है। इन्हें मिलाइए और मिलते हैं singletons (एक ही object, हमेशा दोबारा इस्तेमाल) और callable objects (class के रूप में क्रियाएँ)। तीन औज़ार, एक जुड़ा हुआ परिवार।
__new__ 创建对象,__init__ 填充对象,__call__ 让对象可以像函数一样被调用。把它们组合起来,就得到 单例(只有一个对象,始终复用)和 可调用对象(以类的形式表达的动词)。三个工具,一个相互关联的家族。
Look for the interactive boxes: Object Birth, Step by Step (Section 02), the Callable Workshop (04), the Singleton Lab (07) and the Bug Doctor (11). Every result comes from real Python runs.
Interactive डिब्बे खोजें: Object का जन्म, क़दम-दर-क़दम (Section 02), Callable Workshop (04), Singleton Lab (07) और Bug Doctor (11)। हर नतीजा असली Python runs से है।
请留意这些互动框:对象的诞生 · 逐步演示(第 02 节)、可调用对象工坊(04)、单例实验室(07)和 Bug 医生(11)。每个结果都来自真实的 Python 运行。
__new__ vs __init__ — The Full Lifecycle 🏗️__new__ बनाम __init__ — पूरा Lifecycle 🏗️__new__ vs __init__ — 完整的生命周期 🏗️
When you write Person("Alice", 30), two methods run in order. Almost every class only needs __init__ — Python's default __new__ does the creation quietly. Knowing both is what lets you build singletons and subclasses of immutable built-in types (and, later, metaclasses — an upcoming tutorial).
जब आप Person("Alice", 30) लिखते हैं, तो दो methods क्रम से चलते हैं। लगभग हर class को सिर्फ़ __init__ चाहिए — Python का default __new__ चुपचाप object बना देता है। दोनों को समझकर ही आप singletons और immutable built-in types की subclasses बना पाते हैं (और आगे metaclasses भी — आने वाले tutorial में)।
当你写 Person("Alice", 30) 时,两个方法会依次运行。几乎所有类都只需要 __init__ — Python 默认的 __new__ 会悄悄完成创建。理解这两者,才能写出单例和不可变内置类型的子类(以及之后的元类 — 后续教程)。
Person("Alice", 30)Person("Alice", 30) पर असल में क्या होता है执行 Person("Alice", 30) 时实际发生了什么Person.__new__(cls, "Alice", 30). It creates a bare, empty Person object and returns it.Person.__new__(cls, "Alice", 30) बुलाता है। यह एक ख़ाली Person object बनाता है और उसे लौटाता है।Person.__new__(cls, "Alice", 30)。它 创建 一个空的 Person 对象并 返回 它。Person.__init__(new_object, "Alice", 30). It fills in the attributes on that object.Person.__init__(new_object, "Alice", 30) बुलाता है। यह उस object पर attributes भरता है।Person.__init__(new_object, "Alice", 30),它在该对象上 填充 属性。__new__ receives the class (cls) — there is no object yet, so no self. __init__ receives the object (self) that __new__ just made.__new__ को class (cls) मिलती है — अभी object नहीं है, इसलिए self नहीं। __init__ को वह object (self) मिलता है जो __new__ ने अभी बनाया।__new__ 接收的是 类(cls)— 此时还没有对象,所以没有 self。__init__ 接收的是 __new__ 刚创建的 对象(self)。class Person:
def __new__(cls, *args, **kwargs):
print(f" [__new__] creating a new Person object")
instance = super().__new__(cls) # let object create it for us
return instance # MUST return the new object
def __init__(self, name, age):
print(f" [__init__] filling in name={name!r}, age={age}")
self.name = name
self.age = age
print("Creating Alice:")
alice = Person("Alice", 30)
print()
print("Creating Bob:")
bob = Person("Bob", 25)
Every Person(...) call runs this two-step pipeline: __new__ builds the empty shell; __init__ fills it in.
हर Person(...) call यही दो क़दम चलाती है: __new__ ख़ाली ढाँचा बनाता है; __init__ उसे भरता है।
每次调用 Person(...) 都会走这两步:__new__ 造出空壳,__init__ 把它填好。
👣 Simulator: Object Birth, Step by Step👣 Simulator: Object का जन्म, क़दम-दर-क़दम👣 模拟器:对象的诞生 · 逐步演示
Recorded with sys.settrace. Watch the call stack: first __new__ (with cls, no self), then __init__ (with self). Then try the two broken versions — when __new__ does not return a Person, __init__ never runs.
sys.settrace से रिकॉर्ड किया हुआ। Call stack देखिए: पहले __new__ (cls के साथ, self नहीं), फिर __init__ (self के साथ)। फिर दोनों टूटे versions आज़माइए — जब __new__ Person नहीं लौटाता, तो __init__ कभी नहीं चलता।
用 sys.settrace 录制。观察调用栈:先是 __new__(有 cls,没有 self),然后是 __init__(有 self)。再试试两个有问题的版本 — 当 __new__ 没有返回 Person 时,__init__ 根本不会运行。
When Do You Actually Override __new__? 🤔__new__ को असल में कब override करें? 🤔什么时候才需要重写 __new__?🤔
Almost no Python class touches __new__ — the default handles it. You reach for it only when you need to control which object comes back, or when you subclass an immutable built-in type.
लगभग कोई Python class __new__ को नहीं छूती — default काम कर देता है। इसकी ज़रूरत तभी पड़ती है जब आपको तय करना हो कि कौन-सा object लौटे, या जब आप किसी immutable built-in type की subclass बनाएँ।
几乎没有 Python 类会去碰 __new__ — 默认实现就够了。只有当你需要控制返回 哪个 对象,或者要继承不可变的内置类型时,才会用到它。
__new__.__new__ का सबसे आम असली इस्तेमाल यही है।__new__ 在实际中最常见的用法。str, int or tuple, the value is already fixed by the time __init__ runs. To change the value itself, do it in __new__. (A full example comes in an upcoming tutorial.)str, int या tuple की subclass में, __init__ चलने तक value पहले ही तय हो चुकी होती है। Value ख़ुद बदलनी हो तो यह __new__ में करें। (पूरा उदाहरण आने वाले tutorial में।)str、int 或 tuple 时,__init__ 运行之前 值 就已经固定了。要改变值本身,就在 __new__ 中处理。(完整示例见后续教程。)__new__ is a static method (Python makes it one automatically) whose first argument is cls — the class, not self. It must return an object. If it returns something that is not an instance of cls, Python skips __init__. Try that in the simulator above.
__new__ एक static method है (Python इसे अपने आप ऐसा बनाता है) जिसका पहला argument cls है — class, self नहीं। इसे object लौटाना ही होगा। अगर यह ऐसा कुछ लौटाए जो cls का instance नहीं है, तो Python __init__ छोड़ देता है। ऊपर के simulator में यह आज़माइए।
__new__ 是一个静态方法(Python 会自动把它变成静态方法),第一个参数是 cls — 类,不是 self。它 必须返回一个对象。如果返回的不是 cls 的实例,Python 就会 跳过 __init__。在上面的模拟器里试试看。
__call__ — Making an Instance Callable 📞__call__ — Instance को Callable बनाना 📞__call__ — 让实例可以被调用 📞
Functions are callable — len(), print(), your own calculate(). Objects usually are not. Defining __call__ changes that: now you can call your object with (), just like a function.
Functions callable होते हैं — len(), print(), आपका अपना calculate()। Objects आमतौर पर नहीं होते। __call__ define करने से यह बदल जाता है: अब आप अपने object को () से बुला सकते हैं, ठीक function की तरह।
函数是可调用的 — len()、print()、你自己的 calculate()。对象通常 不是。定义 __call__ 就改变了这一点:现在你可以像调用函数一样用 () 调用你的对象。
class Multiplier:
def __init__(self, factor):
self.factor = factor
# -- This makes the instance callable --
def __call__(self, x):
return x * self.factor
double = Multiplier(2)
triple = Multiplier(3)
# Instances now behave like functions
print(double(10)) # 20 <- calls double.__call__(10)
print(triple(10)) # 30 <- calls triple.__call__(10)
# They can even be passed anywhere a function is expected
print(list(map(double, [1, 2, 3]))) # [2, 4, 6]
# They remain OBJECTS - you can inspect and change state
print(double.factor) # 2
double.factor = 5
print(double(10)) # 50 <- same instance, new behaviour
Calling an object with () is really Python calling its __call__ method. Same syntax as a function, but the object keeps its state.
() से object बुलाना असल में Python का उसका __call__ method बुलाना है। Function जैसा syntax, पर object अपनी state रखता है।
用 () 调用对象,其实就是 Python 调用它的 __call__ 方法。语法和函数一样,但对象保留着自己的状态。
🛠️ Simulator: Callable Workshop🛠️ Simulator: Callable Workshop🛠️ 模拟器:可调用对象工坊
Pick one of the three callable classes from this tutorial and press the buttons to run lines. Watch obj(…) turn into obj.__call__(…), and watch the object's own state change between calls. Checked against Python on 300 random sequences.
इस tutorial की तीन callable classes में से एक चुनिए और lines चलाने के लिए buttons दबाइए। देखिए obj(…) कैसे obj.__call__(…) बनता है, और calls के बीच object की अपनी state कैसे बदलती है। 300 random sequences पर Python से जाँचा गया।
从本教程的三个可调用类中选一个,按按钮运行代码。观察 obj(…) 如何变成 obj.__call__(…),以及对象自身的状态在多次调用之间如何变化。已在 300 个随机序列上与 Python 对照。
Why Callable Classes Instead of Just Functions? 🤷सिर्फ़ Functions की जगह Callable Classes क्यों? 🤷为什么用可调用类而不只用函数?🤷
| No memory between callsCalls के बीच कोई याद नहीं调用之间没有记忆 |
| Settings passed in every timeहर बार settings देनी पड़ती हैं每次都要传入配置 |
| Fine for work with no stateबिना state वाले काम के लिए ठीक适合无状态的操作 |
def multiply(x, factor):def multiply(x, factor):def multiply(x, factor): |
| Carries state across callsCalls के बीच state रखता है在调用之间保留状态 |
| Set up once, when it is createdबनते समय एक बार set up创建时配置一次 |
| Reads like a function, behaves like an objectFunction जैसा पढ़ा जाता है, object जैसा चलता है读起来像函数,用起来像对象 |
Multiplier(2) — then reuse it foreverMultiplier(2) — फिर हमेशा दोबारा इस्तेमालMultiplier(2) — 之后一直复用 |
Common patterns that benefit from __call__:
__call__ से फ़ायदा पाने वाले आम patterns:
受益于 __call__ 的常见模式:
| PatternPattern模式 | Ideaविचार思路 |
|---|---|
| Configured functionsConfigured functions预先配置的函数 | A validator with rules set when it is created (MinLengthValidator(8)), then called as validator("input") — see Section 10बनते समय नियम तय करने वाला validator (MinLengthValidator(8)), फिर validator("input") से बुलाया जाता है — Section 10 देखें创建时就设定规则的校验器(MinLengthValidator(8)),之后以 validator("input") 调用 — 见第 10 节 |
| Counters and accumulatorsCounters और accumulators计数器与累加器 | The object carries the running total between calls — see Section 09Object calls के बीच कुल योग रखता है — Section 09 देखें对象在调用之间保存累计值 — 见第 09 节 |
| Decorators as classesClasses के रूप में decorators类形式的装饰器 | @Retry(max_attempts=3) — the decorator's __call__ wraps the function (upcoming tutorial)@Retry(max_attempts=3) — decorator का __call__ function को लपेटता है (आने वाला tutorial)@Retry(max_attempts=3) — 装饰器的 __call__ 包装函数(后续教程) |
| Pipelines / transformsPipelines / transforms流水线 / 转换 | Pipeline(steps), then pipeline(data)Pipeline(steps), फिर pipeline(data)Pipeline(steps),然后 pipeline(data) |
| Fluent APIsFluent APIs流式 API | Chainable calls that also keep state you can inspectजुड़ने वाली calls जो जाँचने लायक state भी रखती हैं可链式调用,同时保留可检查的状态 |
The Singleton Pattern — One Instance, Reused Forever ☀️Singleton Pattern — एक Instance, हमेशा दोबारा ☀️单例模式 — 只有一个实例,永远复用 ☀️
A singleton is a class that only ever produces one object. However many times you call Config(), you get the same Config object. It suits app-wide things — settings, database connections, logging, caches.
Singleton ऐसी class है जो हमेशा एक ही object बनाती है। Config() कितनी भी बार बुलाइए, वही Config object मिलता है। यह पूरे app की चीज़ों के लिए ठीक है — settings, database connections, logging, caches।
单例 是只会产生 一个对象 的类。无论调用 Config() 多少次,得到的都是 同一个 Config 对象。它适合全应用共享的东西 — 配置、数据库连接、日志、缓存。
class Config:
_instance = None # class variable - the "one and only" slot
def __new__(cls, *args, **kwargs):
if cls._instance is None:
print(" [__new__] first call — creating THE instance")
cls._instance = super().__new__(cls)
else:
print(" [__new__] already exists — returning the same instance")
return cls._instance
def __init__(self, filename=None):
# NOTE: __init__ runs on EVERY Config(...) call - beware of overwriting
if filename is not None:
self.filename = filename
print("First call:")
a = Config("app.ini")
print("\nSecond call:")
b = Config()
print("\nThird call:")
c = Config("override.ini")
print()
print("a is b:", a is b) # True - literally the same object
print("b is c:", b is c) # True
print("a.filename:", a.filename) # override.ini (the last __init__ overwrote it)
__init__ runs on every Config(...) call — even when __new__ returned the existing object. So calling Config("override.ini") later overwrites the filename set the first time. Guard against this if you don't want it (Section 07 shows the "initialised flag" pattern).
__init__ हर Config(...) call पर चलता है — तब भी जब __new__ ने मौजूदा object लौटाया। इसलिए बाद में Config("override.ini") बुलाने पर पहली बार वाला filename बदल जाता है। अगर यह नहीं चाहिए तो इससे बचाव कीजिए (Section 07 में "initialised flag" pattern है)।
__init__ 在 每一次 Config(...) 调用时都会运行 — 即使 __new__ 返回的是已有对象。所以之后再调用 Config("override.ini") 会 覆盖 第一次设置的文件名。如果不希望这样,就要加以防护(第 07 节介绍"已初始化标志"模式)。
Three calls, one object. __new__ checks the slot and hands back the existing object; __init__ still runs each time.
तीन calls, एक object। __new__ slot जाँचकर मौजूदा object लौटाता है; __init__ फिर भी हर बार चलता है।
三次调用,一个对象。__new__ 检查槽位并返回已有对象;__init__ 仍然每次都运行。
A Safer Singleton — Guard __init__ Too 🛡️सुरक्षित Singleton — __init__ को भी बचाएँ 🛡️更安全的单例 — 也要保护 __init__ 🛡️
Because __init__ runs on every construction call, you often want a flag so the real setup runs only once. This "initialised once" pattern is used in most real singletons.
क्योंकि __init__ हर बार object बनाने की call पर चलता है, अक्सर एक flag चाहिए ताकि असली setup सिर्फ़ एक बार चले। ज़्यादातर असली singletons में यही "एक बार initialise" pattern होता है।
由于 __init__ 在每次构造调用时都会运行,通常需要一个标志,让真正的初始化只执行一次。大多数真实的单例都使用这种"只初始化一次"的模式。
class ConfigManager:
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, filename="app.ini"):
# Guard: don't re-run on later construction calls
if ConfigManager._initialized:
return
print(f"Loading {filename} — this runs ONCE")
self.filename = filename
self.settings = {"debug": True, "version": "2.4"}
ConfigManager._initialized = True
a = ConfigManager("app.ini") # prints "Loading app.ini..."
b = ConfigManager("different.ini") # silent - already initialised
print(a.filename) # app.ini (still the first value)
print(a is b) # True
☀️ Simulator: Singleton Lab☀️ Simulator: Singleton Lab☀️ 模拟器:单例实验室
Press the call buttons to create up to six names. Compare three versions of Config: a normal class, the plain singleton from Section 06, and the guarded one from this section. Watch where each name points and what filename ends up as. Checked against Python on 300 random sequences.
Call buttons दबाकर छह तक नाम बनाइए। Config के तीन versions की तुलना कीजिए: सामान्य class, Section 06 वाला सादा singleton, और इस section वाला guarded singleton। देखिए हर नाम कहाँ इशारा करता है और filename आख़िर में क्या बनता है। 300 random sequences पर Python से जाँचा गया।
按调用按钮,最多创建六个名字。比较 Config 的三个版本:普通类、第 06 节的简单单例,以及本节带防护的单例。观察每个名字指向哪里,以及 filename 最终是什么。已在 300 个随机序列上与 Python 对照。
Alternative Singleton Patterns 🔀Singleton के दूसरे Patterns 🔀其他单例写法 🔀
The __new__ approach is the most direct, but Python offers other ways to get the same effect. Each suits a different style.
__new__ वाला तरीक़ा सबसे सीधा है, पर Python यही असर पाने के दूसरे तरीक़े भी देता है। हर एक अलग style के लिए ठीक है।
__new__ 的方式最直接,但 Python 还提供了其他方式来达到同样的效果,各自适合不同的风格。
Pattern 1 — DecoratorPattern 1 — Decorator写法 1 — 装饰器
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self, host):
self.host = host
db1 = Database("localhost")
db2 = Database("other-host")
print(db1 is db2) # True
print(db1.host) # localhost (the second call was ignored)
print(Database) # the name now points to the wrapper function, not the class
After @singleton, the name Database points to the inner get_instance function, not to the class. That is why isinstance(db1, Database) fails with TypeError (see the Bug Doctor in Section 11). The __new__ version keeps Database a real class.
@singleton के बाद नाम Database अंदर वाले get_instance function की ओर इशारा करता है, class की ओर नहीं। इसीलिए isinstance(db1, Database) TypeError देता है (Section 11 का Bug Doctor देखें)। __new__ वाला version Database को असली class बनाए रखता है।
加上 @singleton 之后,名字 Database 指向内部的 get_instance 函数,而不是类。这就是为什么 isinstance(db1, Database) 会抛出 TypeError(见第 11 节的 Bug 医生)。__new__ 版本则让 Database 保持为真正的类。
Pattern 2 — Module-Level (the Pythonic Default)Pattern 2 — Module-Level (Pythonic default)写法 2 — 模块级(Python 风格的默认做法)
# In config.py - the module itself IS the singleton
settings = {"debug": True, "version": "2.4"}
def get(key):
return settings.get(key)
# Anywhere else:
# from config import settings, get
# Every import gets the same module -> the same settings dict - a natural singleton
In many real Python projects, the "singleton" is just a module. Python runs a module once and caches it, so import config in ten different files gives every file the same config object. No __new__, no decorator — just a plain module. Use a __new__-based singleton only when you really need class features (subclassing, methods with behaviour).
कई असली Python projects में "singleton" बस एक module होता है। Python module को एक बार चलाकर cache कर लेता है, इसलिए दस अलग files में import config करने पर हर file को वही config object मिलता है। न __new__, न decorator — बस एक सादा module। __new__ वाला singleton तभी लें जब सच में class की सुविधाएँ चाहिए (subclassing, व्यवहार वाले methods)।
在很多真实的 Python 项目中,"单例"就是一个 模块。Python 只运行一次模块并缓存它,所以在十个不同文件中 import config,每个文件得到的都是同一个 config 对象。不需要 __new__,不需要装饰器 — 只是一个普通模块。只有在确实需要类的特性(子类化、带行为的方法)时,才使用基于 __new__ 的单例。
Practical Example — A Callable Counter With State 🔢Practical Example — State वाला Callable Counter 🔢实战示例 — 带状态的可调用计数器 🔢
A class that acts like a function but remembers how many times it has been called. A classic __call__ use. Try it in the Callable Workshop (Section 04) with Counter().
ऐसी class जो function की तरह चलती है पर याद रखती है कि उसे कितनी बार बुलाया गया। __call__ का क्लासिक इस्तेमाल। Callable Workshop (Section 04) में Counter() से आज़माइए।
一个像函数一样工作、却能记住自己被调用了多少次的类。这是 __call__ 的经典用法。到可调用对象工坊(第 04 节)选 Counter() 试试。
class Counter:
def __init__(self, start=0):
self.count = start
def __call__(self):
self.count += 1
return self.count
def reset(self):
self.count = 0
def __repr__(self):
return f"Counter(count={self.count})"
c = Counter()
print(c()) # 1 <- called like a function
print(c()) # 2
print(c()) # 3
# Still an object - you can inspect and reset
print(c) # Counter(count=3)
c.reset()
print(c()) # 1 (started over)
# Several independent counters - each carries its own state
hits = Counter()
misses = Counter()
hits(); hits(); hits()
misses()
print(f"hits={hits.count}, misses={misses.count}") # hits=3, misses=1
Practical Example — A Callable Validator ✅Practical Example — Callable Validator ✅实战示例 — 可调用的校验器 ✅
Combine __call__ with settings stored in __init__ to build small, reusable validation objects. Set up once, call anywhere.
__call__ को __init__ में रखी settings के साथ मिलाकर छोटे, दोबारा इस्तेमाल होने वाले validation objects बनाइए। एक बार set up, कहीं भी call।
把 __call__ 和 __init__ 中保存的配置结合起来,构建小巧、可复用的校验对象。配置一次,随处调用。
class MinLengthValidator:
def __init__(self, min_length):
self.min_length = min_length
def __call__(self, value):
# Uses the setting from __init__ every time it is called
if len(value) < self.min_length:
raise ValueError(
f"{value!r} must be at least {self.min_length} chars"
)
return value
# Build once, use everywhere
username_valid = MinLengthValidator(3)
password_valid = MinLengthValidator(8)
# Call the instances like functions
print(username_valid("alice")) # alice
print(password_valid("SecureP@ss")) # SecureP@ss
try:
password_valid("abc")
except ValueError as e:
print("Blocked:", e)
# A callable object can be passed to higher-order functions like map()
inputs = ["alice", "bob", "chandra"]
valid_names = list(map(username_valid, inputs))
print(valid_names)
The original comment said "callables can be passed to higher-order functions", but the code then checked len(n) >= username_valid.min_length by hand and never passed the object anywhere. Now it does: map(username_valid, inputs) calls the object once per name. The comments on the first two prints are also fixed — print() shows alice, not 'alice'.
मूल comment में लिखा था "callables को higher-order functions में दे सकते हैं", पर code ने फिर len(n) >= username_valid.min_length हाथ से जाँचा और object कहीं दिया ही नहीं। अब देता है: map(username_valid, inputs) हर नाम के लिए object को एक बार बुलाता है। पहले दो prints के comments भी ठीक किए — print() alice दिखाता है, 'alice' नहीं।
原注释说"可调用对象可以传给高阶函数",但代码随后却手动检查 len(n) >= username_valid.min_length,根本没有把对象传给任何函数。现在改为:map(username_valid, inputs) 对每个名字调用一次该对象。前两个 print 的注释也已修正 — print() 显示 alice,而不是 'alice'。
Common Mistakes (and Fixes) 🩹आम ग़लतियाँ (और उनके हल) 🩹常见错误(及修正)🩹
| Mistakeग़लती错误 | What goes wrongक्या बिगड़ता है会出什么问题 | Fixहल修正 |
|---|---|---|
Forgetting to return from __new____new__ से return भूलना忘记在 __new__ 中 return | Person(...) gives None, and __init__ never runsPerson(...) None देता है, और __init__ कभी नहीं चलताPerson(...) 得到 None,而且 __init__ 从不运行 | Always end __new__ with return instance (or return cls._instance)__new__ को हमेशा return instance (या return cls._instance) से ख़त्म करें__new__ 末尾始终写 return instance(或 return cls._instance) |
Naming the first parameter of __new__ self__new__ के पहले parameter का नाम self रखना把 __new__ 的第一个参数命名为 self | It still runs (a name is just a name), but it misleads readers — that argument is the class, because no object exists yetयह फिर भी चलता है (नाम बस नाम है), पर पढ़ने वालों को भटकाता है — वह argument class है, क्योंकि अभी object है ही नहीं代码照样能运行(名字只是名字),但会误导读者 — 那个参数是 类,因为对象还不存在 | Write def __new__(cls, ...):def __new__(cls, ...): लिखें写成 def __new__(cls, ...): |
Setting attributes in __new__ that __init__ overwrites__new__ में ऐसे attributes रखना जिन्हें __init__ बदल देता है在 __new__ 中设置会被 __init__ 覆盖的属性 | Whatever __new__ sets is replaced by __init__ right after__new__ जो रखता है, __init__ तुरंत बाद बदल देता है__new__ 设置的值紧接着就被 __init__ 替换 | Set state in __init__. Use __new__ only for creation and identityState __init__ में रखें। __new__ सिर्फ़ बनाने और पहचान के लिए状态放在 __init__ 中。__new__ 只负责创建和身份 |
| Singleton with changing state, no re-init guardबदलने वाली state वाला singleton, re-init guard नहीं有可变状态的单例,却没有重复初始化防护 | A later call's __init__ quietly overwrites the first call's settingsबाद की call का __init__ पहली call की settings चुपचाप बदल देता है之后调用的 __init__ 会悄悄覆盖第一次的配置 | Add an _initialized flag and return early from __init__ when it is set_initialized flag जोड़ें और set होने पर __init__ से जल्दी return करें加一个 _initialized 标志,已设置时就从 __init__ 提前返回 |
| Singleton in multi-threaded code without a lockLock के बिना multi-threaded code में singleton多线程代码中的单例没有加锁 | Two threads may both see _instance is None and create two objectsदो threads दोनों _instance is None देखकर दो objects बना सकते हैं两个线程可能同时看到 _instance is None,于是创建了两个对象 | Guard the check with a threading.Lock(), or use a module-level singleton (imports are thread-safe) — threads are an upcoming tutorialजाँच को threading.Lock() से बचाएँ, या module-level singleton लें (imports thread-safe हैं) — threads आने वाले tutorial में用 threading.Lock() 保护检查,或使用模块级单例(导入是线程安全的)— 线程将在后续教程讲解 |
Making __call__ change self when callers expect no side effectsजब callers side effects की उम्मीद न करें, तब __call__ में self बदलना调用方预期没有副作用时,__call__ 却修改了 self | Callers think obj(x) works like fn(x) — hidden changes surprise themCallers सोचते हैं obj(x) fn(x) जैसा है — छिपे बदलाव चौंकाते हैं调用方以为 obj(x) 和 fn(x) 一样 — 隐藏的变化让人意外 | Document the side effect clearly, or use a separate method for changesSide effect साफ़ लिखें, या बदलाव के लिए अलग method रखें清楚地写明副作用,或用单独的方法做修改 |
| Using a singleton for state that tests must controlजिस state को tests को control करना हो, उसके लिए singleton对测试需要控制的状态使用单例 | Tests can't easily reset or replace it — flaky testsTests इसे आसानी से reset या बदल नहीं पाते — अस्थिर tests测试很难重置或替换它 — 测试结果不稳定 | Pass the object in where it is needed (dependency injection), or reset it in test setupजहाँ ज़रूरत हो वहाँ object पास करें (dependency injection), या test setup में reset करें在需要的地方传入对象(依赖注入),或在测试准备阶段重置它 |
🩺 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.
इनमें से पाँच ग़लतियाँ, असली run में। बाईं ओर buggy code, दाईं ओर ठीक किया हुआ, बदली lines चिह्नित।
其中五个错误的真实运行。左边是有 bug 的代码,右边是修正后的代码,改动的行已标出。
Quick Reference 📋Quick Reference 📋速查表 📋
| Taskकाम任务 | SyntaxSyntax语法 | Notesनोट说明 |
|---|---|---|
| Control object creationObject बनना control करना控制对象创建 | def __new__(cls, *a, **kw): | First argument is cls; must return an objectपहला argument cls; object return करना ज़रूरी第一个参数是 cls;必须 return 一个对象 |
| Use the default creationDefault creation इस्तेमाल करना使用默认创建 | super().__new__(cls) | The standard way to make the bare objectख़ाली object बनाने का मानक तरीक़ा创建空对象的标准方式 |
| Fill in attributesAttributes भरना填充属性 | def __init__(self, ...): | Runs AFTER __new__ — only if it returned an instance of the class__new__ के बाद चलता है — तभी जब उसने class का instance लौटाया在 __new__ 之后运行 — 前提是它返回了该类的实例 |
| Make an instance callableInstance को callable बनाना让实例可调用 | def __call__(self, ...): | Then use obj(args) like a functionफिर obj(args) function की तरह然后像函数一样使用 obj(args) |
| Basic singletonBasic singleton基本单例 | Store _instance as a class variable, check it in __new___instance class variable में रखें, __new__ में जाँचें把 _instance 存为类变量,在 __new__ 中检查 | The simplest and most common patternसबसे आसान और आम pattern最简单、最常见的模式 |
| Safe singletonSafe singleton安全单例 | Add an _initialized flag, guard __init___initialized flag जोड़ें, __init__ को बचाएँ添加 _initialized 标志,保护 __init__ | Stops re-initialising on later callsबाद की calls पर दोबारा initialise होना रोकता है防止后续调用重新初始化 |
| Singleton via decoratorDecorator से singleton用装饰器实现单例 | Wrap the class in a factory functionClass को factory function में लपेटें用工厂函数包装类 | Short, but the name becomes a function — isinstance breaksछोटा, पर नाम function बन जाता है — isinstance टूटता है简洁,但名字变成了函数 — isinstance 失效 |
| Pythonic singletonPythonic singletonPython 风格的单例 | Just use a moduleबस एक module直接用模块 | Modules are cached — natural singletonsModules cache होते हैं — स्वाभाविक singletons模块会被缓存 — 天然的单例 |
| Check if callableCallable है या नहीं检查是否可调用 | callable(obj) | True for functions, classes, and objects whose class defines __call__Functions, classes, और उन objects के लिए True जिनकी class __call__ define करती है对函数、类,以及其类定义了 __call__ 的对象返回 True |
| Check identityपहचान जाँचना检查身份 | a is b | True if both names point to the same objectTrue अगर दोनों नाम एक ही object की ओर हों两个名字指向同一对象时为 True |
Golden Rules and Quiz 🏆सुनहरे नियम और Quiz 🏆黄金法则与小测验 🏆
ClassName(...) call runs two methods: __new__ creates the object, __init__ fills it in. Singletons and immutable subclasses both depend on this order.ClassName(...) call दो methods चलाती है: __new__ object बनाता है, __init__ उसे भरता है। Singletons और immutable subclasses दोनों इसी क्रम पर टिके हैं।ClassName(...) 调用都会运行 两个方法:__new__ 创建对象,__init__ 填充对象。单例和不可变子类都依赖这个顺序。__new__ without a reason. The default is right almost every time. Reach for it only for singletons, immutable subclasses of built-ins, or object pools.__new__ override न करें। Default लगभग हमेशा सही है। इसे सिर्फ़ singletons, built-ins की immutable subclasses, या object pools के लिए लें।__new__。默认实现几乎总是对的。只在单例、内置类型的不可变子类或对象池时才使用它。__new__ takes cls, not self — the object doesn't exist yet. It must return the object. Forgetting the return gives the classic 'NoneType' object has no attribute … bug.__new__ cls लेता है, self नहीं — object अभी है ही नहीं। इसे object लौटाना ही होगा। Return भूलने से क्लासिक 'NoneType' object has no attribute … bug आता है।__new__ 接收 cls 而不是 self — 对象还不存在。它必须 返回 这个对象。忘记 return 就会出现经典的 'NoneType' object has no attribute … 错误。__init__ runs every time you call ClassName(...) — even when __new__ returned an existing object. For singletons, guard __init__ with an _initialized flag so settings are not overwritten.ClassName(...) बुलाने पर __init__ हर बार चलता है — तब भी जब __new__ ने मौजूदा object लौटाया। Singletons में __init__ को _initialized flag से बचाएँ ताकि settings न बदलें।ClassName(...),__init__ 都会 运行 — 即使 __new__ 返回的是已有对象。对单例来说,用 _initialized 标志保护 __init__,避免配置被覆盖。__call__ makes an object callable with obj(x). Use it for configured functions (MinLengthValidator(8)) and objects that keep a running state (counters). If the object never carries state, a plain function is clearer.__call__ object को obj(x) से callable बनाता है। इसे configured functions (MinLengthValidator(8)) और चलती state रखने वाले objects (counters) के लिए लें। अगर object कभी state नहीं रखता, तो सादा function ज़्यादा साफ़ है।__call__ 让对象可以用 obj(x) 调用。把它用于预先配置的函数(MinLengthValidator(8))和保存累计状态的对象(计数器)。如果对象从不携带状态,普通函数更清晰。_instance), check it in __new__, and hand back the same object every time. Test with a is b — identity, not equality._instance) में रखें, __new__ में जाँचें, और हर बार वही object लौटाएँ। a is b से जाँचें — पहचान, बराबरी नहीं।_instance),在 __new__ 中检查,每次返回同一个对象。用 a is b 测试 — 比较身份,而不是相等。from config import settings gives you a natural singleton with no extra code.from config import settings बिना अतिरिक्त code के स्वाभाविक singleton देता है।from config import settings 不用额外代码就得到天然的单例。_instance is None at the same moment will both create an object. Wrap the check in a threading.Lock(), or use module-level state._instance is None देखें तो दोनों object बना देंगे। जाँच को threading.Lock() में लपेटें, या module-level state लें।_instance is None,就会各自创建一个对象。用 threading.Lock() 包住检查,或使用模块级状态。__new__. Should the object be callable like a function? → __call__. Do I need exactly one object across the app? → a singleton (or a module).__new__। क्या object को function की तरह बुलाना है? → __call__। क्या पूरे app में ठीक एक object चाहिए? → singleton (या module)।__new__。对象需要像函数一样被调用吗?→ __call__。整个应用只需要一个对象吗?→ 单例(或模块)。Quick Quiz — 8 Questionsछोटा Quiz — 8 सवाल小测验 — 8 道题
ClassName(...) runs __new__(cls) to create the object, then __init__(self) to fill it in — but only if __new__ returned an instance of the class. A singleton keeps one object in _instance and returns it from __new__; guard __init__ with a flag, or simply use a module. __call__ lets obj(x) work like a function while the object keeps its state.
ClassName(...) पहले __new__(cls) से object बनाता है, फिर __init__(self) से उसे भरता है — पर तभी जब __new__ ने class का instance लौटाया। Singleton एक object _instance में रखता है और __new__ से वही लौटाता है; __init__ को flag से बचाएँ, या बस module लें। __call__ से obj(x) function की तरह चलता है जबकि object अपनी state रखता है।
ClassName(...) 先运行 __new__(cls) 创建对象,再运行 __init__(self) 填充它 — 前提是 __new__ 返回了该类的实例。单例把唯一的对象存在 _instance 中,并在 __new__ 中返回它;用标志保护 __init__,或者干脆用模块。__call__ 让 obj(x) 像函数一样工作,同时对象保留自己的状态。