说起来,这“★”符号,看着挺简单的对吧?一颗小星星,亮亮的。结果真要在代码里用它,尤其在 Python 里,有时候就不是那么顺滑的事儿了。我第一次想打印这玩意儿,还是想做个简陋的命令行评分显示来着,比如五颗星代表满分。想着多简单啊,print("★★★★★")
,结果,哎哟喂,命令行里跑出来一堆问号,或者干脆报错!当时就有点蒙,这不就是个字符嘛,咋就不行了?
其实啊,这背后牵扯到一点点“字符”是怎么被电脑,被 Python 理解的那些事儿。你眼睛看到的“★”,在电脑内部可不是直接存个形状的。它其实是个数字!没错,就是个编号。全球有个叫 Unicode 的组织,就像个巨大的图书馆,给世界上几乎所有的文字、符号都编了个独一无二的号。这颗“★”,它的编号就是U+2605。
所以,最最直接了当,也是通常情况下应该好使的办法,就是你键盘上能直接敲出来,或者能通过输入法选出来,然后把它原原本本地塞到你的字符串里。就像这样:
python
my_star = "★"
print(my_star)
print("我很喜欢这颗星:", my_star)
绝大多数现代的编辑器、终端、以及新版本的 Python (Python 3 系列基本都是) 都默认用的是 UTF-8 这种编码。UTF-8 呢,它是个很牛的编码方式,能表示 Unicode 里的绝大部分字符,包括我们这颗“★”。所以,如果你的源文件是 UTF-8 编码保存的,你的终端也支持 UTF-8 显示,那 print("★")
多半是没问题的,直接就出来了。这是最理想的情况,简单,直观。
但是,就像我前面说的,有时候就是会遇到问题。为啥呢?最常见的就是编码不匹配。你的Python源文件,它保存的时候用的不是 UTF-8,比如用了个老的、只支持英文或者少数语言的编码(比如GBK什么的,国内以前挺常见的)。或者,你的终端,就是那个黑乎乎(或者白乎乎)显示程序输出的窗口,它不支持 UTF-8,或者它当前设置的编码跟你的程序输出编码对不上。
想想看,程序心里想着“我要打出那个编号是 U+2605 的东西”,结果终端那边说“我只认识 GBK 编码,你说的那个号,我不知道怎么画出来”,或者更糟,终端觉得你发过来的是一堆乱码,就给你显示个问号或者方块。
为了避免这种“鸡同鸭讲”的尴尬,有时候我们可以明确告诉 Python,我们要的就是那个 Unicode 编号对应的字符。有两种常用姿势。
第一种,用 Unicode 转义序列。在字符串前面加个 u
(虽然Python 3 里字符串默认就是 Unicode 了,但写不写都行,写了有时候能提醒自己这是处理 Unicode),然后用 \u
跟着字符的16进制编号。记住,\u
后面跟4个16进制数字,如果编号超过四个16进制数(比如emoji很多都是),就得用 \U
后面跟8个16进制数字。我们的“★”是 U+2605,它在 \u
能搞定的范围里。所以,你可以这么写:
python
star_unicode_escape = "\u2605"
print("用\\u表示的星:", star_unicode_escape)
看吧,\u2605
,这就是明确告诉 Python,我要的就是 Unicode 编码是 2605(16进制)的那个字符。这招的好处是,它不依赖于你的源文件编码,只要 Python 解释器能理解 Unicode 转义序列就行(当然,Python 3 肯定行),而且输出的终端支持显示这个字符,它就能出来。
第二种,更“程序化”一点,用 chr()
函数。chr()
函数接受一个表示 Unicode 码点的整数,然后返回对应的字符。这个整数可以是十进制的,也可以是十六进制的(用 0x
前缀)。“★”的 Unicode 码点是 2605(16进制),换算成十进制是 9733。所以,你可以这么干:
“`python
star_decimal = chr(9733) # 9733 是 2605 转十进制
star_hex = chr(0x2605) # 0x2605 就是 2605 的十六进制写法
print(“用chr(9733)得到的星:”, star_decimal)
print(“用chr(0x2605)得到的星:”, star_hex)
``
\u
这种方式,本质上和用转义序列差不多,都是直接通过 **Unicode** 码点来指定字符。有时候,如果你是从一个列表或者数据结构里获取到一堆字符的 **Unicode** 编号,用
chr()` 就特别方便,可以批量生成字符。
那么问题来了,啥时候用哪种呢?
最直接的当然是第一种,直接粘贴字符。如果你的开发环境和运行环境都是统一的、现代的 UTF-8 环境,这通常是最佳实践,因为代码看起来最直观,“所见即所得”。你写的是啥,程序里就是啥。
但如果你经常需要在不同系统、不同终端、或者那些老旧的环境下运行代码,或者你的源文件编码历史遗留问题比较多,那么使用 \u
转义序列或者 chr()
函数会更保险。它们跳过了源文件编码的可能陷阱,直接跟 Unicode 码点打交道。这就像是你不说本地话,直接说国际通用语言( Unicode )一样,不容易产生误解。
我还遇到过一个比较刁钻的情况,就是把带有特殊字符的字符串写到文件里。这时候除了程序内部的字符串表示,还要考虑文件本身的编码。如果你直接 open("output.txt", "w")
然后往里写,如果文件编码不对,读出来可能还是乱码。正确的姿势是,明确指定文件的打开模式和编码,比如 open("output.txt", "w", encoding="utf-8")
。这样,Python 就会确保你写入的字符串以 UTF-8 的方式存到文件里,以后再用 UTF-8 读出来,就还是那颗闪亮的“★”了。
“`python
写入文件
with open(“stars.txt”, “w”, encoding=”utf-8″) as f:
f.write(“评分:”)
f.write(“★★★★☆”) # 五颗星加一个半星(☆是U+2606)
f.write(“\n”)
f.write(“又一颗星:”)
f.write(chr(0x2605))
读出文件
with open(“stars.txt”, “r”, encoding=”utf-8″) as f:
content = f.read()
print(“从文件读出的内容:”)
print(content)
“`
你看,处理文本、处理字符,尤其是非 ASCII 字符,比如中文,比如各种符号(“★”只是其中一个),归根结底就是个 编码 问题。理解了 Unicode 是字符的“身份证号”,UTF-8 是把这些身份证号“包装”起来方便传输和存储的一种方法,很多看似奇怪的乱码问题就迎刃而解了。
所以,下次你在 Python 里想用那颗“★”,或者别的什么奇奇怪怪的符号,记住这几招:
1. 最简单的:直接复制粘贴到字符串里(前提是你的环境支持 UTF-8)。
2. 更稳妥的:用 Unicode 转义 \u2605
或 \U...
。
3. 编程化的:用 chr(9733)
或 chr(0x2605)
。
4. 别忘了文件操作时指定 encoding="utf-8"
。
总的来说,在现代 Python 开发里,绝大多数时候直接敲或者粘贴那颗“★”进去就行,因为 UTF-8 是王道。但要是碰壁了,别慌,想想是不是编码出了问题,再试试 Unicode 转义或者 chr()
,多半都能解决。这就像是编程世界里处理国际化和本地化遇到的冰山一角,搞定了这个小小的“★”,以后遇到别的特殊字符,甚至是那些花里胡哨的 emoji 🤩,你也知道从哪下手了。就是这么回事儿,没那么玄乎。
评论(0)