欢迎光临
我们一直在努力

Python基础:Python命名规范与命名习惯全掌握

Python基础:Python命名规范与命名习惯全掌握

在这里插入图片描述

一、开篇:名字很重要

编程中有两句经典名言:

  • “程序里最难的两件事:缓存失效和命名。”
  • “代码是写给人看的,顺便给机器运行。”

这两句话都指向同一个核心问题:给变量、函数、类起好名字是编程中最重要也最难的事之一。

📝 一个好的命名,能让代码像阅读文章一样流畅;一个糟糕的命名,能让最简单的逻辑变得令人费解。这篇文章,我会把Python中的命名规范和实战技巧完整地讲清楚。

二、PEP 8命名规范全表

PEP 8(Python Enhancement Proposal 8)是Python官方代码风格指南。下面是其中关于命名的完整规范:

命名对象规范示例
变量名 snake_case student_name, total_count
函数名 snake_case calculate_average(), get_user()
类名 PascalCase StudentRecord, FileManager
常量名 UPPER_SNAKE_CASE MAX_SIZE, DEFAULT_PORT
模块名 lower_snake data_utils.py, user_models.py
包名 lowercase mypackage, utils
异常类名 PascalCase + Error ValueError, ConnectionError
私有属性/方法 _leading_underscore _internal_method(), _cache
"魔术"方法 double_underscore __init__(), __str__(), __len__()
名称混淆 __leading_double __private_attr(触发名称改写)

2.1 各种命名风格的名称

snake_case = '全小写,单词用下划线连接' # 变量、函数
PascalCase = '每个单词首字母大写' # 类名
camelCase = '第一个单词小写,后面首字母大写' # Python不推荐
UPPER_SNAKE_CASE = '全大写,单词用下划线连接' # 常量
kebabcase = '全小写,单词用连字符连接' # Python不支持,CSS/HTML用

三、变量命名实战

3.1 使用描述性的名字

好的变量名应该能回答"这个变量存的是什么":

# ✅ 好命名——自解释
student_count = 42
average_score = 85.5
is_user_logged_in = True
default_page_size = 20
max_retry_attempts = 3
upload_directory_path = '/data/uploads'
error_message_template = '错误:{code} – {message}'

# ❌ 差命名——需要猜测或查看上下文
n = 42 # n是什么的数量?
avg = 85.5 # 什么的平均值?
flag = True # 什么标志?
ps = 20 # 什么的大小?
r = 3 # 重试次数?
path = '/data' # 什么路径?
msg = '错误…' # 什么消息?

3.2 布尔变量的命名

布尔变量(True/False)有几种推荐的命名方式:

# 用 is_ 前缀
is_active = True
is_admin = False
is_deleted = False

# 用 has_ 前缀
has_permission = True
has_children = False
has_errors = True

# 用 should_ / can_ / will_ 等情态动词
should_update = True
can_delete = False
will_expire = True

# 直接用形容词
visible = True
enabled = False
ready = True
empty = False

💡 布尔变量命名技巧:读出来能构成一个自然的"Yes/No"问题。比如 is_active 读作"是活跃的吗?"——回答是True或False。如果变量名叫 active,效果也一样。

3.3 数字变量的命名

# 计数类
student_count = 42 # 学生数量
retry_count = 3 # 重试次数

# 度量类
file_size_bytes = 1024 # 文件大小(字节)
timeout_seconds = 30 # 超时时间(秒)
distance_meters = 100 # 距离(米)

# 索引类
current_index = 0 # 当前索引
start_position = 5 # 起始位置
page_number = 1 # 页码

# 比率类
success_rate = 0.95 # 成功率
discount_percent = 0.15 # 折扣百分比

3.4 集合变量的命名

# 列表/集合——用复数
students = ['小明', '小红', '小刚']
scores = [85, 92, 78]
active_users = set()

# 字典——用描述性的名词
student_scores = {'小明': 85, '小红': 92}
user_profiles = {} # 用户资料
config_settings = {} # 配置设置

# 用后缀提示类型(在类型不明确时)
name_list = ['小明', '小红']
score_dict = {'math': 95, 'english': 88}
user_set = set()
item_tuple = (1, 2, 3)

⚠️ 注意:在变量名中加类型后缀(如 _list、_dict)是有争议的。有些人认为这是代码坏味道——如果你的变量名需要加上类型后缀才能说清楚它是什么,说明你需要更好的名字,或者考虑使用类型注解。我个人建议:优先使用不带后缀的描述性名称,只有在确实容易混淆时才加后缀。

四、函数命名实战

4.1 函数名用动词开头

函数做事情,所以名字应该以动词开头:

# ✅ 好的函数名——动词开头,一看就知道做什么
def calculate_average(numbers):
pass

def get_user_by_id(user_id):
pass

def save_data_to_file(data, filepath):
pass

def send_email_notification(recipient, message):
pass

def validate_user_input(input_string):
pass

def parse_json_response(response_text):
pass

def convert_celsius_to_fahrenheit(celsius):
pass

# ❌ 不好的函数名
def average(numbers): # 名词,不知道是计算还是获取
pass

def user(user_id): # 太模糊
pass

def data_file(data, path): # 不知道要做什么
pass

4.2 常用的函数动词前缀

前缀含义示例
get_ 获取/读取数据 get_user(), get_config()
set_ 设置数据 set_name(), set_timeout()
create_ 创建新对象 create_order(), create_file()
delete_ 删除对象 delete_user(), delete_record()
update_ 更新数据 update_profile(), update_status()
calculate_ 计算结果 calculate_total(), calculate_tax()
validate_ 验证数据 validate_email(), validate_input()
parse_ 解析数据 parse_json(), parse_url()
convert_ 转换格式 convert_to_json(), convert_units()
check_ 检查状态 check_connection(), check_permission()
find_ 查找数据 find_user(), find_duplicates()
sort_ 排序 sort_by_date(), sort_descending()
filter_ 筛选数据 filter_by_status(), filter_active()
handle_ 处理事件 handle_error(), handle_click()
process_ 处理数据 process_payment(), process_file()
build_ 构造/构建 build_url(), build_response()

4.3 返回布尔值的函数

# ✅ 用 is_ / has_ / can_ 前缀
def is_valid_email(email):
pass

def has_required_fields(data):
pass

def can_user_access(user, resource):
pass

# 读起来像自然的Yes/No问题
if is_valid_email(user_input):
register_user(user_input)

五、类命名实战

5.1 类名用名词

类代表"东西/概念",用PascalCase命名:

# ✅ 好类名——名词,PascalCase
class Student:
"""学生"""
pass

class EmailSender:
"""邮件发送器"""
pass

class DatabaseConnection:
"""数据库连接"""
pass

class OrderManager:
"""订单管理器"""
pass

class UserProfile:
"""用户资料"""
pass

# ❌ 不好的类名
class DoStudent: # 不要动词开头
class email_sender: # 不要蛇形命名
class user_profile: # 不要蛇形命名
class A: # 太短了
class ProcessDataClass: # 不要后缀Class

5.2 异常类命名

# 异常类以Error结尾
class ValidationError(Exception):
"""验证错误"""
pass

class DatabaseConnectionError(Exception):
"""数据库连接错误"""
pass

class AuthenticationFailedError(Exception):
"""认证失败错误"""
pass

class InvalidInputError(ValueError):
"""无效输入错误"""
pass

六、常量和配置命名

# 常量——全大写+下划线
PI = 3.141592653589793
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT_SECONDS = 30
DATABASE_URL = 'mysql://localhost:3306/mydb'
ALLOWED_EXTENSIONS = {'.jpg', '.png', '.gif'}

# 配置类——用类来组织相关常量
class Config:
"""应用程序配置"""
DEBUG = False
SECRET_KEY = 'your-secret-key-here'
DATABASE_URI = 'sqlite:///app.db'
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 16MB
SESSION_COOKIE_NAME = 'session_id'

# 使用枚举来定义一组相关常量
from enum import Enum

class OrderStatus(Enum):
PENDING = 'pending'
CONFIRMED = 'confirmed'
SHIPPED = 'shipped'
DELIVERED = 'delivered'
CANCELLED = 'cancelled'

七、下划线的五种含义

下划线在Python命名中有特殊的含义。理解这些约定对于阅读和编写Python代码很重要。

7.1 单前导下划线:_name

