Python技术迷

说明 Python 中标识符的命名规则

Python 变量名别乱起,解释器第一刀就砍在这里

3user = "tom",这行代码跑不起来。

报错也很直接:

SyntaxError: invalid decimal literal

这种问题我见过不少。代码逻辑还没开始,数据库还没连,接口还没调,程序先死在变量名上。Python 里这些变量名、函数名、类名、模块名,其实都有一个共同名字:标识符。

标识符就是你给代码里的东西起的名字。

比如:

user_name = "tom"
order_total = 199
defclean_phone(phone):
return phone.strip()

这里的 user_name、order_total、clean_phone 都是标识符。

Python 对标识符不是完全放开的,最基本的规则就几条,但真写业务代码时,坑基本也都在这几条里面。

第一个规则,标识符只能由字母、数字、下划线组成。

user_name = "tom"
user2 = "jerry"
_order_id = "A10086"

这些都没问题。

但下面这种,一眼就不对:

user-name = "tom"
order.total = 199
user age = 18

user-name 在 Python 看来不是一个变量名,它会被拆成 user - name。中间那个 - 是减号。

user age 更不用说,中间有空格,解释器直接不认。

我一般看新人代码,发现变量里混了 -,基本不用往下看,先让他把命名改了。

第二个规则,不能以数字开头。

user1 = "tom"
name2026 = "order"

可以。

但这个不行:

1user = "tom"
2026_order = "A001"

数字可以放后面,不能放前面。

这不是 Python 小气,是解释器没法判断你到底想写数字,还是想写名字。2026_order 这种写法,人看着像变量,解释器看着像一坨非法数字。

第三个规则,大小写敏感。

这个地方挺容易埋雷。

user_name = "tom"
User_Name = "jerry"

print(user_name)
print(User_Name)

这两个不是同一个变量。

Python 不会替你“猜一下是不是手滑”。你写 userId,后面又写 userid,它就当两个名字看。

线上代码里这种问题不一定马上报错,尤其是变量在不同分支里赋值的时候,排起来还挺烦。

比如:

defbuild_user_payload(row):
    user_id = row.get("user_id")

if row.get("vip"):
        userId = f"VIP-{user_id}"

return {
"user_id": user_id,
"trace": userId
    }

这段代码看着像那么回事,但只要 vip 不成立,userId 根本没创建。

报错:

UnboundLocalError: cannot access local variable 'userId'

这个锅不是 if 的,是命名不统一埋的。

第四个规则,不能使用 Python 关键字。

关键字就是 Python 语法自己要用的词,比如 if、for、class、def、return。

你不能拿它们当变量名。

class = "vip"
for = 10
return = "ok"

这些都会出问题。

不确定是不是关键字,可以现场查一下:

import keyword

names = ["class", "user_class", "for", "order_id", "return"]

for name in names:
    print(name, keyword.iskeyword(name))

输出大概是这样:

classTrue
user_classFalse
forTrue
order_idFalse
returnTrue

我自己写字段清洗脚本时,经常会遇到这种问题。比如从 Excel 或数据库里读出来一个字段,字段名刚好叫 class,直接拿来做变量名肯定不合适。

一般我会这样处理:

import keyword

defsafe_field_name(raw_name):
    name = raw_name.strip().lower().replace("-", "_").replace(" ", "_")

if name and name[0].isdigit():
        name = f"f_{name}"

if keyword.iskeyword(name):
        name = f"{name}_field"

return name

columns = ["User Name", "class", "2026-order", "phone-number"]

for col in columns:
    print(col, "=>", safe_field_name(col))

这段代码不是为了炫技,就是很普通的字段兜底。

输出类似:

User Name => user_name
class => class_field
2026-order => f_2026_order
phone-number => phone_number

这比手工一个个改靠谱,尤其是导入脚本、报表脚本、批量同步脚本里,字段名一多,靠眼睛看迟早漏。

再说一个很多人会问的点:中文能不能做标识符?

可以。

用户名 = "tom"
订单金额 = 199

print(用户名, 订单金额)

Python 3 是支持 Unicode 标识符的,所以中文变量名能跑。

但我不建议在项目代码里这么干。

不是不能跑,是协作成本高。日志里、接口字段里、数据库字段里、代码审查里,中英文混着来,后面排问题会很别扭。脚本自己临时用一下可以,进项目仓库我一般会拦。

命名规则之外,还有命名习惯。

Python 里变量名和函数名一般用小写加下划线:

user_name = "tom"
order_amount = 199

defparse_order_line(line):
return line.split(",")

类名一般用大驼峰:

classOrderImporter:
pass

classUserProfile:
pass

常量一般用全大写:

MAX_RETRY_TIMES = 3
DEFAULT_TIMEOUT = 5

这些不是解释器强制的,但团队代码里最好别乱来。

比如你写:

defParseOrderLine(LineText):
pass

能跑。

但放到 Python 项目里就很扎眼,像从 Java 或 C# 那边直接搬过来的。不是说不能这么写,而是后面别人维护的时候,会觉得这个代码不太像一个 Python 项目里的代码。

还有一种名字,看见要小心:前后双下划线。

__name__
__init__
__file__

这种名字在 Python 里通常有特殊含义。

自己业务代码里别随便造这种:

__order_status__ = "paid"

能跑,但没必要。容易让人误会这是 Python 或框架约定的魔法变量。

单下划线开头倒是常见:

_cache_data = {}

它一般表示“内部使用”,不是强制私有,只是一种约定。别人看到 _cache_data,就知道这玩意最好别在外面乱调。

最后可以用一小段代码,把标识符规则压一下:

import keyword

defcheck_identifier(name):
ifnot name:
returnFalse, "空字符串不行"

ifnot name.isidentifier():
returnFalse, "格式不符合标识符规则"

if keyword.iskeyword(name):
returnFalse, "撞上 Python 关键字了"

returnTrue, "可以用"

test_names = [
"user_name",
"2_user",
"order-id",
"class",
"_temp",
"订单金额"
]

for item in test_names:
    ok, reason = check_identifier(item)
    print(f"{item:10} -> {ok}, {reason}")

这里我会优先用 isidentifier(),别自己写一大坨正则。正则很容易漏 Unicode、下划线、关键字这些细节。

Python 标识符的规矩不复杂:字母、数字、下划线;数字不能开头;不能是关键字;大小写敏感。

真正麻烦的不是记不住规则,而是项目里命名一会儿 userId,一会儿 user_id,一会儿 userid。这种代码短期能跑,长期一定会恶心自己。

名字先起稳,后面少查一半低级问题。