Python类:将所有继承的方法设为私有

时间:2012-09-14 10:47:32

标签: python class

Class Bar继承自Foo:

class Foo(object):
      def foo_meth_1(self):
          return 'foometh1'
      def foo_meth_2(self):
          return 'foometh2'
class Bar(Foo):
      def bar_meth(self):
          return 'bar_meth'

有没有办法让所有从Foo继承的方法变为私有?

class Bar(Foo):
      def bar_meth(self):
          return 'bar_meth'
      def __foo_meth_1(self):
          return 'foometh1'
      def __foo_meth_2(self):
          return 'foometh2'

4 个答案:

答案 0 :(得分:3)

Python没有私有,只有混淆的方法名称。但是我想你可以在创建实例时迭代超类的方法,从自己中删除它们并为这些函数创建新的混淆命名的方法名称。如果使用函数创建模糊名称,setattr和getattr可能很有用。

据说,这是一个非常好的事情。你提到的目的是保持命名空间更清洁,但这更像是混合氨和氯。如果需要隐藏该方法,请将其隐藏在超类中。不要创建超类的实例 - 而是创建一个特定的类,将隐藏的方法包装在公共类中,你可以命名相同的东西,但剥离前导空格。

假设我理解你的意图,我会建议做这样的事情:

class BaseFoo(object):
    def __init__(self):
        raise NotImplementedError('No instances of BaseFoo please.')
    def _foo(self):
        return 'Foo.'
    def _bar(self):
        return 'Bar.'

class HiddenFoo(BaseFoo):
    def __init__(self): pass

class PublicFoo(BaseFoo):
    def __init__(self): pass
    foo = BaseFoo._foo
    bar = BaseFoo._bar

def try_foobar(instance):
    print 'Trying ' + instance.__class__.__name__
    try:
        print 'foo: ' + instance.foo
        print 'bar: ' + instance.bar
    except AttributeError, e:
        print e

foo_1 = HiddenFoo()
foo_2 = PublicFoo()
try_foobar(foo_1)
try_foobar(foo_2)

如果PublicFoo.foo会执行超过BaseFoo.foo的操作,您可以编写一个包装器来执行所需的操作,然后从超类中调用foo。

答案 1 :(得分:2)

这只适用于Pyhtons的元类。但这很复杂,我不确定是否值得付出努力。有关详细信息,请查看here

你为什么要这样做?

答案 2 :(得分:0)

您可以使用元类,但Boo将不再是Foo的实际子类,除非您希望Foo的方法在{{的实例中同时为'private'和'public' 1}}(您无法有选择地继承从父类继承的名称或Bar成员)。这是一个非常人为的例子:

delattr

如果您希望让属性访问工作,可以在from inspect import getmembers, isfunction class TurnPrivateMetaclass(type): def __new__(cls, name, bases, d): private = {'__%s' % i:j for i,j in getmembers(bases[0]) if isfunction(j)} d.update(private) return type.__new__(cls, name, (), d) class Foo: def foo_meth_1(self): return 'foometh1' def foo_meth_2(self): return 'foometh2' class Bar(Foo, metaclass=TurnPrivateMetaclass): def bar_meth(self): return 'bar_meth' b = Bar() assert b.__foo_meth_1() == 'foometh1' assert b.__foo_meth_2() == 'foometh2' assert b.bar_meth() == 'bar_meth 中创建一个新的Foo基类,并删除所有重命名的方法。

答案 3 :(得分:0)

由于foo()__foo()是完全不同的方法,它们之间没有链接,因此Python无法理解您想要做什么。所以你必须一步一步地向它解释,意思是(像sapth所说)删除旧方法并添加新方法。

这是一个面向对象的设计缺陷,更好的方法是通过委派:

class Basic:
    def meth_1(self):
        return 'meth1'

    def meth_2(self):
        return 'meth2'


class Foo(Basic):
    # Nothing to do here
    pass


class Bar:
    def __init__(self):
        self.dg = Basic()

    def bar_meth(self):
        return 'bar_meth ' + self.__meth_1()

    def __meth_1(self):
        return self.dg.meth_1()

    def __meth_2(self):
        return self.dg.meth_2()

虽然Foo继承了Basic类,因为他想要来自他的公共方法,Bar只会将作业委托给Basic,因为他不想整合Basic进入自己界面的界面。