【问题标题】:Does the existence of a derived class modify a base class, even if the derived class is never used?派生类的存在是否会修改基类,即使派生类从未使用过?
【发布时间】:2020-05-29 10:52:04
【问题描述】:

我有一个基类Sample 和一个派生类SignalSample,这两个类的代码通常驻留在同一个文件Sample.py 中。

我以通常的方式将这些类导入到我的主脚本中:from Sample import Sample, SignalSample

在寻找其中一个类中的错误时,我注意到一些不寻常的行为:删除SignalSample 派生类的代码会改变Signal 基类的行为。

所以我的问题是,即使派生类从未实例化,派生类的存在能否改变基类?

具体来说,我尝试了以下组合。

  1. SampleSignalSample 的代码都在Sample.py 中。 from Sample import Sample, SignalSample 在我的主脚本中用于加载这些类。 Sample 对象已实例化,没有 SignalSample 对象实例化,代码就在那里且未使用。在这种情况下,我会收到一个错误,我将其称为“类型 1”。
  2. 删除Sample.pySignalSample 的代码,并删除... import SignalSample 语句。在这种情况下,我会得到一个不同的错误,我将其称为“类型 2”。

请注意,我不认为错误来自类本身(尽管它们可能是),更有趣的是我发现代码的行为似乎发生了变化,因为有一个继承的类,甚至尽管没有使用该类。

这是我的设置的精简示例,请注意,这不是我的错误来源的 MWE,因为目前我不知道它来自哪里,所以我什至不能缩小范围。这不是我正在寻找的错误的解决方案,只是有关这种看似奇怪的类继承行为的更多信息。

# file Sample.py
class Sample:
   def __init__(self):
      self._tfile = None
      self._filepath = None

   def calculate_filepath(self):
      return "my/file/path"

   __calculate_filepath = calculate_filepath # private copy

   def get_histogram(self, histogram_name):
      if not self._filepath:
         self._filepath = self.calculate_filepath()
      if not self._tfile:
         from ROOT import TFile # this is a special filetype 
         self._tfile = TFile.Open(self._filepath, "READ")

      histo = self._tfile.Get(histogram_name)
      histo.SetDirectory(0)
      self._tfile.Close()
      return histo

class SignalSample(Sample):
   def __init__(self):

      # Inherit
      Sample.__init__(self)

      self._filepath = self.calculate_filepath()

   def calculate_filepath(self):
      # Overloaded version of the function in Sample
      return "my/very/special/filepath"

请注意,我选择在get_histogram 中调用calculate_filepath 方法是因为我想避免可能与派生类发生命名空间冲突。这也是为什么我尝试使用命名空间修饰使方法“私有”。这也是我在get_histogram 方法中打开特殊TFile 文件的原因,尽管很高兴我也可以在同一函数中Close 这个文件。也许这不是正确的用法,也许这与我的问题的根源有关?

【问题讨论】:

  • 我不清楚你在问什么。如果那不是minimal reproducible example 它想显示什么?
  • @jonrsharpe 我只想知道,如果您为派生类编写代码,即使派生类对象从未实例化,该代码是否会影响基类的行为?跨度>
  • 它当然可以做到。例如,即使你从不实例化子类,它也会出现在父类的__subclasses__() 列表中,所以如果有基于它的行为,它就会改变。
  • 好的,谢谢@jonrsharpe。有没有在不显式调用的情况下访问__subclasses__() 列表的方法?我上面显示的示例中的方法显示了我的类的基本结构,我不明白这会如何影响基类?
  • 这只是一个例子,重点是:是的,有很多方法可以做到。至于你具体情况的问题,你得给minimal reproducible example

标签: python python-2.7 polymorphism


【解决方案1】:

get_histogram 如果被多次调用,它看起来可能会损坏。您将打开的文件分配给实例(在self._tfile 上),然后在返回之前将其关闭......这意味着下次调用该方法时not self._tfile 可能(*)评估为False,这意味着您然后尝试在关闭的文件上调用Get。如果你使用的是一个健全的库,这可能会抛出一个很好的错误告诉你,但我看到你正在使用 ROOT,所以谁知道会发生什么:)

最简单的方法可能是将文件存储在Sample 上,只要调用get_histogram 就打开文件?

(*) 有时值得避免使用隐含的 booliness。特别是当您实际上想要检查某事是否为 None 时,更喜欢写 if x is None: (https://legacy.python.org/dev/peps/pep-0008/#programming-recommendations)

顺便说一下,在这个例子中,__calculate_filepath = calculate_filepath # private copy 没有做任何事情,因为你从未真正使用过它。

【讨论】:

  • 感谢@tom,文件不再存储在Sample 中(尽管实际上每个样本对象的每个生命周期只调用一次)。我还按照您的建议删除了 __calculate_filepath 变量。不幸的是,我仍然在我的代码中观察到不同的行为,这取决于我是否添加了import SignalSample。也许这需要一个更完整的例子......
  • 我想是的。正如上面@jonrsharpe 所观察到的,在 Python 中做各种令人发指的恶心事情当然是可能的。如果Sample 要从根类继承——或者以任何方式向ROOT 声明它的存在——那么我认为恶意游戏的可能性会更高。
猜你喜欢
  • 2017-07-04
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2019-07-25
相关资源
最近更新 更多