【问题标题】:Constrain method access to an interface?限制方法访问接口?
【发布时间】:2012-08-18 18:10:48
【问题描述】:

我有一个 Python 系统,由大约 9-10 个类组成,所有类都实现了大部分的胖鸭类型接口,并且可以被大量模块互换使用。我正在尝试将类重构为核心、显式(即 ABC)接口和外围功能,遵循职责分离,但为了做到这一点,我需要能够判断消费者模块何时调用核心之外的方法界面。

假设我有一个带有抽象方法的 ABC:

from abc import ABCMeta, abstractmethod

class MyABC:
    __metaclass__ = ABCMeta
    @abstractmethod 
    def foo(self):
        pass

我还有一个实现这些抽象方法以及其他方法的类:

class MyClass(MyABC):
    def foo(self):
        pass
    def bar(self):
        pass

instance = MyClass()

>>> isinstance(instance, MyABC)
True

如何确保当我将 instance 传递给方法 do_something 时,它使用属于 MyABC 的方法(在本例中为 foo)而不是任何方法其他方法(bar)?在静态类型语言(例如 C++)中,我可以传递 do_something ABC 类型的指针; Python 中是否有某种包装器可以类似地限制方法访问?

【问题讨论】:

    标签: python interface abstract-class


    【解决方案1】:

    简短的回答:没有

    在 Python 中没有可以强制执行的私有方法/变量的概念,如 detail 中所述。

    在 Python 中,这是由 convention 处理的。

    如果您真的想深入了解内部结构,请查看此thread

    【讨论】:

      【解决方案2】:

      这是我想出的:

      class ABCGuard(object):
          def __init__(self, obj, *abcs):
              if any(not isinstance(obj, abc) for abc in abcs):
                  raise ValueError("{0} must implement {1}"
                                   .format(obj.__class__.__name__,
                                           ', '.join(abc.__name__ for abc in abcs
                                                     if not isinstance(obj, abc))))
              self.__obj = obj
              self.__abcs = abcs
              classname = '{0}{{{1}}}'.format(obj.__class__.__name__,
                                              ', '.join(abc.__name__ for abc in abcs))
              self.__class__ = type(classname, (ABCGuard, ) + abcs, {})
      
          def __getattribute__(self, name):
              if name.startswith('_ABCGuard__') or (name.startswith('__') and
                                                    name.endswith('__')):
                  return super(ABCGuard, self).__getattribute__(name)
              elif any(name in abc.__abstractmethods__ for abc in self.__abcs):
                  return getattr(self.__obj, name)
              else:
                  raise AttributeError("%r object has no attribute %r" %
                                       (self.__class__.__name__, name))
      
          def __dir__(self):
              return [x for abc in self.__abcs for x in abc.__abstractmethods__]
      

      【讨论】:

        猜你喜欢
        • 2011-09-03
        • 2010-09-30
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 1970-01-01
        • 2011-07-25
        相关资源
        最近更新 更多