约束方法访问接口?

时间:2012-08-23 08:51:57

标签: python interface abstract-class

我有一个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的方法(在这种情况下{ {1}})而不是任何其他方法(foo)?在静态类型语言(例如C ++)中,我可以传递bar ABC类型的指针; Python中是否有某种类型的包装器可以同样限制方法访问?

2 个答案:

答案 0 :(得分:0)

简短回答:没有

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

在Python中,这是convention的handeld。

如果你真的想进入深层内部结账这thread

答案 1 :(得分:0)

这就是我提出的:

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__]