rebeccaMyKid
V2EX  ›  问与答

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

  •  
  •   rebeccaMyKid · Aug 17, 2017 · 2841 views
    This topic created in 3225 days ago, the information mentioned may be changed or developed.

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

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

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

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