【问题标题】:Python: make lib use redefined classPython:使 lib 使用重新定义的类
【发布时间】:2019-07-26 02:58:39
【问题描述】:

想象一下使用 python 库。假设这个库有一个脚本和几个感兴趣的类。所有这些类都在单独的文件中定义。假设 D 类被 A、B 和 C 类以多种方式导入和使用。以同样的方式,A 类使用 B 类,B 类使用 C 类。脚本直接使用 A 类,因此直接和间接使用 D 类。现在假设您要自定义 D 并在本地定义一个类 D'派生自 D 类。

让脚本和其他类(A、B、C)使用 D' 类而不是 D 类的最优雅的方法是什么?

谢谢你,祝你有美好的一天!

【问题讨论】:

  • 没有一般的答案,你具体想做什么?
  • 这完全取决于如何准确管理导入。例如,如果脚本使用from d import D 而不是import d,然后在文件中使用d.D 引用D,这将非常困难。
  • 对于json 等常用库,您可以继承类,然后在函数调用中使用该类,例如json.dump(x, fp, encoder=YourNewClass)

标签: python python-3.x oop derived-class


【解决方案1】:

你可以monkey patch the library

# a.py
import d
class A():
    my_d = d.D()

# script.py
A.d.D = D_prime

def foo():
    a_cls = a.A() # uses A.d.D is D'

a.py 导入 D 的方式很重要

# a.py
from d import D
class A():
    my_d = D()

# script.py
A.D = D_prime

def foo():
    a_cls = a.A() # uses A.D is D'

其他导入方案可能涉及类似的模式。像这样的东西可能很难修补。

def builder():
    from d import D
    return D()

看看mock library 是如何做到这一点的也可能会有所帮助。如果它是一个玩具,您可以直接使用它。 patch 特别是interesting

@patch('A.d.D', new=D_prime)
def my_func(...):
    a = A() # a.d.D is D_prime

猴子补丁是一种代码气味,取决于应用程序代码中的单元测试是一种气味。没有一个是“优雅的”。如果你是库作者,请支持依赖注入。

如果你够勇敢,你可能会将一些补丁装饰器提取到不专注于模拟的东西中。因为这个模式存在于 unittest 库中,所以它可以被认为是 Python 的和“优雅的”,上面的警告。

如果您对如何感兴趣,您正在修改模块a 的符号表。详情请参阅globalslocals

【讨论】:

  • 谢谢(和其他所有人)。一旦我明白了它,结果证明它很容易。对于其他有理解问题的人,这是我在知道猴子补丁这个词后发现的一个不太抽象的例子:(stackoverflow.com/questions/19545982/…)。
  • 跟进:为什么我的猴子补丁坏了?我正在使用的库是 ray 0.6.2 (github.com/ray-project/ray),我成功地应用了我的补丁,如下所示:ray.tune.trial.Trial.init_logger = custom_init_logger。到目前为止,一切都很好。现在我还想修补另一个函数ray.rllib.evaluation.metrics.summarize_episodes = custom_summarize_episodes,它不起作用。回过头来,我发现ray.rllib.agents.dqn.DQNAgent.train = exit 有效,ray.tune.trainable.Trainable.train = exit 无效。 'Trainable' 被导入,它是在代理训练函数中调用的训练函数。
  • @DisplayName 我怀疑ray.rllib.agents.dqn.DQNAgent.train 是从ray.tune.trainable.Trainable.train 导入的。如果补丁发生在此导入之后,并且您已修补 ray.tune.trainable.Trainable.train,则使用它的地方引用了原始函数。
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
相关资源
最近更新 更多