简体   繁体   English

继承自“str”类

[英]Inheriting from “str” class

I'm doing this little exercise... I want to reorder a string based on some weird dictionary. 我正在做这个小练习...我想根据一些奇怪的字典重新排序一个字符串。 For example, according to my dictionary, the letters come in the order: "a", "b", "d", "c", "f", "e" 例如,根据我的字典,字母按顺序排列:“a”,“b”,“d”,“c”,“f”,“e”

So I figured I should just overload the < operator for strings and call sorted() 所以我想我应该重载字符串的<运算符并调用sorted()

Here goes: 开始:

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)

And then 接着

In [59]: sorted((MyString(x) for x in "abcdef"))
Out[59]: ['a', 'b', 'd', 'c', 'f', 'e']

That's awesome. 棒极了。 Or even: 甚至:

In [64]: MyString("".join(sorted((MyString(x) for x in "abcdef"))))
Out[64]: 'abdcfe'

But why can't I just do sorted(MyString("abcdef")) ? 但为什么我不能做sorted(MyString("abcdef"))

In [70]: sorted(MyString("abcdef"))
Out[70]: ['a', 'b', 'c', 'd', 'e', 'f']

Apparently the iterator of MyString is returning strings. 显然,MyString的迭代器正在返回字符串。

In [72]: for i in MyString("abcdef"):
             print type(i)
      ....:     
      <type 'str'>
      <type 'str'>
      <type 'str'>
      <type 'str'>
      <type 'str'>
      <type 'str'>

What happens if I call join on MyString: 如果我在MyString上调用join,会发生什么:

In [63]: type(MyString("").join(sorted((MyString(x) for x in "abcdef"))))
Out[63]: str

Why does MyString have str iterators? 为什么MyString有str迭代器?

You need to override the __getitem__ method here: 您需要在此处覆盖__getitem__方法

class MyString(str):
    def __getitem__(self, i):
        return type(self)(super(MyString, self).__getitem__(i))

This returns a new instance of the current type: 这将返回当前类型的新实例:

>>> 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 itself doesn't implement iteration (it has no __iter__ menthod , but does implement the sequence protocol (it has both a __len__ length method an a __getitem__ method); it is this that the for loop ultimately uses). str本身不实现迭代(它没有__iter__ menthod ,但确实实现了序列协议(它有__len__长度方法和__getitem__方法);这是for循环最终使用的)。

If using Python 3, the str object does have a __iter__ method and you need to override that instead: 如果使用Python 3, str对象确实有一个__iter__方法,你需要覆盖它:

class MyString(str):
    def __iter__(self):
        return (type(self)(i) for i in super().__iter__())

Note that str is an immutable type, overriding __init__ has little influence on the instance. 请注意, str是一个不可变类型,覆盖__init__对实例几乎没有影响。

For ordering, you really need to implement all of the __gt__ , __ge__ , __eq__ , etc. methods too. 如需订购,你真的需要实现所有的__gt____ge____eq__等方法了。 Use the @functools.total_ordering() decorator to save yourself most of the work here: 使用@functools.total_ordering()装饰器来保存自己的大部分工作:

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))

Last but not least, for sorting, just use the key argument to sorted() here: 最后但并非最不重要的是,对于排序,只需在此处使用key参数来sorted()

>>> sortmap = {x: i for i, x in enumerate("abdcfe")}
>>> sorted('abcdef', key=sortmap.get)
['a', 'b', 'd', 'c', 'f', 'e']

You don need a subclass for customizing sort behavior - you can pass a key parameter to a sort method or sorted call, specifying a function that gives the relative weights of each element being compared. 您不需要用于自定义排序行为的子类 - 您可以将key参数传递给sort方法或sorted调用,指定一个函数,该函数提供要比较的每个元素的相对权重。

Like in: 像:

def mycomp(text): myseq = ("abdcfe") weigthed = [myseq.find(char) for char in text] return weigthed # this will place -1's for chars not found in your mapping string def mycomp(text):myseq =(“abdcfe”)weigthed = [myseq.find(char)for char in text] return weigthed#这将为你的映射字符串中找不到的字符放置-1'

You should indeed use the key parameter instead of your approach. 您确实应该使用key参数而不是您的方法。 The reason it is not working however is simply that you didn't overload the __iter__ function: 它不工作的原因只是你没有重载__iter__函数:

class MyString(str):
    # ...
    def __iter__(self):
        for x in super().__iter__():
            yield self.__class__(x)

In Python 2 you can use 在Python 2中,您可以使用

class MyString(str):
    # ...
    def __iter__(self):
        for x in super(MyString, self).__str__():
            yield self.__class__(x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM