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。这种代码短期能跑,长期一定会恶心自己。
名字先起稳,后面少查一半低级问题。