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

Python类:将所有继承的方法变为私有,python,class,Python,Class,类栏从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):

类栏从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'

这只有在Pythons的元类中才可能实现。但这是相当复杂的,我不确定是否值得努力。详情请看一看


为什么要这样做?

这只适用于Pyhtons的元类。但这是相当复杂的,我不确定是否值得努力。详情请看一看


为什么要这样做?

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。

Python没有private,只有模糊的方法名。但我认为,在创建实例时,您可以迭代超类的方法,将它们从自己身上删除,并为这些函数创建新的模糊命名的方法名。如果使用函数创建模糊名称,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。

您可以使用元类,但
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

如果你想让属性访问正常工作,你可以在
\uuuuuuuuuuuuu
中创建一个新的
Foo
基类,删除所有重命名的方法。

你可以使用元类,但是
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
如果您想让属性访问正常工作,可以在
\uuu new\uuu
中创建一个新的
Foo
基类,删除所有重命名的方法。

由于
Foo()
\uu 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
的接口集成到自己的接口中。

因为
Foo()
\ufoo()
是完全不同的方法,它们之间没有链接,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
的接口集成到它自己的接口中。

如果隐藏Foo的方法,你就不是一个很好的Foo。如果你想这样做,最好是简单地拥有一个
Bar
实例,而不是从是吗?@约阿希姆·绍尔——同意,这只是一个例子。我正试图深入研究类,了解什么可以做,什么不能做。适配器不是比继承更好的解决方案吗?@Tim Hoffman--我将研究它,谢谢。如果你隐藏了Foo的方法,你就不会是一个很好的Foo。如果你想这样做,简单地拥有一个
Bar
实例,而不是从它继承,不是更好吗?@约阿希姆·绍尔——同意,这只是一个例子。我试图深入研究类,了解什么可以做,什么不能做。适配器不是比继承更好的解决方案吗。@蒂姆·霍夫曼——我会研究它,谢谢。它是你自己的本地名称空间,所以我看不出你会如何“污染”它。但是无论如何,如果您将方法名更改为私有名称,则原始类的所有内部方法调用都需要