在保留原始类方法调用的同时覆盖类方法

时间:2018-09-02 00:16:39

标签: python

除了原始方法调用之外,我还想修改类方法以执行某些操作。我下面有一个玩具示例。

示例:

class str2(str):
    def __init__(self, val):
        self.val = val

    def upper(self):
        print('conveting to upper')
        return self.upper()

x = str2('a')
print(x.upper())

这符合我的预期,并给出了最大递归深度错误。是否可以修改upper方法,使其在调用实际的str.upper方法之前打印一些文本,而在理想情况下,使名称保持不变?

我一直在想使用装饰器是否是这种情况,但是我对它们还不熟悉,无法清楚地知道如何进行装饰。

4 个答案:

答案 0 :(得分:1)

解决方案是:

class str2(str):
    def __init__(self, val):
        self.val = val

    def upper(self):
        print('conveting to upper')
        return str.upper(self.val)

x = str2('a')
print(x.upper())

我指向您的代码:

  1. upper函数中,您只需打印它,然后一次又一次地使用相同的函数

  2. 这使得它将继续打印

  3. 它最终会引发错误,因为python基本上有足够的

我指向我的代码:

  1. 使用方法描述符(<method 'upper' of 'str' objects>)来使用它,以免它与self混淆

  2. 使用它是因为它仍将调用真实的str类(而不是元类)

我也自责自己为什么没想到:

class str2(str):
    def __init__(self, val):
        self.val = val

    def upper(self):
        print('conveting to upper')
        return self.val.upper()

x = str2('a')
print(x.upper())

答案 1 :(得分:1)

在方法str2.upper中,您要调用str2.upper,然后依次调用str2.upper,其中...您会看到它的去向。

您可能打算这样做的是从str.upper调用str2.upper。这可以通过使用super完成。调用super()返回一个将方法调用委托给父类的对象。

class str2(str):
    def upper(self):
        print('converting to upper')
        return super().upper()

答案 2 :(得分:0)

研究“映射”和“装饰器”-我认为有一种更简单/更Python化的方法来完成您要尝试的操作。

答案 3 :(得分:0)

正如@Schalton所说,有一种方法可以不必使用装饰器从str继承。请考虑以下代码段:

def add_text(func):
    def wrapper(*args, **kwargs):
        print('converting to upper')
        return func(*args)
    return wrapper

class str2:
    def __init__(self, val):
        self.val = val

    @add_text
    def upper(self):
        return self.val.upper()

instance = str2('a')

print(instance.upper())

最大的优点是包装器是可重复使用的,例如如果您要使用完全相同的行为来修改另一个类,则只需添加@decorator即可,而不必重做所有工作。而且,删除其他功能也变得更加容易。