V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
rebeccaMyKid
V2EX  ›  问与答

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

  •  
  •   rebeccaMyKid · 2017-08-17 14:08:24 +08:00 · 2411 次点击
    这是一个创建于 2648 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前几天看了那篇讲 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()。

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

    20 条回复    2017-08-18 00:07:11 +08:00
    yksoft1
        1
    yksoft1  
       2017-08-17 14:13:17 +08:00
    问题是 python 默认的字符串内码和平台有关,和系统有关。
    ysc3839
        2
    ysc3839  
       2017-08-17 14:16:53 +08:00 via Android   ❤️ 1
    是可以不要 Unicode,Unicode 实际上也是一堆 bytes,弄这个只是为了方便处理。
    rebeccaMyKid
        3
    rebeccaMyKid  
    OP
       2017-08-17 14:23:58 +08:00
    @yksoft1 这么讲太高深了。。。完全没概念
    rebeccaMyKid
        4
    rebeccaMyKid  
    OP
       2017-08-17 14:26:51 +08:00
    @ysc3839 对啊, 不知道其他语言是怎么样处理的。我能想到一点的就是,在做字符串操作的时候,可能需要这 unicode 或者说 str(py3)这种类型,比如说 a = u'中文', a[0] == u'中',但 b = '中文', b[0] 这个就是 code points 了。除此之外想不到其他的,这里面的细节我也是很清楚,就是觉得有点迷。
    glasslion
        5
    glasslion  
       2017-08-17 14:27:36 +08:00   ❤️ 1
    字节是和编码相关的, 用户有不一定都是 utf-8 编码
    rebeccaMyKid
        6
    rebeccaMyKid  
    OP
       2017-08-17 14:27:39 +08:00
    打错:这里面的细节我也不是很清楚
    ysc3839
        7
    ysc3839  
       2017-08-17 14:29:09 +08:00 via Android   ❤️ 1
    @ysc3839 至于方便在哪,大概是不用考虑多字节的问题吧,比如 UTF-16 一个字符一般是两个字节,自己处理的话就不能直接一个个来读取了,得读取两个。
    另外在调用一些函数的时候,如果直接传 Unicode,那函数就可以根据系统来直接编码成对应的 bytes。如果传 bytes 进去的话,还得指定是什么编码,函数内部再转换。
    ysc3839
        8
    ysc3839  
       2017-08-17 14:31:30 +08:00 via Android
    @rebeccaMyKid 其他语言的话,C++ 有 UTF-16 UTF-32 对应的类型。还有个平台相关的 wchar_t ( Windows 下是 UTF-16,*nix 下是 UTF-32 )。
    BOYPT
        9
    BOYPT  
       2017-08-17 14:32:19 +08:00   ❤️ 1
    主要问题是你的源码文件也是有编码的,utf8 的源码文件还是 GBK 的?这处理起来就不一样了。
    最终都还是要理解透编码。
    rebeccaMyKid
        10
    rebeccaMyKid  
    OP
       2017-08-17 14:42:49 +08:00
    @BOYPT 哇,小白 dig 不下去了呀。说得太简略了
    BOYPT
        11
    BOYPT  
       2017-08-17 15:01:01 +08:00   ❤️ 2
    @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
        12
    SuperMild  
       2017-08-17 15:01:23 +08:00 via iPhone
    假设你在 win 下用该代码写文件,系统默认 gbk 编码,后来在 linux 上读取该文件,系统默认 utf8,读取失败!
    wwqgtxx
        13
    wwqgtxx  
       2017-08-17 15:02:04 +08:00 via iPhone
    说到底,utf8 并不是唯一的编码格式,而 bytes 保存的并不一定就是 utf8 编码的数据,也有可能是 utf16,utf32 等等,比如 u"aaa".encode("utf16be")你试试输出什么结果
    rebeccaMyKid
        14
    rebeccaMyKid  
    OP
       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
        15
    wzha2008  
       2017-08-17 15:33:16 +08:00   ❤️ 1
    我就举一个例子:
    >> print len('啊')
    >> 3

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

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

    已经学到东西拉,不 dig 了,谢谢各位 :D
    rebeccaMyKid
        17
    rebeccaMyKid  
    OP
       2017-08-17 15:41:10 +08:00
    @wzha2008
    哈哈哈,对对对,我就是这么想的。只是 po 出来想问问还有其他什么原因没:D
    rebeccaMyKid
        18
    rebeccaMyKid  
    OP
       2017-08-17 15:56:16 +08:00
    @BOYPT 这个看懂了,谢谢老哥。
    ysc3839
        19
    ysc3839  
       2017-08-17 17:31:21 +08:00 via Android
    @BOYPT 关于 Windows 的 Console,系统有提供 Unicode(UTF-16) 编码的 API。用这个 API 输出的话就会自动转换为 Console 对应的编码。
    BOYPT
        20
    BOYPT  
       2017-08-18 00:07:11 +08:00
    @ysc3839 #19 嗯嗯。。。其实在 cmd 运行 python 前用 chcp 65001 切换一下就能让 cmd 显示 utf-8... 所以说显示编码是外部环境的问题,不一定是 python 能解决的……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2901 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 13:24 · PVG 21:24 · LAX 05:24 · JFK 08:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.