【问题标题】:Chain methods in sub-class hierarchy to execute to get union of all methods execution in hierarchy子类层次结构中的链方法执行以获得层次结构中所有方法执行的联合
【发布时间】:2019-01-28 15:17:47
【问题描述】:

让我们考虑一下我的要求的简化版本

class Base:
    def __method(self):
        self.base = 'my-base'


class SubClass(Base):
    def __method(self):
        self.sub = 'my-sub'

我希望我的 SubClass 实例包含 basesub

这两个字段

让我们考虑一下我对实际需求的尝试

from configargparse import ArgParser


class BaseConf(object):
    def __init__(self) -> None:
        super().__init__()
        self._parser = ArgParser()
        self.__add_arg()

    def pop(self, args):
        first_base = self.__class__.__bases__[0]
        if first_base is not object:
            super().__populate_arg(args) # <----------Compile failure------->
        self.__populate_arg(args)

    def __add_arg(self):
        self._parser.add_argument('--base', type=str, default='NA')

    def __populate_arg(self, args):
        self.base = args.base


class SubConf(BaseConf):

    def __init__(self) -> None:
        super().__init__()
        self.__add_arg()

    def __add_arg(self):
        self._parser.add_argument('--sub', type=str, default='NA')

    def __populate_arg(self, args):
        self.sub = args.sub


conf = SubConf()
args, _ = conf._parser.parse_known_args()
conf.pop(args)
assert all(x in conf.__dict__ for x in ['base', 'sub'])

最终我希望断言条件通过。我已经通过标记 Compile failure 提到了导致问题的代码行。

我还会考虑彻底改革整体方法并尝试更好的方法。

感谢您的宝贵时间。

【问题讨论】:

  • super().__method() 总是会失败,因为这就是在__method 中使用名称修饰双下划线的全部意义所在。这确保此方法是私有方法,只能由该类本身访问(通过正常方式)。你为什么要这样做?为什么不让Base.method()SubClass.method() 打电话给super().method()

标签: python python-3.x inheritance decorator


【解决方案1】:

正如我在 cmets 中所说,使用名称重整的__private 方法的全部意义在于确保属性/方法是私有的 -- 它们仅限于该类使用 --不是它的子类。您可以通过删除前导下划线、创建方法_protectedpublic 轻松解决此问题。例如:

class Base:
    def method(self):
        self.base = 'my-base'

class SubClass(Base):
    def method(self):
        self.sub = 'my-sub'
        super().method()

这是非常不建议的,但如果你绝对必须从基类中获取私有属性,那么你可以使用

class Base:
    def __method(self):
        self.base = 'my-base'

class SubClass(Base):
    def method(self):
        self.sub = 'my-sub'
        super()._Base__method()

但这只有在您知道超类的名称时才有效。如果你不这样做,你就必须变得非常 hacky,比如

 class SubClass(Base):
    def method(self):
        self.sub = 'my-sub'
        sup = self.__class__.mro()[1].__name__
        getattr(super(), f'_{sup}__meth')()

【讨论】:

  • 要了解更多关于 Python 中下划线的信息,请查看here
  • 我不想做super().method(),因为对于另一个实现AnotherSubClass(Base),我必须再次显式调用它。这就是我试图通过使用pop(self,args) 方法来解决的问题。 __add_arg 也按预期工作(获取为子类执行的两种方法。)。名称 mangling 在这里帮助了我,因为基类中的 self.__add_arg 调用将从基类调用子类实例的版本.如果方法的名称是 add_arg(),则调用 self.add_arg() 将被覆盖以使用子类版本。
  • pop(self,args) 是整个层次结构中的一种常见实现,它试图链接类层次结构中的所有__populate_args 方法。 再次,我想链接而不是覆盖
猜你喜欢
  • 1970-01-01
  • 2019-06-05
  • 2018-02-22
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 2014-01-24
  • 2022-01-12
  • 1970-01-01
相关资源
最近更新 更多