The Story That Explains Python Variables 🏷️Python Variables समझाने वाली कहानी 🏷️一个解释 Python 变量的故事 🏷️
int a = 10; reserves a fixed-size box called a and puts 10 inside. a = 20; puts 20 into the same box.Python works differently. Values are objects that live in memory on their own. A variable is a sticky note with a name on it, stuck onto an object.
a = 10 creates (or finds) the object 10 and sticks the note a on it. a = 20 does not change the 10 — it moves the note to a different object.This one idea explains most of the "strange" things in Python: why
a++ does not exist, why id(a) changes when you "change" a number, why two names can see the same list change, and why is sometimes surprises you.int a = 10; a नाम का एक तय आकार का box रखता है और उसमें 10 डालता है। a = 20; उसी box में 20 डालता है।Python अलग तरह से काम करता है। मान objects हैं जो memory में अपने आप रहते हैं। Variable एक नाम लिखा sticky note है, जो किसी object पर चिपका है।
a = 10 object 10 बनाता (या ढूँढता) है और उस पर note a चिपकाता है। a = 20 10 को नहीं बदलता — note को दूसरे object पर ले जाता है।यह एक विचार Python की ज़्यादातर "अजीब" बातें समझाता है:
a++ क्यों नहीं है, संख्या "बदलने" पर id(a) क्यों बदलता है, दो नाम एक ही list का बदलाव क्यों देखते हैं, और is कभी-कभी क्यों चौंकाता है।int a = 10; 预留一个名为 a 的固定大小的盒子,把 10 放进去;a = 20; 把 20 放进同一个盒子。Python 不一样。值是独立存在于内存中的对象,变量是一张写着名字的便利贴,贴在某个对象上。
a = 10 创建(或找到)对象 10,把便利贴 a 贴上去;a = 20 并不修改 10 —— 而是把便利贴移到另一个对象上。这一个概念解释了 Python 中大多数“奇怪”现象:为什么没有
a++,为什么“修改”数字后 id(a) 会变,为什么两个名字能看到同一个列表的变化,以及为什么 is 有时会让人意外。"A Python variable is a name that refers to an object. It is not the object itself." Everything below follows from this sentence.
"Python variable एक नाम है जो किसी object की ओर इशारा करता है। वह ख़ुद object नहीं है।" नीचे की हर बात इसी वाक्य से निकलती है।
“Python 变量是一个指向对象的名字,它本身不是对象。”下面的所有内容都由这句话推导而来。
How Python Stores a Variable 🧠Python Variable कैसे Store करता है 🧠Python 如何存储变量 🧠
When you write a = 10, three things happen:
जब आप a = 10 लिखते हैं, तो तीन चीज़ें होती हैं:
当你写下 a = 10 时,会发生三件事:
a in the current namespace — a table of names, like a dictionary.a खोजता है — नामों की एक table, dictionary जैसी।a —— 命名空间就是一张名字表,类似字典。a refers to 10. Nothing is copied.a 10 की ओर है। कुछ copy नहीं होता।a 指向 10。没有任何复制。a = 10
print(a) # the value the name refers to
print(type(a)) # what kind of object it is
print(id(a)) # the object's identity (in CPython: its memory address)
print(hex(id(a))) # the same number in hexadecimal
id() returns a number that is unique for each object while it is alive. In CPython (the normal Python from python.org) it is the object's memory address. The exact number changes from run to run, so yours will differ. Small ints such as 10 sit in a fixed area set up when Python starts, which is why their ids look shorter.
id() एक संख्या लौटाता है जो हर जीवित object के लिए अनोखी होती है। CPython (python.org वाला सामान्य Python) में यह object का memory address है। सटीक संख्या हर run में बदलती है, इसलिए आपकी अलग होगी। 10 जैसे छोटे ints Python शुरू होने पर बने एक तय हिस्से में रहते हैं, इसीलिए उनके ids छोटे दिखते हैं।
id() 返回一个数字,在对象存活期间对每个对象唯一。在 CPython(python.org 提供的标准 Python)中,它就是对象的内存地址。具体数字每次运行都不同,你的结果会不一样。10 这样的小整数位于 Python 启动时准备好的固定区域,所以它们的 id 看起来更短。
Pick a tiny program and run it line by line. Orange tags are names; boxes are objects with their real ids (last 6 digits) from running this code on Python 3.13.16.
एक छोटा program चुनें और line-दर-line चलाएँ। नारंगी tags नाम हैं; boxes objects हैं, Python 3.13.16 पर यह code चलाकर मिले असली ids (आख़िरी 6 अंक) के साथ।
选择一个小程序并逐行运行。橙色标签是名字;方框是对象,附带在 Python 3.13.16 上运行这段代码得到的真实 id(最后 6 位)。
What Happens When You Write a = 20? 🔄a = 20 लिखने पर क्या होता है? 🔄写下 a = 20 时发生了什么?🔄
The old number is not overwritten. Integers are immutable — they can never change. So Python makes (or finds) a new object and moves the name to it. You can prove it with id(). Lists are different: they are mutable, so append changes the same object and the id stays the same.
पुरानी संख्या overwrite नहीं होती। Integers immutable हैं — वे कभी नहीं बदलते। इसलिए Python एक नया object बनाता (या ढूँढता) है और नाम उस पर ले जाता है। id() से यह साबित कर सकते हैं। Lists अलग हैं: वे mutable हैं, इसलिए append उसी object को बदलता है और id वही रहता है।
旧数字不会被覆盖。整数是不可变的 —— 永远不能修改。所以 Python 创建(或找到)一个新对象,再把名字移过去。用 id() 可以证明。列表不同:它们是可变的,append 修改的是同一个对象,id 保持不变。
a = 1000
first = id(a)
a = 2000 # reassignment: a NEW object
print(a, id(a) == first)
x = 1000
before = id(x)
x = x + 1 # builds a new int 1001, then rebinds x
print(x, id(x) == before)
x += 1 # same thing: ints cannot change in place
print(x, id(x) == before)
nums = [1, 2]
before = id(nums)
nums.append(3) # mutation: the SAME list object changes
nums += [4] # for lists, += also changes it in place
print(nums, id(nums) == before)
nums = nums + [5] # + builds a NEW list, then rebinds
print(nums, id(nums) == before)
Rebinding moves a name to another object (a = 20, x = x + 1). It works for every type, and the id changes.
Mutation changes the object itself (nums.append(3)). Only mutable types such as list, dict and set allow it, and the id stays the same. Ints, floats, strings and tuples are immutable.
Rebinding नाम को दूसरे object पर ले जाता है (a = 20, x = x + 1)। यह हर type पर चलता है, और id बदलता है।
Mutation object को ही बदलता है (nums.append(3))। सिर्फ़ list, dict और set जैसे mutable types इसकी अनुमति देते हैं, और id वही रहता है। Ints, floats, strings और tuples immutable हैं।
重新绑定是把名字移到另一个对象(a = 20、x = x + 1)。所有类型都可以,id 会改变。
变异是修改对象本身(nums.append(3))。只有 list、dict、set 等可变类型允许,id 保持不变。int、float、str 和 tuple 都是不可变的。
When Is the Old Object Freed?पुराना Object कब मुक्त होता है?旧对象什么时候被释放?
CPython counts how many references point to each object. When the count drops to zero, the object is freed immediately — not "eventually". The separate garbage collector is only needed for objects that refer to each other in a cycle. This class prints a message when it is freed, so you can watch it happen:
CPython गिनता है कि हर object की ओर कितने references हैं। जब गिनती शून्य होती है, object तुरंत मुक्त होता है — "कभी बाद में" नहीं। अलग garbage collector की ज़रूरत सिर्फ़ उन objects के लिए है जो एक-दूसरे की ओर cycle में इशारा करते हैं। यह class मुक्त होने पर message छापती है, ताकि आप इसे होते देख सकें:
CPython 统计每个对象被多少个引用指向。计数降到零时,对象会立即被释放 —— 而不是“迟早”。独立的垃圾回收器只用于互相引用形成循环的对象。下面这个类在被释放时会打印消息,你可以亲眼看到这一过程:
class Tracker:
"""A tiny object that announces when Python frees it."""
def __init__(self, label):
self.label = label
print(f" created {label}")
def __del__(self):
print(f" freed {self.label}")
print("t = Tracker('first')")
t = Tracker("first")
print("t = Tracker('second') # rebind t")
t = Tracker("second") # 'first' has no names left → freed at once
print("u = t # a second name")
u = t
print("del t")
del t # 'second' still has the name u
print("del u")
del u # last name gone → freed now
print("end of program")
Small ints from −5 to 256 are an exception: they are created once at start-up and are never freed.
−5 से 256 तक के छोटे ints अपवाद हैं: वे start पर एक बार बनते हैं और कभी मुक्त नहीं होते।
−5 到 256 的小整数是例外:它们在启动时创建一次,永远不会被释放。
Why a++ and a-- Do Not Exist in Python 🚫Python में a++ और a-- क्यों नहीं हैं 🚫为什么 Python 没有 a++ 和 a-- 🚫
In C, Java and JavaScript, a++ means "add 1 to a". Python does not have it:
C, Java और JavaScript में a++ का मतलब है "a में 1 जोड़ो"। Python में यह नहीं है:
在 C、Java 和 JavaScript 中,a++ 表示“a 加 1”。Python 没有这个运算符:
a = 5
a++
Worse, ++a and --a are valid — they are just two unary pluses or minuses — so they run without error and change nothing:
इससे बुरा, ++a और --a मान्य हैं — ये बस दो unary plus या minus हैं — इसलिए बिना error चलते हैं और कुछ नहीं बदलते:
更糟的是,++a 和 --a 是合法的 —— 只是两个一元正号或负号 —— 所以运行不会报错,却什么也没改变:
a = 5
print(++a, --a, a) # +(+a) and -(-a): no change at all
a += 1
print(a)
counter = 0
for _ in range(5):
++counter # looks like C, silently does nothing
print("with ++counter:", counter)
counter = 0
for _ in range(5):
counter += 1
print("with counter += 1:", counter)
Why? Three Reasons From Python’s Designक्यों? Python के Design से तीन कारण为什么?来自 Python 设计的三个原因
a++ changes the value stored in a box. In Python there is no box, and an int object can never change. The only option is to rebind the name to a new int — and a += 1 already says that clearly.a++ box में रखा मान बदलता है। Python में कोई box नहीं, और int object कभी नहीं बदल सकता। एक ही रास्ता है नाम को नए int से बाँधना — और a += 1 यह साफ़ कहता है।a++ 修改盒子里的值。Python 没有盒子,int 对象也永远不能修改,唯一的办法是把名字重新绑定到新的 int —— a += 1 已经清楚地表达了这一点。a++ and ++a return different values, and code like a = a++ + ++a has no defined meaning. In Python, assignment is a statement, so a += 1 cannot hide inside a bigger expression.a++ और ++a अलग मान लौटाते हैं, और a = a++ + ++a जैसे code का कोई तय अर्थ नहीं। Python में assignment एक statement है, इसलिए a += 1 किसी बड़े expression में छिप नहीं सकता।a++ 和 ++a 返回不同的值,a = a++ + ++a 这样的代码甚至没有确定的含义。在 Python 中赋值是语句,a += 1 无法藏在更大的表达式里。a += 1 already exists, so a second spelling would add nothing but confusion.a += 1 पहले से है, इसलिए दूसरी spelling सिर्फ़ उलझन बढ़ाती।a += 1,再加一种写法只会增加困惑。Pick the loop body and watch the counter after each of the 5 loops. Values come from really running each version.
Loop body चुनें और 5 loops में हर एक के बाद counter देखें। मान हर version को सच में चलाकर मिले हैं।
选择循环体,观察 5 次循环中每次之后的 counter。数值来自实际运行每个版本。
If you come from C or Java and type ++counter out of habit, Python gives no error — and your counter never grows. Always write counter += 1.
अगर आप C या Java से आए हैं और आदतन ++counter लिखते हैं, तो Python कोई error नहीं देता — और आपका counter कभी नहीं बढ़ता। हमेशा counter += 1 लिखें।
如果你从 C 或 Java 转来,习惯性地写 ++counter,Python 不会报错 —— 但计数器永远不会增加。请始终写 counter += 1。
The −5 to 256 Rule — Small Integer Caching 🧊−5 से 256 का नियम — Small Integer Caching 🧊−5 到 256 规则 —— 小整数缓存 🧊
Try this in the interactive REPL, one line at a time:
इसे interactive REPL में एक-एक line करके आज़माएँ:
在交互式 REPL 中逐行试试:
Same code, opposite answers for 100 and 1000. The reason: when CPython starts, it creates every int from −5 to 256 once and reuses those objects everywhere. Ask for 100 and you always get the shared object. Ask for 1000 and you usually get a new one. To test the edges fairly, build the numbers at run time with int(str(n)):
वही code, 100 और 1000 के लिए उल्टे जवाब। कारण: CPython शुरू होते समय −5 से 256 तक का हर int एक बार बनाता है और उन्हें हर जगह दोबारा इस्तेमाल करता है। 100 माँगें तो हमेशा साझा object मिलता है। 1000 माँगें तो अक्सर नया मिलता है। किनारों को ठीक से जाँचने के लिए संख्याएँ run time पर int(str(n)) से बनाएँ:
同样的代码,100 和 1000 的结果却相反。原因是:CPython 启动时会把 −5 到 256 的每个整数创建一次,并在各处复用这些对象。请求 100 总会拿到共享对象;请求 1000 通常会得到新对象。为了公平地测试边界,用 int(str(n)) 在运行时生成数字:
# int(str(n)) builds each number at run time, like real data does
for n in [-6, -5, 0, 100, 256, 257, 1000]:
a = int(str(n))
b = int(str(n))
print(f"{n:>5}: a == b → {a == b}, a is b → {a is b}")
But beware of the classic demo print(257 is 257) or x = 1000; y = 1000 in a script. Inside one file the compiler stores each constant once, so both names get the same object and the answer is True:
पर script में print(257 is 257) या x = 1000; y = 1000 वाले पुराने demo से सावधान रहें। एक file के अंदर compiler हर constant एक बार रखता है, इसलिए दोनों नामों को वही object मिलता है और जवाब True आता है:
但要小心经典演示 —— 在脚本里写 print(257 is 257) 或 x = 1000; y = 1000。同一个文件中,编译器对每个常量只存一份,所以两个名字拿到的是同一个对象,结果为 True:
x = 1000
y = 1000
print(x is y) # True here! Both lines are in ONE file, so the compiler
# stores the constant 1000 once and reuses it.
print(x == y)
Slide n and see whether two run-time ints with that value are the same object. All 322 results come from CPython 3.13.16.
n खिसकाएँ और देखें कि उस मान वाले दो run-time ints एक ही object हैं या नहीं। सारे 322 नतीजे CPython 3.13.16 से हैं।
拖动 n,查看两个运行时生成的同值整数是否为同一对象。全部 322 个结果来自 CPython 3.13.16。
Why Cache −5 to 256?−5 से 256 तक cache क्यों?为什么缓存 −5 到 256?
is True for any two equal ints). And as shown above, even CPython gives different answers in a script and in the REPL.is True देता है)। और ऊपर दिखा कि CPython भी script और REPL में अलग जवाब देता है।is 都为 True)。如上所示,即使 CPython,在脚本和 REPL 中给出的结果也不同。Compare values with ==. Use is for None (PEP 8 says so) or when you truly need "the same object". Python 3.8+ even prints a SyntaxWarning when you write x is 1000. The cache is fun to know about — correct code never depends on it.
मानों की तुलना == से करें। is को None के लिए (PEP 8 यही कहता है) या तब इस्तेमाल करें जब सच में "वही object" जानना हो। Python 3.8+ तो x is 1000 लिखने पर SyntaxWarning भी छापता है। Cache जानना मज़ेदार है — सही code कभी उस पर निर्भर नहीं होता।
比较值请用 ==。is 只用于 None(PEP 8 的要求),或确实需要判断“同一个对象”时。从 Python 3.8 起,写 x is 1000 甚至会打印 SyntaxWarning。了解缓存很有趣 —— 但正确的代码从不依赖它。
Type Conversion — int(), float(), str() 🔁Type Conversion — int(), float(), str() 🔁类型转换 —— int()、float()、str() 🔁
An object's type can never change. To "convert", you call a function that builds a new object of the type you want. The original stays as it was.
किसी object का type कभी नहीं बदलता। "बदलने" के लिए आप एक function बुलाते हैं जो चाहे गए type का नया object बनाता है। मूल वैसा ही रहता है।
对象的类型永远不会改变。所谓“转换”,是调用一个函数,构建所需类型的新对象。原对象保持不变。
int(x)_ allowed), or bools. Cuts toward zero — it does not round. Takes a base: int("FF", 16)._ चलते हैं), या bools से। शून्य की ओर काटता है — round नहीं करता। Base भी लेता है: int("FF", 16)।_)或布尔值转换。向零截断,不是四舍五入。可指定进制:int("FF", 16)。float(x)"1e-3"), bools, and the special words "inf" and "nan". A comma is not a decimal point."1e-3"), bools, और ख़ास शब्द "inf" व "nan" से। Comma दशमलव बिंदु नहीं है।"1e-3")、布尔值,以及特殊词 "inf" 和 "nan" 转换。逗号不能作小数点。str(x)int() — building a new integerint() — नया integer बनानाint() —— 构建新整数
print(int("42"), int("-17"), int(" 100 "), int("1_000"))
print(int(3.9), int(-3.9), round(3.9)) # int() cuts toward zero
print(int(True), int(False))
print(int("101", 2), int("FF", 16), int("777", 8), int("0x1F", 0))
print(int("४२"), int("١٢٣")) # Devanagari and Arabic-Indic digits work too
for bad in ["3.14", "hello", ""]:
try:
int(bad)
except ValueError as err:
print("ValueError:", err)
print(int(float("3.14")))
Notice int("४२") gives 42: int() accepts digits from any script that Unicode marks as decimal digits, including Devanagari and Arabic-Indic.
ध्यान दें int("४२") 42 देता है: int() किसी भी लिपि के वे अंक मानता है जिन्हें Unicode decimal digits मानता है, Devanagari और Arabic-Indic समेत।
注意 int("४२") 得到 42:int() 接受 Unicode 标记为十进制数字的任何文字的数字,包括天城文和阿拉伯-印度数字。
float() — building a new floatfloat() — नया float बनानाfloat() —— 构建新浮点数
print(float("3.14"), float("-0.5"), float("1e-3"), float("6.022e23"))
print(float(7), float(-42), float(True), float(False))
print(float("inf"), float("-inf"), float("nan"), float(" 2.5 "))
try:
float("3,14")
except ValueError as err:
print("ValueError:", err)
str() — building a new stringstr() — नई string बनानाstr() —— 构建新字符串
print(str(42), str(3.14), str(True), str(None))
print(str([1, 2, 3]), str({"a": 1}))
print(repr(str(42))) # quotes show it is now text
age = 25
try:
msg = "I am " + age
except TypeError as err:
print("TypeError:", err)
print("I am " + str(age))
print(f"I am {age}") # f-strings convert for you
Conversion Cheat SheetConversion Cheat Sheet转换速查表
| Fromसे源值 | int() | float() | str() |
|---|---|---|---|
int 42 | 42 | 42.0 | '42' |
float 3.9 | 3 | 3.9 | '3.9' |
float -3.9 | -3 | -3.9 | '-3.9' |
str "42" | 42 | 42.0 | '42' |
str "3.14" | ValueError | 3.14 | '3.14' |
str "hi" | ValueError | ValueError | 'hi' |
bool True | 1 | 1.0 | 'True' |
None | TypeError | TypeError | 'None' |
Every cell above was computed by Python while building this page. A conversion always makes a new object — the original is untouched:
ऊपर का हर cell यह page बनाते समय Python ने निकाला। Conversion हमेशा नया object बनाता है — मूल वैसा ही रहता है:
上表的每个单元格都是生成本页时由 Python 计算的。转换总是生成新对象 —— 原对象不受影响:
s = "42"
n = int(s)
print(type(s).__name__, type(n).__name__, s is n, id(s) == id(n))
print(repr(s)) # the string is untouched
Pick a value to see what int(), float() and str() really return for it.
एक मान चुनें और देखें int(), float() और str() उसके लिए सच में क्या लौटाते हैं।
选择一个值,看看 int()、float() 和 str() 实际返回什么。
Putting It All Together — Practice Program 🧪सब एक साथ — अभ्यास Program 🧪综合运用 —— 练习程序 🧪
This script shows every idea from the lesson with real ids. Run it yourself: your ids will be different numbers, but every True/False will match.
यह script lesson का हर विचार असली ids के साथ दिखाती है। इसे ख़ुद चलाएँ: आपके ids अलग संख्याएँ होंगे, पर हर True/False मेल खाएगा।
这个脚本用真实的 id 展示了本课的每个概念。自己运行一下:你的 id 数字会不同,但每个 True/False 都会一致。
# variable_lab.py — every idea from this lesson in one script
def show(name, value):
"""Print a name, its value, its type and its object id."""
print(f" {name:<7} = {value!r:<7} type={type(value).__name__:<6} id={id(value)}")
def main():
line = "─" * 48
print(f"{line}\n 1. Binding — a = 1000\n{line}")
a = 1000
show("a", a)
first = id(a)
print(f"\n{line}\n 2. Reassignment — a = 2000\n{line}")
a = 2000
show("a", a)
print(f" same object as before? {id(a) == first}")
print(f"\n{line}\n 3. a += 1 (Python's answer to a++)\n{line}")
before = id(a)
a += 1
show("a", a)
print(f" same object as before? {id(a) == before}")
print(f"\n{line}\n 4. Mutation keeps the id\n{line}")
scores = [90, 85]
before = id(scores)
scores.append(70)
print(f" {scores} — same object? {id(scores) == before}")
print(f"\n{line}\n 5. Small-int cache (numbers made at run time)\n{line}")
for n in ("100", "1000"):
x, y = int(n), int(n)
print(f" int({n!r}) is int({n!r}) → {x is y} == → {x == y}")
print(f"\n{line}\n 6. Conversions build new objects\n{line}")
user_input = "42" # imagine this came from input()
show("text", user_input)
show("as_int", int(user_input))
show("as_flt", float(user_input))
show("back", str(int(user_input)))
print(f"\n{line}\n 7. Counter loop — the Pythonic way\n{line}")
counter = 0
for _ in range(5):
counter += 1 # NOT counter++
print(f" final counter: {counter}")
if __name__ == "__main__":
main()
Golden Rules 🏆सुनहरे नियम 🏆黄金法则 🏆
Six questions on names, objects and the cache. Pick an answer to see why.
नाम, objects और cache पर छह सवाल। जवाब चुनें और कारण देखें।
关于名字、对象和缓存的六道题。选择答案查看解释。
Python variables are name tags on objects. Assignment moves a tag; it never copies. Immutable objects (int, float, str) are never changed — operations build new ones, so id() changes, and that is why a++ makes no sense in Python. Mutable objects (list, dict, set) can change in place, and every name for them sees it. The −5…256 cache is a CPython speed trick, not a rule: compare values with ==.
Python variables objects पर लगे name tags हैं। Assignment tag ले जाता है; copy कभी नहीं करता। Immutable objects (int, float, str) कभी नहीं बदलते — operations नए बनाते हैं, इसलिए id() बदलता है, और इसीलिए Python में a++ का कोई मतलब नहीं। Mutable objects (list, dict, set) अपनी जगह बदल सकते हैं, और उनके हर नाम को यह दिखता है। −5…256 cache CPython की speed trick है, नियम नहीं: मानों की तुलना == से करें।
Python 变量是贴在对象上的名字标签。赋值移动标签,从不复制。不可变对象(int、float、str)永远不会被修改 —— 运算会生成新对象,所以 id() 会变,这也是 a++ 在 Python 中没有意义的原因。可变对象(list、dict、set)可以原地修改,它的所有名字都能看到。−5…256 缓存是 CPython 的加速技巧,不是语言规则:比较值请用 ==。