为啥 Python 不能理解单词形式的整数?

Posted

技术标签:

【中文标题】为啥 Python 不能理解单词形式的整数?【英文标题】:Why can't Python understand integers in word form?为什么 Python 不能理解单词形式的整数? 【发布时间】:2016-07-12 00:43:34 【问题描述】:

我无法在任何地方找到我的问题的答案,而且我对 Python 还是很陌生。这个问题的目的主要是了解 Python 的工作原理以及它的限制。 This answer 提供了一个模块,可以将数字从整数转换为整数的单词形式。但是,如果我想运行这样的代码,而没有任何与链接中的模块以相反方式工作的模块,

a = "five"
b = 2
if b < a:
    print("a is higher than b")

我收到了TypeError: unorderable types: int() &lt; str()

那么,为什么 Python 不能将此字符串识别为单词形式的数字呢?是不是类似于“尚未构建 Python 来识别数字的单词形式”?

【问题讨论】:

是的:“Python 还没有被构建来识别数字的单词形式” The Zen of Python: 特殊情况不足以打破规则。面对模棱两可,拒绝猜测的诱惑。应该有一种——最好只有一种——明显的方法来做到这一点。显式优于隐式。 【参考方案1】:

注意:我使用&gt;&gt;&gt; 来演示实际的python 代码,?-&gt; 来演示一个假设的shell

如何隐式解析有几种可能的场景:

3 < "two"

Python 2 为所有对象定义了一个顺序,以便完全任意对象的列表仍然可以排序,因此所有 str 的计算结果为 more:

 >>> 3 < "two" #this is the actual result in python 2
 True

另一种方法是将数字转换为等效的单词字符串,然后按字母顺序进行比较:

 >>> "three" < "two"
 True

第三种方法是尝试将字符串解析为一个数字,但由于有很多不同的符号和语言可以写入数字,因此几乎不可能每次都得到它 (see this question)

可以说我们在python中实现了这个英语

?-> 1 < "two"
True
?-> 1 < "cent" #100 in french
(Traceback)
   ...

这不太好,因为有许多程序员可能不会说英语,并且为每种可能的语言实现一个数字词解析器是非常不可能的,而且如果 1000 &gt; "cent" 在您使用英文单词“cent”。


现在假设我们已经实现了上面提到的英语解析器,并且开发人员决定区分除英语以外的所有语言,字符串之间的比较如何?

如果在 python 中比较字符串的行为没有改变,则会在比较中产生巨大的不一致:

>>> "five" < "three"
True
?-> "three" == 3
True
?-> "five" > 3 == "three"
True
?-> "five" < "three" == 3
True
?-> "ONE" == "one"
False
?-> "one" == 1 == "ONE"
True

或者假设您尝试将两个字符串都转换为数字并将它们作为数字进行比较,那么排序字符串将会中断:

?-> words = "please give me five apples".split()
?-> words.sort()
?-> words
['five', 'apples', 'give', 'me', 'please']

所以基本上任何你看它隐式添加此功能的方式都会完全破坏许多其他完美的功能。


编辑

我很好奇排序实际上是如何工作的,所以我创建了一个真正进行这种比较的类:

from functools import total_ordering

@total_ordering
class number_word:
    key = dict(enumerate(
               ("zero one two three four five six seven eight nine ten".split())
              ))
    key.update(v:k for k,v in key.items())

    def __init__(self,value):
        alt = self.key.get(value,None)
        if isinstance(value,str):
            self.word = value
            self.num = alt

        elif isinstance(value,int):
            self.num = value
            self.word = alt
        else:
            raise TypeError("must be str or int")

    def __repr__(self):
        return "nw(%r)"%self.word

    def __eq__(self,other):
        if not isinstance(other,number_word):
            other = word_number(other)

        if self.num == None == other.num:
            #neither are valid numbers, compare as strings
            return self.word == other.word
        else:
            return self.num == other.num

    def __lt__(self,other):
        if not isinstance(other,number_word):
            other = word_number(other)

        if self.num is None or other.num is None:
            return self.word < other.word
        else:
            return self.num < other.num

所以number_word(2) &lt; number_word("five") 将评估为真,看看字符串的排序:

words = "range(1,6) goes from  one to five".split()
correct = sorted(words)
num_sort = sorted(words,key=number_word)
backward = sorted(words,key=number_word, reverse=True)

print(correct)
print(num_sort)
print(backward[::-1])

理论上这三个应该是相同的,尤其是num_sort == backward[::-1],但结果是这样的:

['five', 'from', 'goes', 'one', 'range(1,6)', 'to']
['from', 'goes', 'one', 'five', 'range(1,6)', 'to']
['one', 'five', 'from', 'goes', 'range(1,6)', 'to']

是的,它确实会破坏字符串排序。

【讨论】:

以上是关于为啥 Python 不能理解单词形式的整数?的主要内容,如果未能解决你的问题,请参考以下文章

python字符串为啥不能用int处理?

为啥我不能在 Angular ngFor 循环中设置我的第一个单词的样式?

linux 为啥不能后台运行

为啥我不能将整数向量推入 C++ 中的二维整数向量?

为啥我不能通过 LeetCode 练习 139?

为啥我不能在c中将字符串转换为int