gpt4 book ai didi

python - Python 2.5 和 2.6 之间的不同实例方法行为

转载 作者:太空狗 更新时间:2023-10-30 03:07:44 27 4
gpt4 key购买 nike

在实例创建后尝试更改实例上的 __unicode__ 方法会在 Python 2.5 和 2.6 上产生不同的结果。

这是一个测试脚本:

class Dummy(object):

def __unicode__(self):
return u'one'

def two(self):
return u'two'

d = Dummy()
print unicode(d)
d.__unicode__ = d.two
print unicode(d)
print d.__unicode__()

在 Python 2.5 上,这会产生

one
two
two

也就是说,改变实例的__unicode__也会改变unicode(instance)

在 Python 2.6 上,这产生

one
one
two

因此,在更改后,unicode(instance)instance.__unicode__() 返回不同的结果。

为什么?我怎样才能让它在 Python 2.6 上运行?

(对于它的值(value),这里的用例是我想为给定类的所有子类在 __unicode__ 的输出中附加一些内容,而不必修改子类的代码。 )

编辑使用例更清晰

我有 A 类,它有很多子类。这些子类定义了简单的 __unicode__ 方法。我想添加逻辑,以便对于 A 类子类的实例,unicode(instance) 得到一些附加到最后的东西。为了保持代码简单,并且因为有很多子类我不想更改,所以我宁愿避免编辑子类代码。

这实际上是适用于 Python 2.5 的现有代码。它是这样的:

class A(object):

def __init__(self):
self._original_unicode = self.__unicode__
self.__unicode__ = self.augmented_unicode

def augmented_unicode(self):
return self._original_unicode() + u' EXTRA'

此代码不再适用于 2.6。关于如何在不修改子类代码的情况下实现这一目标的任何建议? (如果答案涉及元类,请注意类 A 本身是另一个类的子类 -- django.db.models.Model -- 有一个非常复杂的元类。)

最佳答案

看来您不被允许monkey-patch protocol methods (以双下划线开头和结尾的):

Note

In practise there is another exception that we haven't handled here. Although you can override methods with instance attributes (very useful for monkey patching methods for test purposes) you can't do this with the Python protocol methods. These are the 'magic methods' whose names begin and end with double underscores. When invoked by the Python interpreter they are looked up directly on the class and not on the instance (however if you look them up directly - e.g. x.repr - normal attribute lookup rules apply).

在这种情况下,除非您可以使用 ~unutbu's answer,否则您可能会被卡住.

编辑:或者,您可以让基类 __unicode__ 方法在实例对象的字典中搜索 __unicode__ 属性。如果存在,则 __unicode__ 定义在实例对象上,类方法调用实例方法。否则,我们回退到 __unicode__ 的类定义。

认为这可以让您现有的子类代码无需任何更改即可工作。但是,如果派生类想要调用类实现,它会变得很丑陋——您需要小心避免无限循环。我没有在这个例子中实现这样的黑客攻击;只是评论了他们。

import types

class Dummy(object):
def __unicode__(self):
func = self.__dict__.get("__unicode__", None)
if func:
// WARNING: if func() invokes this __unicode__ method directly,
// an infinite loop could result. You may need an ugly hack to guard
// against this. (E.g., set a flag on entry / unset the flag on exit,
// using a try/finally to protect against exceptions.)

return func()

return u'one'

def two(self):
return u'two'

d = Dummy()
print unicode(d)
funcType = type(Dummy.__unicode__)
d.__unicode__ = types.MethodType(Dummy.two, d)
print unicode(d)
print d.__unicode__()

使用 Python 2.6 进行测试会产生以下输出:

> python dummy.py 
one
two
two

关于python - Python 2.5 和 2.6 之间的不同实例方法行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3391293/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com