是否可以在扩展方法的中间添加功能

时间:2017-03-26 01:16:16

标签: python

是否可以从中间修改/扩展继承的方法。我意识到我可以调用super并获取原始方法,然后在该调用之前或之后放置代码,这将扩展原始方法。是否有一种技术可以做一些类似但从方法中间做的事情?

class Base():
    def __init__(self):
        self.size = 4

    def get_data(self):
        data = []
        for num in range(self.size):
            data.append("doing stuff")
            data.append("doing stuff")
            ### add here from child##
            data.append("doing stuff")
            data.append("doing stuff")
        return data

class MyClass(Base):
    def __init__(self):
        super().__init__()

    def get_data(self):
        # inherited parent code
        # Do something else here
        # inherited parent code

2 个答案:

答案 0 :(得分:1)

  

是否有一种做类似但从中间做的事情的技巧   方法?

不是真的。 def编译成一个函数对象,该对象具有一个通常被视为不透明的自包含代码对象。

当出现这样的需求时,通常表明父方法需要拆分为可以单独调用的可重用组件。

如果你不能重构父方法,那么不幸的替代方案是子类必须覆盖该方法并从父方法中复制一些代码。

简而言之,Pythonic面向对象设计将方法和属性视为可组合性的原子单位。

答案 1 :(得分:1)

尽管Python具有强大的内省和代码修改功能,但没有" clean"这样做的方式。它只能通过直接修改原始函数中的字节码并在其中进行新的方法调用来完成 - 这也意味着创建新的代码和函数对象 - 绝对不能在生产代码中执行 - 即使因为字节码不是保证在Python版本或Python实现中保持不变。

重构原始方法:

但如果原始方法的编码方式是"意识到"那么可以这样做。点是子类可能想要运行其他代码(甚至可能在几种方法中拆分):

就你的例子而言,你有类似的东西:

class Base():
    def __init__(self):
        self.size = 4

    def get_data(self):
        self.data = data = []
        for num in range(self.size):
            data.append("doing stuff")
            data.append("doing stuff")
            self.do_extra_things_with_data()
            data.append("doing stuff")
            data.append("doing stuff")
        return data

    def do_extra_things_with_data():
        """Override this on subclasses"""

class MyClass(Base):
    def __init__(self):
        super().__init__()

    def do_extra_things_with_data():
        print(len(self.data), "objects defined so far")

其中一个技术名称是" slot"。 (它用于某些Web框架中的模板 - 派生页面使用父模板进行列和一般布局,并为内容区域定义"插槽" 另外需要注意的是描述符,例如"属性":您无法更改超类方法代码 - 但如果代码检索其计算的实例属性,则可以将这些属性定义为在子类上运行自定义代码的属性。

使用描述符:

另一种方法是使用描述符,例如"属性":你不能改变超类方法代码 - 但如果代码检索其计算的实例属性,您可以将这些属性定义为子类上的属性以运行自定义代码。

假设您的方法使用self.size属性,但正是为了计算它您可能想要运行更多代码 - 保持完全相同的基类:

class MyClass(Base):
    @property
    def size(self):
         # put extr calculation to retrieve the dynamc value
         of self.size here
         return value