我正在做这个小小的练习...... 我想基于一些奇怪的字典重新排序字符串。 例如,根据我的字典,字母按顺序排列: “a”,“b”,“d”,“c”,“f”,“e”
所以我想我应该重载<字符串的运算符和调用sorted()
这里是:
class MyString(str):
new_dict = dict((x,i) for i,x in enumerate(["a", "b", "d", "c", "f", "e"]))
def __lt__(self,other):
return self.new_dict[self] < self.new_dict[other]
def __init__(self,x):
str.__init__(self,x)
然后
In [59]: sorted((MyString(x) for x in "abcdef"))
Out[59]: ['a', 'b', 'd', 'c', 'f', 'e']
那真棒。甚至:
In [64]: MyString("".join(sorted((MyString(x) for x in "abcdef"))))
Out[64]: 'abdcfe'
但为什么我不能sorted(MyString("abcdef"))
?
In [70]: sorted(MyString("abcdef"))
Out[70]: ['a', 'b', 'c', 'd', 'e', 'f']
显然,MyString的迭代器正在返回字符串。
In [72]: for i in MyString("abcdef"):
print type(i)
....:
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
<type 'str'>
如果我在MyString上调用join,会发生什么:
In [63]: type(MyString("").join(sorted((MyString(x) for x in "abcdef"))))
Out[63]: str
为什么MyString有str迭代器?
答案 0 :(得分:2)
您需要覆盖此处的__getitem__
method:
class MyString(str):
def __getitem__(self, i):
return type(self)(super(MyString, self).__getitem__(i))
这将返回当前类型的新实例:
>>> for i in MyString("abcdef"):
... print type(i)
...
<class '__main__.MyString'>
<class '__main__.MyString'>
<class '__main__.MyString'>
<class '__main__.MyString'>
<class '__main__.MyString'>
<class '__main__.MyString'>
str
本身不实现迭代(它没有__iter__
menthod,但 实现了序列协议(它有__len__
长度方法和一个__getitem__
方法);这是for
循环最终使用的。)
如果使用Python 3,str
对象 有__iter__
方法,您需要覆盖它:
class MyString(str):
def __iter__(self):
return (type(self)(i) for i in super().__iter__())
请注意str
是一个不可变类型,覆盖__init__
对实例几乎没有影响。
对于订购,您确实需要实施所有__gt__
,__ge__
,__eq__
等方法。使用@functools.total_ordering()
decorator可以节省大部分工作:
from functools import total_ordering
@total_ordering
class MyString(str):
sortmap = {x: i for i, x in enumerate("abdcfe")}
def __lt__(self, other):
return self.sortmap[self] < self.sortmap[other]
# inherit __eq__ from str
def __getitem__(self, i):
return type(self)(super(MyString, self).__getitem__(i))
最后但并非最不重要的是,对于排序,只需在key
使用sorted()
参数:
>>> sortmap = {x: i for i, x in enumerate("abdcfe")}
>>> sorted('abcdef', key=sortmap.get)
['a', 'b', 'd', 'c', 'f', 'e']
答案 1 :(得分:0)
您不需要子类来自定义排序行为 -
您可以将key
参数传递给sort
方法或sorted
调用,指定一个函数
它给出了被比较的每个元素的相对权重。
喜欢在:
def mycomp(文字): myseq =(“abdcfe”) weigthed = [myseq.find(char)for char in text] return weigthed#这将为你的映射字符串中找不到的字符放置-1'
答案 2 :(得分:0)
您确实应该使用key
参数而不是您的方法。它不起作用的原因只是你没有重载__iter__
函数:
class MyString(str):
# ...
def __iter__(self):
for x in super().__iter__():
yield self.__class__(x)
在Python 2中,您可以使用
class MyString(str):
# ...
def __iter__(self):
for x in super(MyString, self).__str__():
yield self.__class__(x)