Python字符串中特殊字符存储不一致

Yun*_*Gun 1 python string unicode-normalization python-3.x python-3.7

版本是Python 3.7。我刚刚发现python有时会将字符ñ存储在具有多种表示形式的字符串中,而我完全不知道为什么或如何处理它。

我不确定显示此问题的最佳方法,所以我将仅显示一些代码输出。

我有两个字符串s1和s2都设置为相等 'Dan Pen?a'

它们都是字符串类型。

我可以运行代码:

print(s1 == s2) # prints false
print(len(s1)) # prints 8
print(len(s2)) # prints 9
print(type(s1)) # print 'str'
print(type(s2)) # print 'str'
for i in range(len(s1)):
    print(s1[i] + ", " + s2[i])
Run Code Online (Sandbox Code Playgroud)

循环的输出为:

D, D
a, a
n, n
 ,  
P, P
e, e
n?, n
a, ~
Run Code Online (Sandbox Code Playgroud)

那么,是否有任何python方法来处理这些不一致问题,或者至少有一些关于python什么时候使用哪种表示形式的规范?

很高兴知道Python为什么会选择以这种方式实现。

编辑:

一个字符串从Django数据库中检索,另一个字符串从解析列表目录调用中的文件名获得的字符串中。

from app.models import Model
from django.core.management.base import BaseCommand

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        load_dir = "load_dir_name"
        save_dir = "save_dir"

        files = listdir(load_dir)
        save_file_map = {file[:file.index("_thumbnail.jpg")]: f"{save_dir}/{file}" for file in files}
        for obj in Model.objects.all():
            s1 = obj.title
            save_file_path = save_file_map[s1] # Key error when encountering ñ.
Run Code Online (Sandbox Code Playgroud)

但是,当我搜索save_file_map字典时,我发现与s1完全相同的键,除了ñ被编码为字符n~而不是character ñ

请注意,我在上述代码中使用list dir加载的文件首先是基于obj.title字段命名的,因此应确保目录中包含该名称的load_dir文件。

Cof*_*sso 6

您将需要规范化字符串以使用相同的表示形式。现在,其中一个正在使用n字符+代字号字符(2个字符),而另一个正在使用单个字符代表代号n。

unicodedata.normalize应该做你想做的。在此处查看文档。

您需要这样称呼:unicodedata.normalize('NFC', s1)'NFC'告诉unicodedata.normalize您要对所有内容使用组合形式,例如的1个字符的版本n?。除了以外'NFC',文档中还提供了其他选项,您可以完全由您使用。

现在,在什么时候进行规范化取决于您(我不知道您的应用程序的结构)。例如,您可以在插入数据库之前进行标准化,或者在每次从数据库读取数据时进行标准化。

  • @YungGun:您正在使用Python 3;str类型是保存Unicode数据的类型。在Python 3中,只有一种文本类型“ str”,可以容纳任何Unicode文本。只有在Python 2中,“ str”(ASCII或特定于区域设置的文本或二进制数据)和“ unicode”(任何文本)才有所区别。 (3认同)
  • @YungGun讨论了为什么有多种方式表示特殊字符(例如n tilde),这是unicode的东西,而不是python的东西。如果我没记错的话,它或多或少是为了与其他编码向后兼容。 (2认同)