Python 能直接用 unicode 字符声明一个 str(byte)变量,为什么还要 unicode type?

2017-08-17 14:08:24 +08:00
 rebeccaMyKid

前几天看了那篇讲 unicode pain 的文章,感觉很理解了,unicode sandwish:要输出的时候转 bytes,程序里统一用 unicode。

但今天码作的时候写着写着突然发现我可以用中文声明一个变量,然后输出到文件

zhongwen = ['中文','你好']
with open('test.txt','w') as f:
	f.writelines(zhongwen)

那干嘛还要 unicode 或者说 unicdoe type 这个东西?通篇用字节类型不就行了? 字符串操作, str(py2), bytes(py3)一样都能 strip()。

请打脸,大脸必重谢。(严肃脸)

2358 次点击
所在节点    问与答
20 条回复
yksoft1
2017-08-17 14:13:17 +08:00
问题是 python 默认的字符串内码和平台有关,和系统有关。
ysc3839
2017-08-17 14:16:53 +08:00
是可以不要 Unicode,Unicode 实际上也是一堆 bytes,弄这个只是为了方便处理。
rebeccaMyKid
2017-08-17 14:23:58 +08:00
@yksoft1 这么讲太高深了。。。完全没概念
rebeccaMyKid
2017-08-17 14:26:51 +08:00
@ysc3839 对啊, 不知道其他语言是怎么样处理的。我能想到一点的就是,在做字符串操作的时候,可能需要这 unicode 或者说 str(py3)这种类型,比如说 a = u'中文', a[0] == u'中',但 b = '中文', b[0] 这个就是 code points 了。除此之外想不到其他的,这里面的细节我也是很清楚,就是觉得有点迷。
glasslion
2017-08-17 14:27:36 +08:00
字节是和编码相关的, 用户有不一定都是 utf-8 编码
rebeccaMyKid
2017-08-17 14:27:39 +08:00
打错:这里面的细节我也不是很清楚
ysc3839
2017-08-17 14:29:09 +08:00
@ysc3839 至于方便在哪,大概是不用考虑多字节的问题吧,比如 UTF-16 一个字符一般是两个字节,自己处理的话就不能直接一个个来读取了,得读取两个。
另外在调用一些函数的时候,如果直接传 Unicode,那函数就可以根据系统来直接编码成对应的 bytes。如果传 bytes 进去的话,还得指定是什么编码,函数内部再转换。
ysc3839
2017-08-17 14:31:30 +08:00
@rebeccaMyKid 其他语言的话,C++ 有 UTF-16 UTF-32 对应的类型。还有个平台相关的 wchar_t ( Windows 下是 UTF-16,*nix 下是 UTF-32 )。
BOYPT
2017-08-17 14:32:19 +08:00
主要问题是你的源码文件也是有编码的,utf8 的源码文件还是 GBK 的?这处理起来就不一样了。
最终都还是要理解透编码。
rebeccaMyKid
2017-08-17 14:42:49 +08:00
@BOYPT 哇,小白 dig 不下去了呀。说得太简略了
BOYPT
2017-08-17 15:01:01 +08:00
@rebeccaMyKid #10 编码问题,归结下来有这几个地方需要注意:

输入编码 - 处理过程 - 输出编码 - 显示编码


输入编码是指,你获取的信息来源,比如从数据库里、文件里、网页里、源文件里,获取的是输入的数据,要让程序正确低读取出这些数据; python3 里,"中文"和 u"中文"是等价的,而.py 文件如无意外是 utf-8 编码的,这时候就是一个隐式的 utf-8 到 unicode 的转换了。如果文件编码不是 utf-8,是需要在源码前写#coding: GBK 这样的声名,说这个文件是 GBK 编码的; python2 时候,如果没声名 utf-8,,在源码里写中文是会报错的,因为默认了 ascii 编码而已。

处理过程,在 python 里的话用 Unicode 串最方便了,因为方便后续处理;其他语言有些是没有宽字节类型的比如 php,就用 utf-8。

输出编码,一般需要根据你输出的地方,把处理过程中的字符处理成合适的编码;这一点在 python 里很多时候是隐式处理的,意思就是,直接给输出接口喂 Unicode 的东西,自动封装来编码过程;例子就是,print(u'中文')跟 print("中文".encode('utf-8'))其实是两个处理方式了。

显示编码,根据使用环境,不一定是 python 的问题;比如 python 输出 web 页面,需要设置 HTTP Header 声名编码、Html META 声名,然后浏览器才能正确解释出内容,否则也是乱码。极端例子是在 windows 的命令符使用 python,直接 print(u'中文') 会出现 unicode 无法显示的问题,因为,中文 Windows 的终端是 GBK 的,print()输出时候没法编码正确。


其实所有语言处理编码都是这几个关键点。
SuperMild
2017-08-17 15:01:23 +08:00
假设你在 win 下用该代码写文件,系统默认 gbk 编码,后来在 linux 上读取该文件,系统默认 utf8,读取失败!
wwqgtxx
2017-08-17 15:02:04 +08:00
说到底,utf8 并不是唯一的编码格式,而 bytes 保存的并不一定就是 utf8 编码的数据,也有可能是 utf16,utf32 等等,比如 u"aaa".encode("utf16be")你试试输出什么结果
rebeccaMyKid
2017-08-17 15:33:12 +08:00
编码的问题我懂。。但我没看懂编码的问题跟我这个问题有什么联系。。我还是觉得
@ysc3839 跟我想的差不多。
另外我也在 stackoverflow 上提了这问题,觉得答案也是跟我想的差不多,https://stackoverflow.com/questions/45728178/why-do-python-need-unicode-type-since-i-can-declare-a-variable-directly-with-any/45728222#45728222,结题吧,谢谢各位。
wzha2008
2017-08-17 15:33:16 +08:00
我就举一个例子:
>> print len('啊')
>> 3

>> print len(u'啊')
>> 1
rebeccaMyKid
2017-08-17 15:40:02 +08:00
我觉得里面有句话说得很有意思,就是“ Text is text and bytes are bytes.”。我理解这句话是说,其实都是字节,但 text 是从 bytes 抽象出来的给人看的东西,len(字节) 跟 len(字符),后者这种对于字符的操作,才对我们( human )使用者有意义,我猜这是这种类型存在的理由(之一?)。

(如果全世界的字符都能只用一个 byte 编码,可能就不需要这种类型了?)。

已经学到东西拉,不 dig 了,谢谢各位 :D
rebeccaMyKid
2017-08-17 15:41:10 +08:00
@wzha2008
哈哈哈,对对对,我就是这么想的。只是 po 出来想问问还有其他什么原因没:D
rebeccaMyKid
2017-08-17 15:56:16 +08:00
@BOYPT 这个看懂了,谢谢老哥。
ysc3839
2017-08-17 17:31:21 +08:00
@BOYPT 关于 Windows 的 Console,系统有提供 Unicode(UTF-16) 编码的 API。用这个 API 输出的话就会自动转换为 Console 对应的编码。
BOYPT
2017-08-18 00:07:11 +08:00
@ysc3839 #19 嗯嗯。。。其实在 cmd 运行 python 前用 chcp 65001 切换一下就能让 cmd 显示 utf-8... 所以说显示编码是外部环境的问题,不一定是 python 能解决的……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/383655

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX