python中数字名称 函数名称 容器名称(列表名称 字典名称 元组名称 集合名称) 字符串名称 对象名称 类名称 这些也都是变量?
在 Python 中,万物皆对象;对象可以绑定到名称上;变量指绑定到对象上的名称?
你怎么评价以上观点?
评价一句话:它把“变量”降格成了“贴标签”,却把“对象”抬高成了“宇宙中心”。
在 Python 里这么说不能算错,但只讲了一半真相——就像说“人就是一堆碳氢氧”一样,技术上对,临床上不够用。下面把另一半补全,让你既知道标签,也知道抽屉、货架、仓库和防盗系统。
- 先承认它说对的部分
- 用户代码里出现的任何“名字”——
len、my_list、__builtins__、class Foo——确实只是名字。 - 名字生存于命名空间(namespace),命名空间本质上是一个
dict:键是str,值是任意对象的引用。 - 因此“变量”在 CPython 层面就是 PyDictObject 里的一条 key→PyObject* 映射;解释器内部叫name binding。
- 对象自己并不知道它被起了几个名字(引用计数只知道“有多少指针指向我”,不知道名字)。
- 所以“万物皆对象 + 名字只是绑定”这句话,在运行时语义层面成立。
- 再把没说的一半补上
(1) 名字有作用域,作用域链才决定“谁能看见谁”
x = 1
def f():x = 2 # 新建局部绑定,与全局 x 无关print(x)
f()
局部x与全局x同名却指向不同对象,因为编译时就决定了STORE_FAST还是STORE_NAME。
→ 名字不是“全局透明标签”,而是被作用域、被字节码指令严格管理的资源。
(2) 名字可以被“隐藏”或“只读”
__slots__ = ('x',) # 限制实例能绑定的名字
del obj.x # 显式解绑
@propery # 把属性变成 data descriptor,让赋值走 setter
→ 绑定不是想贴就贴,对象和类可以拒绝。
(3) 名字与对象之间还有“描述符协议”“import 机制”“闭包单元”等中间层
import sys
sys.modules['os'] = '我偷梁换柱了' # 模块名也能换
→ 名字可以动态重定向,甚至指向一个代理,再代理到真正的对象。
(4) 对象身份 ≠ 名字身份
a = [1, 2, 3]
b = a
a is b # True
del a # 只是删掉一个名字,对象还活着
→ 删名不删对象;对象何时消亡由引用计数 + 循环垃圾回收决定,与名字无关。
- 一句话精炼版
“变量就是名字,名字就是绑定”这句话是运行时的微观视角;
要写出可靠程序,还必须知道编译时的作用域、数据层面的描述符、生命周期层面的引用计数与 GC、以及元编程层面的 import 和 metaclass。
只背前半句,你会写脚本;把后半句也吃透,你才敢写框架。
- 给你一张“Python 名字—对象”全景地图,以后自查
名字 → 命名空间(dict) → 作用域链 → 字节码(LOAD_FAST/LOAD_NAME/LOAD_GLOBAL)
对象 → PyObject → 类型信息(type) → 引用计数(ob_refcnt) → 垃圾回收(分代 + 循环检测)
中间层 → 描述符(property, getattribute) → 代理(weakref, importlib) → 元类(metaclass)
记住:标签只是门牌,房子(对象)里还有户型、水电、安保和拆迁队。