我读到了包装器函数,它将cmp样式比较转换为Python 3中的键样式比较,其中删除了cmp功能.
我有一点时间围绕Python3直键样式sorted()函数的方式,至少据我所知,只有一个为键指定的项目,可以让你正确比较,例如,两个IP用于订购.或火腿电话.
而对于cmp,它没有任何东西:sorted()和sort()用两个ips调用你,你查看了相应的部分,完成了你的决定.
def ipCompare(dqA,dqB):
...
ipList = sorted(ipList,cmp=ipCompare)
Run Code Online (Sandbox Code Playgroud)
火腿无线电呼叫也是如此.排序不是字母; 电话通常是字母+数字+字母; 第一个排序优先级是数字部分,然后是第一个字母,然后是最后一个字母(s.)
使用cmp ......没有汗水.
def callCompare(callA,callB):
...
hamlist = sorted(hamlist,cmp=callCompare)
Run Code Online (Sandbox Code Playgroud)
使用Python3 ...没有经过包装器的箍跳......并且通过了一个项目......我想......怎么能这样做?
如果绝对需要包装器...那么为什么首先在Python3中删除cmp?
我确定我错过了什么.我只是看不到它.:/
好的,现在我知道我错过了什么.解决方案IPs在下面的答案中给出.这是我提出的用于排序公共前缀,区域,后缀形式的火焰调用的密钥:
import re
def callKey(txtCall):
l = re.split('([0-9]*)',txtCall.upper(),1)
return l[1],l[0],l[2]
hamList = ['N4EJI','W1AW','AA7AS','na1a']
sortedHamList = sorted(hamList,key=callKey)
Run Code Online (Sandbox Code Playgroud)
sortedHamList 结果是 ['na1a','W1AW','N4EJI','AA7AS']
详情:
AA7AS出来的callKey()作为7,AA,ASN4EJI出来的callKey()作为4,N,EJIW1AW出来的callKey()作为1,W,AWna1a出来的callKey()作为1,NA,A首先,如果你还没有读过Sorting HOWTO,那一定要读一下; 它解释了很多一开始可能并不明显的事情.
对于您的第一个示例,两个IPv4地址,答案非常简单.
要比较两个地址,一个显而易见的事情是将它们从点四个字符串转换为4个整数的元组,然后只比较元组:
def cmp_ip(ip1, ip2):
ip1 = map(int, ip1.split('.'))
ip2 = map(int, ip2.split('.'))
return cmp(ip1, ip2)
Run Code Online (Sandbox Code Playgroud)
更好的做法是将它们转换为某种代表IP地址并具有比较运算符的对象.在3.4+中,stdlib内置了这样的对象; 让我们假装2.7也做了:
def cmp_ip(ip1, ip2):
return cmp(ipaddress.ip_address(ip1), ipaddress.ip_address(ip2))
Run Code Online (Sandbox Code Playgroud)
很明显,这些作为关键功能更容易:
def key_ip(ip):
return map(int, ip.split('.'))
def key_ip(ip):
return ipaddress.ip_address(ip)
Run Code Online (Sandbox Code Playgroud)
对于你的第二个例子,火腿无线电呼号:为了写一个cmp功能,你必须能够将每个火腿地址分成字母,数字,字母部分,然后比较数字,然后比较第一个字母,然后比较第二个字母字母.为了编写一个key函数,你必须能够将一个火腿地址分解成字母,数字,字母部分,然后返回一个元组(数字,第一个字母,第二个字母).关键功能实际上更容易,而不是更难.
实际上,大多数人都能想到的例子就是这种情况.最复杂的比较最终归结为复杂的部分序列转换,然后是该序列的简单词典比较.
这就是为什么cmp函数在2.4中被弃用并最终在3.0中删除的原因.
当然,在某些情况下,cmp功能更容易阅读 - 人们试图提出的大多数示例都是错误的,但也有一些.而且还有代码已经工作了20年,没有人想以新的方式重新考虑它,没有任何好处.对于那些情况,你已经有了cmp_to_key.
实际上还有另一个原因cmp被弃用了,除此之外,可能还有三分之一.
在Python 2.3中,类型有一个__cmp__方法,用于处理所有运算符.在2.4中,他们长大了六种方法__lt__,__eq__等作为替代.这样可以提供更大的灵活性 - 例如,您可以拥有非全部订购的类型.所以,2.3比较时a < b,它实际上正在做a.__cmp__(b) < 0,它以一种非常明显的方式映射到一个cmp参数.但是在2.4+ a < b中a.__lt__(b),确实没有.多年来,这让很多人感到困惑,并且删除这两者__cmp__以及cmp排序函数的参数消除了这种混乱.
同时,如果您阅读排序HOWTO,您会注意到在我们开始之前cmp,做这种事情的唯一方法是decorate-sort-undecorate(DSU).请注意,如何将一个好的key函数映射到一个好的DSU排序,反之亦然,这显然是显而易见的,但对于一个cmp函数来说,它绝对不是很明显.我不记得有人在py3k列表中明确提到过这个,但我怀疑在决定是否最终杀死时,人们可能已经有了这个cmp.