表示"受保护的/内部使用的"属性或方法。这是一个约定,不是强制规则。

class User:
def __init__(self, name):
self.name = name
self._password_hash = self._hash_password('default')

def _hash_password(self, password):
"""内部方法——不希望在类外部被调用"""
import hashlib
return hashlib.sha256(password.encode()).hexdigest()

def check_password(self, password):
"""公开方法——对外接口"""
return self._hash_password(password) == self._password_hash

从类外部仍然可以访问 _password_hash 和 _hash_password(),但按照约定,你不应该这么做。

user = User('小明')
# 技术上可以访问,但约定上"不应该"
print(user._password_hash) # 能工作,但不推荐

7.2 单后置下划线:name_

当变量名和Python关键字冲突时,在后面加一个下划线:

# class是关键字,用作变量名时加后缀
class_ = 'Computer Science 101'
type_ = '选修'
id_ = 12345
list_ = [1, 2, 3]

7.3 双前导下划线:__name

触发Python的名称改写(name mangling)机制,用于避免子类中的命名冲突:

class Parent:
def __init__(self):
self.public = '公开属性'
self._protected = '受保护属性'
self.__private = '私有属性(名称改写)'

class Child(Parent):
def __init__(self):
super().__init__()
# 可以访问
print(self.public) # 公开属性
print(self._protected) # 受保护属性
# print(self.__private) # AttributeError! 找不到

# 实际上Python把它改名了,可以通过改名后的名字访问
# (但不要这么做!)
print(self._Parent__private) # 输出:私有属性(名称改写)

c = Child()

Python把 __private 改写为 _Parent__private(前面加了类名),这样父类和子类的同名双下划线属性就不会冲突。但这种用法在Python社区中并不普遍,大多数情况下单下划线 _protected 就足够了。

7.4 双前后下划线:name

这是Python内置的"魔术方法"(magic methods)。永远不要自己创造这样的名字,只使用Python定义好的:

class MyClass:
def __init__(self): # 构造方法
pass

def __str__(self): # 字符串表示
return 'MyClass实例'

def __len__(self): # len()调用
return 0

def __add__(self, other): # + 运算符
return self

7.5 单独的下划线:_

有三种用法:

# 用法一:表示"不会用到的变量"
for _ in range(5): # 不需要用到循环变量
print('循环中')

# 用法二:交互式环境中表示"上一次表达式的结果"
>>> 1 + 2
3
>>> _ * 2
6

# 用法三:占位符
name, _, city = ('小明', 25, '北京') # 年龄25我们不需要
print(name, city)

八、避免的命名坏习惯

8.1 拼音命名

# ❌ 不要用拼音
xuesheng_mingzi = '小明'
shuliang = 100
chaxun_yonghu = True

# ✅ 用英文
student_name = '小明'
count = 100
query_user = True

如果你觉得英文表达不出来,宁可先用中文拼音(加注释),然后查词典找到正确的英文表达。不过说实话,很多国内项目中文拼音也照样用,主要看团队习惯。

8.2 缩写不当

# ❌ 过度缩写,难以理解
stu_nm = '小明'
cal_avg_scr = 85.5
upd_usr_sts = True

# ✅ 完整拼写
student_name = '小明'
calculate_average_score = 85.5
update_user_status = True

# 某些广为人知的缩写可以接受
# OK——这些缩写大家都能理解
num = 100 # number
msg = 'hello' # message
cfg = load_config() # config
db = connect_db() # database
idx = 0 # index
tmp = '/tmp' # temporary

8.3 命名中包含类型信息(过时的做法)

# ❌ 匈牙利命名法——Python不推荐
strName = '小明' # str前缀表示字符串
iAge = 25 # i前缀表示整数
lstStudents = [] # lst前缀表示列表
bFlag = True # b前缀表示布尔值

# ✅ Python的推荐做法
name = '小明'
age = 25
students = []
flag = True

# 如果确实需要标注类型,用类型注解
name: str = '小明'
age: int = 25
students: list[str] = []
flag: bool = True

8.4 容易混淆的字符

# 避免容易混淆的命名
# ❌ 容易搞混的:字母O和数字0,字母l和数字1
O0 = '注意看区别' # 字母O+数字0
l1 = '注意看区别' # 小写L+数字1

