当前位置: 首页 > news >正文

Part 1:Python 语言核心 - 变量与命名规则

Python 基础语法 - 变量与命名规则

一、python 变量的真实模型

变量 = 名字(name)→ 对象(object)的“绑定关系”

python 中变量本身不存值,值永远存储在对象里,变量只是标签/引用。

a=10

底层语义等价于:

创建整数对象 10 将名字 a 绑定到对象 10

明白这点有助于理解

  • 赋值
  • 传参
  • 可变 / 不可变
  • 拷贝 / 引用
  • globel / nonlocal

二、变量的绑定而不是赋值

重新绑定(Rebinding)

a=10a=20

不是修改 10

是:

  • 创建对象20
  • a从原来的对象解绑
  • a绑定到新对象
a ──▶ 10 ↓ a ──▶ 20

这就是为什么:

id(10)==id(10)# True(小整数缓存)

多个变量指向同一个对象

a=[1,2,3]b=a

内存模型:

a ─┐ ├──▶ [1, 2, 3] b ─┘

修改对象:

a.append(4)print(b)# [1, 2, 3, 4]

三、变量名命名规则

Python 变量名必须满足:

  • 只能包含:

    • 字母(a-z, A-Z)
    • 数字(0-9)
    • 下划线(_
  • 不能以数字开头

  • 区分大小写

  • 不能是关键字:(共35个)

    FalseNoneTrueandasassertasyncawaitbreakclasscontinuedefdelelifelseexceptfinallyforfromglobalifimportinislambdamatchcasenonlocalnotorpassraisereturntrywhilewithyield

为什么这样设计

这和 **词法分析(Lexical Analysis)**有关。

Python 在解析源码时:

  • 需要快速区分:
    • 标识符(identifier)
    • 数字字面量
    • 运算符

如果允许:

2name

解析器将无法区分这是:

  • 数字2
  • 变量name

📌 这不是“规定”,而是编译器设计必然结果

四、命名 ≠ 语法问题,而是「语义设计」

变量名的语义作用

x = 3.14

vs

pi = 3.14

Python 不做类型声明:
👉变量名本身就是“类型提示 + 业务语义”

📌 这也是 Python 社区极度强调命名的原因

PEP 8 命名规范(不是形式主义)

标识符类型规范示例备注
变量、函数、方法、模块、包全小写 + 下划线user_id,calculate_total(),my_module最通用的规则。
常量全大写 + 下划线MAX_CONNECTIONS,DEFAULT_PORT定义在模块级别,值不应改变。
类、异常首字母大写单词串HttpClient,CustomError类名应有名词属性。
类的方法参数首选self,clsdef method(self, param):self是实例引用,cls是类引用。
“私有”属性/方法单下划线开头_internal_cache,_helper_method()提示“内部使用”,非强制。
避免命名冲突单下划线结尾class_,type_避免与关键字冲突。
类/模块内部实现双下划线开头__private_var触发名称改写,实现弱私有。

下划线的“语义约定”(重点)

_var:约定为内部使用
_internal_cache={}

👉 含义:

  • “你可以用”
  • “但别依赖它”

__var:名称改写(Name Mangling)
classA:def__init__(self):self.__x=10

等价于:

self._A__x

📌 目的不是安全,而是避免子类命名冲突


_:临时变量 / 无意义变量
for_inrange(10):print("hello")

或:

a,_,c=(1,2,3)

📌 明确表达:

“我知道这里有值,但我不关心”

五、变量的「生命周期」与「作用域」

变量是否存在,取决于名字是否在当前作用域的命名空间中

deffunc():x=10print(x)# ❌ NameError

后面系统展开,变量存在于命名空间而不是代码本身。

六、变量 vs 对象 vs 类型(三者关系)

a = 10

分解为:

层级内容
名字a
对象10
类型int
type(a) is int # True

📌 类型属于对象,不属于变量
📌 Python 是动态类型 + 强类型

动态类型

动态类型的含义:变量的类型在运行时才确定,并且可以随时改变。我们无须也无法在代码中提前声明变量将存放何种类型的数据。

# 典型动态类型代码x=100# 此时 x 引用一个整数x="Python"# 现在 x 引用一个字符串(完全合法)x=[1,2,3]# 现在 x 引用一个列表# 编译器/解释器在运行前不知道 x 会是什么类型

动态类型的优势与代价

  • 灵活、代码简洁:无需类型声明,快速原型开发。
  • 运行时类型错误:类型相关的错误只能在代码运行时被发现。
  • 工具支持难度大:IDE 的自动补全、跳转、重构不如静态语言精准。

强类型

强类型含义:对象一旦创建,其类型就固定不变。不同类型对象间的操作受到严格限制,除非进行显式的类型转换。

# 强类型语言的典型表现a=10b="20"# print(a + b) # ❌ TypeError: 不能隐式地将 'int' 加到 'str'print(a+int(b))# ✅ 30,需要**显式**转换 str -> intprint(str(a)+b)# ✅ "1020",需要**显式**转换 int -> str

对比弱类型:

// JavaScript (弱类型) - 隐式类型转换很常见leta=10;letb="20";console.log(a+b);// ✅ "1020",数字 10 被隐式转换为字符串 "10"

强类型的优势与代价

  • 行为可预测:代码意图明确,减少因隐式转换带来的诡异bug。
  • 更安全:意外地将字符串当数字用的错误会被立即抛出。
  • 稍显繁琐:需要多写一些类型转换代码。

动态 + 强类型 = Python 的特点

结合两者,Python 的特点是:

“可以随时把变量名贴到任何类型的对象上(动态),但贴上去之后,这个对象能做什么由它自己的类型严格决定(强类型)。”

为什么 Python 不需要“声明变量”?

对比 C / Java:

int a = 10;

Python:

a = 10

原因:

  • Python 是:
    • 动态类型
    • 运行时创建对象
  • 变量只在运行时绑定
  • 不需要编译期类型检查

📌 这直接影响了 Python 的:

  • 灵活性
  • 性能
  • 错误发现时机

工程化实践原则之 .py 文件命名规范

.py文件命名看似随意,其实暗含了 Python 的模块机制、导入规则和工具生态假设

一、.py文件名在 Python 中意味着什么?

一个.py文件 = 一个模块(module)

utils.py → 模块名 utils

📌 文件名直接成为模块名的一部分
📌 影响:

  • import
  • from ... import ...
  • __name__
  • 包结构
  • 工具扫描(pytest / mypy / coverage)

二、Python 官方命名规范(PEP 8)

✅ 推荐规则(核心)

模块名应使用:全小写字母 + 下划线(snake_case)

good: utils.py file_reader.py user_service.py bad: Utils.py FileReader.py userService.py

📌 原因不是“好看”,而是:

  • 跨平台一致性
  • 导入语义清晰
  • 避免大小写敏感问题(Windows vs Linux)

🚫 不推荐的命名方式

1. 含大写字母
import Utils # 可行,但不推荐

问题:

  • Linux 区分大小写
  • Windows 不区分
  • Git 合并冲突高发区

2. 含连字符-
my-utils.py # ❌ import my-utils # 语法错误

📌 因为-在 Python 中是减号


3. 以数字开头
1_utils.py # ❌ import 1_utils # ❌

原因同变量命名规则。


4. 使用关键字作为文件名(强烈不建议)
import.py class.py async.py

📌 结果:

import import # ❌ 语法直接炸

即使你用importlib,也会造成灾难性的可读性问题。

三、.py文件命名与 import 机制

模块名 = 文件名去掉 .py

math_utils.py import math_utils

📌 Python 在sys.path中查找:

  • 内置模块
  • 第三方模块
  • 当前项目模块

文件名不能是内置模块

典型踩坑

random.py
importrandom random.randint(1,10)# ❌ 崩

原因:

  • 你自己的random.py把标准库random**遮蔽(shadow)**了

📌 这是 Python 新手和老手都会踩的坑。

🚫常见不要用的名字

sys.py os.py time.py json.py logging.py asyncio.py

四、包 (package)命名规范

一个目录 +__init__.py= 包

my_project/│ ├── data_utils/│ ├── __init__.py │ ├── reader.py │ └── writer.py

📌 包名规则和模块名完全一致

  • 小写
  • 下划线
  • 不用关键字
  • 不和标准库重名

五、包的初始化

Python 3.3 之前:只有包含__init__.py的目录,才会被认为是一个包。

mypkg/ ├── __init__.py ← 有它,mypkg 才是包 ├── a.py └── b.py

没有__init__.py

mypkg/ ├── a.py └── b.py

Python 不认为它是包,无法import mypkg.a

为什么要用__init_.py这个名字?

因为 Python 的模块机制是:

  • 模块:一个.py文件
  • :一个“特殊的模块”,对应一个目录
  • __init__.py就是这个包对应的“模块文件”
包 ≈ 目录 + __init__.py
importmypkg# 实际执行的是 mypkg/__init__.py

__init__.py的核心语义

__init__.py是 “包被导入时最先执行的代码”

包导入时发生了什么
importmypkg

等价于:

# 1. 找到 mypkg 目录# 2. 执行 mypkg/__init__.py# 3. 创建一个 mypkg 模块对象

所以我们可以在__init__.py里:

  • 初始化包级变量
  • 导入子模块
  • 控制对外暴露的 API
  • 执行一次性初始化逻辑
常见用途一:聚合子模块(最常见)
mypkg/├── __init__.py ├── user.py └── order.py
不用__init__.py聚合:
from mypkg.user import User from mypkg.order import Order
__init__.py聚合:
# mypkg/__init__.py from .user import User from .order import Order

现在用户可以这样用:

from mypkg import User, Order

👉对外 API 更干净、更专业

常见用途二:限制from package import *
# mypkg/__init__.py__all__=["User"]
frommypkgimport*

只会导入User,不会导入内部实现。

常见用途三:包级初始化
# mypkg/__init__.pyprint("mypkg 初始化中")DB_CONN=create_connection()

整个程序中,这段代码只执行一次

Python 3.3+ 没有__init__.py也可以作为包

Python 3.3(PEP 420)开始:

没有__init__.py的目录,也可以作为包

mypkg/ ├── a.py └── b.py

我们可以:

import mypkg.a

✅ 成功

这类包叫做:命名空间包

为什么现在还要写__init__.py?

因为:

场景是否需要__init__.py
想写初始化代码✅ 必须
想定义__all__✅ 必须
想聚合子模块✅ 必须
想明确“这是一个包”✅ 推荐
大型工程 / 团队协作✅ 强烈推荐
临时脚本❌ 可省略

👉现实工程中:几乎都会加

工程视角:为什么“专业项目一定有__init__.py?
1️⃣ 明确模块边界(非常重要)

__init__.py是一个“设计边界”

这是一个对外提供 API 的包 而不是随便 import 的目录
2️⃣ 防止隐式 Bug

没有__init__.py

  • 容易被误判为普通目录
  • IDE、打包工具、老版本 Python 行为不一致
  • 相对导入行为更复杂

六、文件名的”语义粒度“(工程经验)

1️⃣ 文件名 = 职责边界

好的:

auth.py # 认证 permissions.py # 权限 token.py # Token 逻辑

坏的:

utils.py # 万能垃圾桶 common.py helper.py

📌 如果一个文件叫utils.py
👉 往往意味着“该拆了”


2️⃣ 单数 vs 复数

场景推荐
行为 / 逻辑单数:auth.py
集合 / 数据复数:models.py

📌 Django / FastAPI 都遵循这个约定

七、特殊.py文件命名

__init__.py

  • 标记目录为包
  • 控制包的对外 API
  • 影响from pkg import *

__main__.py

python -m mypackage

📌 入口模块


__all__

不是文件,但与模块导出强相关:

__all__ = ["func1", "func2"]

八、工具生态对文件名的隐含要求

pytest

test_*.py *_test.py

alembic / django / flask

  • 有强约定文件名
  • 偏离会导致工具扫描不到

📌 命名 ≠ 个人喜好
📌 命名 = 与生态工具“对齐”

http://www.jsqmd.com/news/574037/

相关文章:

  • GameFramework——FileSystem篇
  • Cpp面试题(持续更新)
  • 2026除尘净化一体机厂家推荐:超声波除尘一体机哪家好?湿式除尘一体机源头厂家精选 - 栗子测评
  • 阿里:多模态检索课程进化框架
  • YOLOv8 验证模式深入解析:model.val() 方法的各项参数,如 split(验证集划分)、save_json(输出 COCO JSON 结果)、conf 等,实现灵活的评估策略
  • Linux文件权限详细解读
  • 2026年4月怎么搭建OpenClaw?本地4分钟零门槛指南及百炼APIKey配置步骤
  • Pixel Fashion Atelier新手教程:RPG式交互界面操作全图解
  • OpenClaw移动办公:iPad远程调用Kimi-VL-A3B-Thinking服务
  • 2026年评价高的热收缩包装机厂家对比推荐 - 品牌宣传支持者
  • 水果网发泡机哪家好?2026EPE发泡设备生产厂家全览:EPE发泡生产线厂家+EPE发泡设备供应商+水果网发泡机厂家深度 - 栗子测评
  • 深入大模型-30-learn-claude-code之第五课Skills技能加载
  • 2026年口碑好的西安混凝土检查井/陕西混凝土检查井精选推荐公司 - 品牌宣传支持者
  • TCA9548A I²C多路复用器原理与嵌入式实战指南
  • 2026年4月OpenClaw怎么部署?阿里云3分钟喂奶级安装及百炼APIKey配置流程
  • Private VLAN与Super VLAN
  • python客户股票交易教学系统的设计与实现
  • PE珍珠棉发泡机哪家好?珍珠棉发泡机哪个品牌好?2026PE珍珠棉发泡机生产厂家+珍珠棉发泡设备供应商全解析 - 栗子测评
  • SSM+JSP动漫网站源码+论文
  • 【回眸】头马演讲备稿演讲框架——出走的莉莉丝
  • AOM vs EOM:激光调制技术选型指南(含带宽测试实战)
  • 从SRCNN到WDSR:图像超分辨率核心演进路径与关键技术剖析
  • OpenClaw邮件自动化:Qwen3-14B分类处理1000+封未读邮件
  • 2025最权威的六大AI论文方案推荐榜单
  • 2026届必备的五大AI辅助写作方案推荐榜单
  • 2026年智能开关贴牌指南:聚焦温州,谁在“速度”与“可靠”上双优? - 2026年企业推荐榜
  • OpenClaw配置备份技巧:Qwen3.5-9B模型迁移无缝衔接方案
  • 经典算法实现:二分查找、全排列与子集生成
  • Windows 使用free-claude-code中转实现 claude code 调用 英伟达NVIDIA API
  • OpenClaw 是基于 Node.js 开发的本地 AI 智能体网关,部署核心是先装 **Node.js ≥ 22**,再用 npm 全局安装并完成配置向导