python - 在运行时替换 python Mixin 类

标签 python python-2.7 mixins

我有一个数据访问类,它从数据库中获取数据。它是作为混合实现的,即 ReferenceData 我想将此类与 MockReferenceData 类交换,因此在单元测试中我不必访问数据库。但不起作用。

*注意:我无法使用依赖注入(inject)。由于团队不想使用它,因为考虑到这将是非常大的代码更改。所以我希望在运行时替换 mixin。

class MockReferenceData(object):
  def dbName(self):
    return 'mock'

  def totalNumberOfSeats(self):
    return '10'

class ReferenceData(object):
  def dbName(self):
    return 'real DB'

  def totalNumberOfSeats(self):
    return 'Fetch from DB'

class Car(ReferenceData):
  def showNumberOfSeats(self):
    print self.totalNumberOfSeats()


class Train(ReferenceData):
  def showNumberOfSeats(self):
    print self.totalNumberOfSeats()

c = Car()
c.showNumberOfSeats()
t = Train()
t.showNumberOfSeats()

def extend_instance(obj, cls):
    """Apply mixins to a class instance after creation"""
    base_cls = obj.__class__
    base_cls_name = obj.__class__.__name__
    obj.__class__ = type(base_cls_name, (base_cls, cls),{})

extend_instance(c, MockReferenceData)
c.showNumberOfSeats() // output now should be 10

输出是:

Fetch from DB
Fetch from DB
Fetch from DB

我希望因为我使用了 extend_instance 方法来指向新的模拟类输出将是:

Fetch from DB
Fetch from DB
10

最佳答案

如果你看MRO类(class)Car你可以看到:

>>> Car.__mro__
(<class '__main__.Car'>, <class '__main__.ReferenceData'>, <type 'object'>)

因此首先在 Car 上查找方法,然后点击ReferenceData最后是object .

将其与新类的 MRO 进行比较(为了清楚起见,我使用 NewCar 作为名称):

>>> type('NewCar', (Car, MockReferenceData), {}).__mro__
(<class '__main__.NewCar'>, <class '__main__.Car'>, <class '__main__.ReferenceData'>, <class '__main__.MockReferenceData'>, <type 'object'>)

这包含 Car 的 MRO类(class)。这里的方法仍然首先在 Car 上查找然后ReferenceData ,如totalNumberOfSeats发现于ReferenceData MockReferenceData 的实现未使用。

您可以做的是将模拟类插入 MRO 中的 Car 之前类:

>>> type('NewCar', (MockReferenceData, Car), {}).__mro__
(<class '__main__.NewCar'>, <class '__main__.MockReferenceData'>, <class '__main__.Car'>, <class '__main__.ReferenceData'>, <type 'object'>)

现在方法将首先在 MockReferenceData 中查找类,如果它们不存在,则回退到以前的版本。所以这个extend_instance方法应该适用于这个简单的情况:

def extend_instance(obj, cls):
    """Apply mixins to a class instance after creation"""
    obj.__class__ = type(obj.__class__.__name__, (cls, obj.__class__),{})

关于python - 在运行时替换 python Mixin 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47753873/

相关文章:

swift - 检查对象是否是特定类并符合协议(protocol)

python - 使用 Python split 将一个变量拼接在一起

python - 如何在 Clojure 中实现递归 DFS(不使用向量/堆栈)

ruby - Ruby 模块包含为什么不是真正的 'multiple inheritance' 以及 Ruby 风格如何避免与多重继承相关的问题?

python-2.7 - 如何使用 Bokeh 制作圆形动画

python - 当元组中只有一个列表时,为什么元组的类型是列表?

java - 从默认实现访问建议的对象方法

python - 打印不符合数据间隔设置

python - 如何在 Plotly (python) 中设置背景颜色、标题?

Python - 获取质数