在Python 2.5中重写reversed(...)

0 投票
2 回答
974 浏览
提问于 2025-04-16 05:35

我需要为我的类写一个自定义的 __reverse__ 函数,因为我在 App Engine 上部署它,所以必须支持 Python 2.5。请问有没有什么 __future__ 的导入或者其他解决办法可以用?

我不能通过继承 list 来实现,因为我需要我的类是 dict 的子类。

编辑:

使用 OrderedDict 也解决不了问题,因为 dict 的键和 list 的项并不相同。

我想创建的对象是这样的:

  1. 我的对象需要提供和 list 一样的属性,也就是说要支持 iter(obj)reverse(obj)

  2. 这些元素必须是一个特殊第三方类的实例。

  3. 每个元素都要和一个键关联。

  4. 在内部,需要通过这些键来访问这些对象。这就是我想把它们放在一个映射中的原因。

我已经把我的实现修改为 list 的子类,而不是 dict 的子类,所以现在我有了以下内容:

class Foo(list):

   pat = {}

   def __init__(self):
       for app in APPS:  # these are strings
           obj = SpecialClass(app)
           self.append(obj)
           self.pat[app] = obj

   def __getitem__(self, item):

       # Use object as a list
       if isinstance(item, int):
           return super(Foo, self).__getitem__(item)

       # Use object as a dict
       if item not in self.pat:
           # Never raise a KeyError
           self.pat[item] = SpecialClass(None)
       return self.pat[item]

   def __setitem__(self, item, value):
       if isinstance(item, int):
           return self.pat.__setitem__(item, value)
       return super(Foo).__setitem__(item, value)

编辑 2:

现在我的类是 list 的子类,我的问题解决了。

2 个回答

1

从2.6版本开始,你可以创建一个自定义的 __reversed__ 方法,这样就能让 reversed 函数正常工作。但在2.5版本及以下,你不能这样做。不过,你可以通过实现序列协议来让你的自定义类也能和 reversed 一起使用。序列协议就是你需要实现两个方法:__len____getitem__

另外一种方法是用一个自定义的函数来替代内置的 reversed 函数,这样可以让你的自定义类有不同的处理方式。可以这样做:

originalReversed = reversed
def myReversed ( seq ):
    if isinstance( seq, MyCustomClass ):
        # do something special
    else:
        return originalReversed( seq )
reversed = myReversed

不过,我不太推荐这种做法,因为这会改变内置函数的正常行为,可能会让其他用户感到困惑。所以,最好还是实现序列协议,这样 reversed 就能正常工作了。

2

在2.5版本中,__reversed__这个功能是不支持的。所以如果你真的需要自定义你集合的反向顺序,你唯一的办法就是修改你调用reversed的地方,换成其他的方法。

不过我很好奇:如果你是在子类化dict(字典),那么字典里的项目顺序本来就是随意的,那在这种情况下,反向(reversed)又是什么意思呢?

撰写回答