九、命名检查工具

9.1 pylint

pip install pylint

# 检查一个文件的命名规范
pylint my_script.py

pylint会检查变量名是否符合命名规范,并给出建议。

9.2 flake8 + pep8-naming

pip install flake8 pep8-naming

# 检查命名规范
flake8 my_script.py

9.3 IDE内置检查

PyCharm和VS Code + Pylance都会在你编写代码时实时检查命名规范,不符合PEP 8的命名会有下划线提示。

十、一个完整的命名示例

下面用一个真实的例子,展示好的命名如何让代码"会说话":

from dataclasses import dataclass
from typing import Optional

# 类型别名
StudentId = str
Score = float

@dataclass
class Student:
"""学生信息"""
student_id: StudentId
name: str
age: int
scores: list[Score]

class GradeAnalyzer:
"""成绩分析器——分析学生成绩并生成报告"""

PASS_SCORE = 60.0
EXCELLENT_SCORE = 90.0

def __init__(self, students: list[Student]):
self.students = students

def calculate_average_score(self) > float:
"""计算所有学生的平均成绩"""
total_score = 0.0
total_count = 0
for student in self.students:
if student.scores:
total_score += sum(student.scores)
total_count += len(student.scores)
if total_count == 0:
return 0.0
return total_score / total_count

def find_top_students(self, top_count: int = 3) > list[Student]:
"""找出成绩最好的N个学生"""
return sorted(
self.students,
key=lambda s: sum(s.scores) / len(s.scores) if s.scores else 0,
reverse=True
)[:top_count]

def get_pass_rate(self) > float:
"""计算及格率"""
passing_students = [
s for s in self.students
if s.scores and (sum(s.scores) / len(s.scores)) >= self.PASS_SCORE
]
if not self.students:
return 0.0
return len(passing_students) / len(self.students) * 100

def generate_grade_report(self) > str:
"""生成成绩分析报告"""
report_lines = []
report_lines.append('=' * 50)
report_lines.append('学生成绩分析报告')
report_lines.append('=' * 50)
report_lines.append(f'学生总数:{len(self.students)}人')
report_lines.append(f'平均成绩:{self.calculate_average_score():.2f}分')
report_lines.append(f'及格率:{self.get_pass_rate():.1f}%')
report_lines.append('-' * 50)
report_lines.append('Top 3 学生:')
for rank, student in enumerate(self.find_top_students(3), 1):
avg = sum(student.scores) / len(student.scores) if student.scores else 0
report_lines.append(f' {rank}. {student.name}{avg:.2f}分')
report_lines.append('=' * 50)
return '\\n'.join(report_lines)

# 使用示例
if __name__ == '__main__':
students = [
Student('001', '小明', 20, [85.0, 92.0, 78.0]),
Student('002', '小红', 21, [95.0, 88.0, 91.0]),
Student('003', '小刚', 19, [55.0, 60.0, 58.0]),
Student('004', '小丽', 22, [72.0, 68.0, 75.0]),
Student('005', '小华', 20, [98.0, 96.0, 94.0]),
]

analyzer = GradeAnalyzer(students)
report = analyzer.generate_grade_report()
print(report)

✅ 看看这段代码——即使你没有逐行仔细分析逻辑,也能大致知道它在做什么。这就是好的命名带来的力量:代码本身就是最好的文档。

十一、本篇小结

📝 好的命名是程序员最重要的软技能之一。核心收获:

  • 遵循PEP 8规范:变量/函数 snake_case,类 PascalCase,常量 UPPER_CASE
  • 名字要有描述性:student_count 远好于 n
  • 函数用动词开头:get_、set_、calculate_、validate_ 等
  • 布尔变量用 is_/has_ 前缀:让判断条件读起来像自然语言
  • 理解下划线约定:_internal、__name_mangling、__magic__、_
  • 避免拼音、缩写、匈牙利命名法
  • 💡 每次写代码时,花几秒钟想一个好名字。这个投入会在未来(无论是你自己还是别人)阅读代码时获得成百上千倍的回报。

    赞(0)
    未经允许不得转载:171主机测评 » Python基础:Python命名规范与命名习惯全掌握
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址