【发布时间】:2015-02-28 01:09:41
【问题描述】:
考虑以下示例:
class Company():
def hireEmployee():
def fireEmployee():
def promoteEmployee():
etc...
class EngineeringFirm(Company):
pass
class PaintingFirm(Company):
pass
假设 Company 类有更多的方法。如果我想从超类中重命名这些方法,以便获得以下内容怎么办:
class EngineeringFirm(Company):
def hireEngineer():
...
class PaintingFirm(Company):
def hirePainter():
...
...等等。虽然在这种情况下使用“员工”确实不会有一点伤害,但这只是为了说明这个想法。我该怎么办?
我的想法是使用一个 classFactory 函数,它将员工的类型作为参数并生成一个 Company 类,而元类将通过遍历属性字典并将“员工”替换为所述类型来处理重命名。
class EngineeringFirm(companyFactory('Engineer'))
...
唯一的问题是:如果 Company 内部的方法通过默认的 'Employee' 名称相互调用会怎样?这就是我难过的地方。我的想法是,重命名方法所涉及的元类也可以获取每个函数的源(通过检查模块)并搜索是否在其中找到已知方法属性,如果是,则替换该部分并通过创建新函数exec 并将其分配回正确的属性键。
...但这看起来确实有点 hacky。我对替代方案持开放态度,尽管我意识到这个问题可能存在与设计相关的问题(我也愿意接受这方面的建议),但我很想知道这个问题是否有更优雅的解决方案。
谢谢!
编辑:另一种解决方案
为了争论,我暂时假设上面的代码确实是我正在使用的;我想我可以用我想到的另一种解决方案来解决 cmets 中的一些问题,我已经考虑过并放弃了,原因我将解释。
如果从 Company 继承的 Firm 类并且我希望维护一个相同的接口(在这种情况下通常会允许动态调用 hire() 或 promote() 等),我可以实现一个 @ 987654328@ 接受 HirePainter()(通过访问原始的 Employee 方法),同时仍允许任何其他接口在必要时使用 HireEmployee()。
我想知道,假设可以扩展我的问题,如果这会被认为是不好的做法,例如,我计划这样做是因为我认为 PaintingFirm 中的代码会提高可读性?再一次,我意识到这个例子很糟糕,因为这里的可读性确实似乎没有任何好处,但假设它有?
(我一开始没有提出这个想法的唯一原因是我的__getattribute__ 已经处理了很多,并且添加额外的噪音并没有那么吸引人。不过,我可以使用它,但这是我不得不问的一个问题,以防万一有更多神奇(但不是骇人听闻的)解决方案..)
【问题讨论】:
-
@Eithos 好吧,关键是,您的公司应该有一个相似的(如果不相同的话)界面,以便您可以告诉任何公司对象雇用某人,并让它决定雇用谁。所以你可以在不知道
firm到底是什么的情况下做firm.hire()。 -
@glglgl 有趣。这让我觉得很傻,因为在大多数其他情况下,这可能是我处理它的方式。完全有道理。我意识到问题很复杂,因为我还没有真正发布我的真实代码,而且几乎没有任何其他类可以/应该访问
firm.hire()的机会(如果有的话)。换句话说,虽然使用firm.hire可以在事先不知道公司的情况下促进动态招聘,但这种动态处理确实没有必要。事实上,这些调用是由 UI 事件激活的…… -
...只针对一个类;因此,他们永远不会称呼不同类型的“雇员”。我想这是我应该提到的......
-
我认为这是一个很好的问题。我正在尝试在 Django 中创建一个
FormsetView泛型类。它应该做FormView所做的所有事情,但用词formset代替。在这种情况下,我真的不需要FormsetView成为FormView的子类。我只是希望它是一个对属性名称进行细微更改的副本。
标签: python inheritance methods metaclass renaming