0

类 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

4 回答 4

3

Python 没有私有属性,只有经过混淆的方法名称。但是我想您可以在创建实例时迭代超类的方法,将它们从您自己身上移除并为这些函数创建新的模糊命名的方法名称。如果您使用函数来创建混淆名称,setattr 和 getattr 可能会很有用。

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

假设我正确理解您的意图,我建议您执行以下操作:

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 。

于 2012-09-14T11:00:30.543 回答
2

这只有在 Pyhtons 的元类中才有可能。但这非常复杂,我不确定是否值得付出努力。详情请看 这里

你为什么要这样做?

于 2012-09-14T10:52:41.633 回答
0

您可以使用元类,但Boo将不再是 Foo 的实际子类,除非您希望Foo' 方法在实例中既是“私有”又是“公共” 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基类,__new__删除所有重命名的方法。

于 2012-09-14T11:46:31.290 回答
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()

While Foo inherits the Basic class because he wants the public methods from him, Bar will only delegate the job to Basic because he doesn't want to integrate Basic's interface into its own interface.

于 2012-09-14T11:53:32.243 回答