Python:重命名父类(super class)的方法及其函数范围引用

标签 python inheritance methods metaclass renaming

考虑以下示例:

class Company():

    def hireEmployee():

    def fireEmployee():

    def promoteEmployee():

    etc...

class EngineeringFirm(Company):
    pass

class PaintingFirm(Company):
    pass

假设 Company 类有很多方法。如果我想从父类(super class)中重命名这些方法怎么办,以便获得以下内容:

class EngineeringFirm(Company):

    def hireEngineer():
    ...

class PaintingFirm(Company):

    def hirePainter():
    ...

……等等。虽然在这种情况下使用“Employee”确实不会有什么坏处,但这实际上只是为了说明这个想法。我该怎么办?

我的想法是使用一个 classFactory 函数,它将员工的类型作为参数并生成一个 Company 类,而元类将通过遍历属性字典并将“Employee”替换为所述类型来处理重命名。

class EngineeringFirm(companyFactory('Engineer'))
    ...

唯一的问题是:如果 Company 内部的方法通过默认的“Employee”名称相互调用怎么办?这就是我难过的地方。我的想法是重命名方法所涉及的元类也可以获取每个函数的源代码(通过检查模块)并搜索是否在其中找到已知的方法属性,如果是,则替换该部分并通过创建一个新函数exec 并将其分配回正确的属性键。

...但这看起来确实有点老套。我对替代方案持开放态度,尽管我意识到这个问题可能存在与设计相关的问题(我也对这方面的建议持开放态度)我很想知道这个问题是否有更优雅的解决方案。

谢谢!

编辑:另一个解决方案

为了论证,我暂时假设上面的代码确实是我正在使用的代码;我想我可以用我想到的另一种解决方案来解决评论中的一些问题,我已经考虑过并搁置了这个解决方案,原因我将解释。

如果 Firm 类继承自 Company 并且我希望维护相同的接口(interface)(在这种情况下通常会允许动态调用 hire()promote() 等)我可以实现一个 __getattribute__ 来接受 HirePainter()(通过访问原始的 Employee 方法),同时仍然允许任何必要时使用 HireEmployee() 的其他接口(interface)。

我想知道,假设可以扩展我的问题,这是否会被认为是不好的做法,比如说,我计划这样做是因为我认为 PaintingFirm 中的代码会受益在可读性?再一次,我意识到这个例子很糟糕,因为这里的可读性似乎并没有以任何方式受益,但假设它有好处呢?

(我一开始没有提出这个想法的唯一原因是我的 __getattribute__ 已经处理了很多,并且向它添加额外的噪音并没有那么吸引人。不过,我可以解决这个问题,但这是我不得不问的一个问题,以防万一那里有更多神奇(但不是 hacky)的解决方案..)

最佳答案

为了后代,我发布了一个我自己的解决方案,我认为它是一个不错的选择。我不建议将此作为答案,因为事实是我没有在我的问题中提到我更喜欢不添加额外的名称,或者保留将这些属性称为 self.hireEngineer 而不是ClassDict['HireEngineer']。鉴于此,我真的不能说这些答案中的任何一个都没有回答问题。

解决方案:

事后看来,问题比我想象的要简单得多。我想我只是为了它而迷上了元分类。如果它还不是很明显,我真的只是在学习元类,有那么一刻这似乎是一个尝试它们的好机会。唉。

我相信以下解决方案尊重 Liskov 原则的精神(谢谢 Ignacio),同时赋予派生类以自己的方式引用派生方法的能力。类命名空间保持不变,其他对象可以在必要时使用它们的真实名称调用这些方法。

# superclass...

def __getattribute__(self, attr):

    # Early exit (AttributeError) if attribute not found.
    obj = object.__getattribute__(self, attr)

    # All the extra code...

def __getattr__(self, attr):

    # Ex. self.type == 'Engineer'
    # Replacing titled-cased and lower-cased 
    # versions just to be safe (ex. self.employeeNames)

    attr = (attr
        .replace(self.type, 'Employee')
        .replace(self.type.lower(), 'employee')
    )

    if attr in self.attributes:
        return self.__getattribute__(attr)
    else:
        raise AttributeError

下次在概述要求时,我会尽量做得更好。谢谢,伙计们。

关于Python:重命名父类(super class)的方法及其函数范围引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27729681/

相关文章:

java - 从两个不同的类调用相同的方法

ruby - 为&符号 block 提供参数

c++ - 在派生类中调用重写的方法

PHP:如何将子类 __construct() 参数传递给 parent::__construct()?

c# - 如何调用带参数的方法?

python - pandas 聚合中的自定义函数非常慢

c++ - 我可以在派生类中继承私有(private)成员吗?

python - Ipython、jupyter 和内核之间有什么关系?

python - Pandas,合并 2 个数据框

python - 以编程方式检测 RDBMS 中多对多关系的方法有哪些?