ChatGPT解决这个技术问题 Extra ChatGPT

为什么在python中通过字符串声明unicode?

我还在学习python,我有一个疑问:

在 python 2.6.x 中,我通常像这样在文件头中声明编码(如 PEP 0263

# -*- coding: utf-8 -*-

之后,我的字符串照常编写:

a = "A normal string without declared Unicode"

但是每次我看到一个python项目代码时,编码都没有在标题中声明。相反,它是在每个字符串中声明的,如下所示:

a = u"A string with declared Unicode"

有什么不同?这样做的目的是什么?我知道 Python 2.6.x 默认设置 ASCII 编码,但它可以被标头声明覆盖,那么每个字符串声明的意义何在?

附录:似乎我把文件编码和字符串编码混在一起了。感谢您解释它:)

# coding: utf8 已经足够好了,不需要 -*-
@jellyfish 我假设您打算输入 # coding: utf-8
应该是#coding=utf-8python.org/dev/peps/pep-0263

C
Chris B.

正如其他人所提到的,这是两件不同的事情。

当您指定 # -*- coding: utf-8 -*- 时,您是在告诉 Python 您保存的源文件是 utf-8。 Python 2 的默认值是 ASCII(对于 Python 3,它是 utf-8)。这只会影响解释器如何读取文件中的字符。

一般来说,无论编码是什么,将高 unicode 字符嵌入到文件中可能不是最好的主意;您可以使用字符串 unicode 转义,它适用于任何一种编码。

当您声明一个前面带有 u 的字符串时,例如 u'This is a string',它会告诉 Python 编译器该字符串是 Unicode,而不是字节。这主要由解释器透明地处理;最明显的区别是您现在可以在字符串中嵌入 unicode 字符(即 u'\u2665' 现在是合法的)。您可以使用 from __future__ import unicode_literals 将其设为默认值。

这仅适用于 Python 2;在 Python 3 中默认为 Unicode,您需要在前面指定一个 b(如 b'These are bytes',以声明一个字节序列)。


感谢您的解释!我将其设置为已接受,因为它是最完整的一个:)
Python 2 的默认源编码是 ascii。
将高 unicode 字符嵌入到文件中实际上是一个好主意。我怀疑非英语使用者想在他们的字符串中阅读 unicode 转义符。
@Mark:感谢 ASCII 更正;我快速浏览了 PEP (python.org/dev/peps/pep-0263),它在序言中谈到了 Latin-1。在大多数情况下,我认为在文件中嵌入高 unicode 字符并不是一个好主意。当然,如果您在源文件中编写大量非英语字符串,它会变得更容易,但您通常这样做是为了向用户显示,并且您可能应该在单独的地方定义这些字符串。一个配置错误的文本编辑器可能会损坏所有这些字符。
如果您正在编写 i18nalized 应用程序,则同意,但请考虑您是中国还是法国程序员。不仅仅是字符串,还有注释。 Python 在源编码方面非常灵活,这很棒。 Python 3 甚至可以在变量名中包含非 ASCII 字符。
M
Mark Tolonen

正如其他人所说,# coding: 指定保存源文件的编码。以下是一些示例来说明这一点:

保存在磁盘上的文件为 cp437(我的控制台编码),但未声明编码

b = 'über'
u = u'über'
print b,repr(b)
print u,repr(u)

输出:

  File "C:\ex.py", line 1
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html for details

添加了 # coding: cp437 的文件输出:

über '\x81ber'
über u'\xfcber'

起初,Python 不知道编码并抱怨非 ASCII 字符。一旦它知道编码,字节字符串就会得到实际在磁盘上的字节。对于 Unicode 字符串,Python 读取 \x81,知道在 cp437 中是 ü,并将其解码为 ü 的 Unicode 代码点,即 U+00FC。打印字节字符串时,Python 直接将十六进制值 81 发送到控制台。打印 Unicode 字符串时,Python 正确检测到我的控制台编码为 cp437,并将 Unicode ü 转换为 ü 的 cp437 值。

以 UTF-8 声明和保存的文件会发生以下情况:

├╝ber '\xc3\xbcber'
über u'\xfcber'

在 UTF-8 中,ü 被编码为十六进制字节 C3 BC,因此字节字符串包含这些字节,但 Unicode 字符串与第一个示例相同。 Python 读取这两个字节并正确解码。 Python 错误地打印了字节字符串,因为它将代表 ü 的两个 UTF-8 字节直接发送到我的 cp437 控制台。

此处文件声明为 cp437,但以 UTF-8 保存:

├╝ber '\xc3\xbcber'
├╝ber u'\u251c\u255dber'

字节字符串仍然获得磁盘上的字节(UTF-8 十六进制字节 C3 BC),但将它们解释为两个 cp437 字符而不是单个 UTF-8 编码字符。这两个字符被转换为 Unicode 代码点,并且所有内容都打印不正确。


i
icktoofay

这并没有设置字符串的格式;它设置文件的格式。即使使用该标头,"hello" 也是字节字符串,而不是 Unicode 字符串。要使其成为 Unicode,您将不得不在任何地方使用 u"hello"。标头只是提示在读取 .py 文件时使用什么格式。


当时我错了,我以为他们是一样的。那么unicode字符串的用途是i18n吗?
@Oscar:是的,在大多数情况下。如果您正在使用 Django 或其他东西制作网站,并且它必须处理使用非 ASCII 字符的人,那么这是另一种可能的用途。
V
Vadim Kotov

标头定义是定义代码本身的编码,而不是运行时生成的字符串。

在没有 utf-8 标头定义的 python 脚本中放置像 2 这样的非 ascii 字符将引发警告

https://i.stack.imgur.com/Lr2qC.jpg


t
tecnobillo

我制作了以下名为 unicoder 的模块,以便能够对变量进行转换:

import sys
import os

def ustr(string):

    string = 'u"%s"'%string

    with open('_unicoder.py', 'w') as script:

        script.write('# -*- coding: utf-8 -*-\n')
        script.write('_ustr = %s'%string)

    import _unicoder
    value = _unicoder._ustr

    del _unicoder
    del sys.modules['_unicoder']

    os.system('del _unicoder.py')
    os.system('del _unicoder.pyc')

    return value

然后在您的程序中,您可以执行以下操作:

# -*- coding: utf-8 -*-

from unicoder import ustr

txt = 'Hello, Unicode World'
txt = ustr(txt)

print type(txt) # <type 'unicode'>