如何在Python中隐藏/删除继承类中的某些方法?

如何在Python中隐藏/删除继承类中的某些方法?,python,Python,我想在继承类B时从类A隐藏一些公共方法: class A(object): def someMethodToHide(): pass def someMethodToShow(): pass class B(A): pass len(set(dir(A)) - set(dir(B))) == 1 如果可能的话,如何在python中实现它?Selcuk最好,但有时重构太麻烦了 因此,这里有一些东西会让你的同事像女妖一样尖叫,诅咒你的名字 它的工作原理是使用一个元

想在继承
类B
时从
类A
隐藏一些公共方法

class A(object):
  def someMethodToHide():
    pass

  def someMethodToShow():
    pass

class B(A):
  pass

len(set(dir(A)) - set(dir(B))) == 1
如果可能的话,如何在python中实现它?Selcuk最好,但有时重构太麻烦了

因此,这里有一些东西会让你的同事像女妖一样尖叫,诅咒你的名字

它的工作原理是使用一个元类,
hide\u meta
,来添加重载的
\uuuu getattribute\uuuuuu
\uuuu dir\uuuu
方法。它对所需类的应用只需设置
\uuuuuu metaclass\uuuuu=hide\uu meta
\uuuuuuu excluded\uuuuu=[“列表”、“of”、“不需要的”、“属性/方法”]


以下是我评论的答案形式:您可以从第三个类C继承A和B。如下所示:

class C(object):
  def someMethodToShow():
    pass

class A(C):
  def someMethodToHide():
    pass

class B(C):
  pass
顺便说一句,如果你想要的是可能的,它将打破多态性。这个不会。您可以创建一个类来模拟“已删除”属性。然后,您可以将“待删除”名称指定给该类的一个实例

下面是一个完整的示例,显示了访问子类及其实例上的该属性时出现的错误/回溯。通过引发自定义错误,回溯明确表示此属性已被故意“删除”

[1]中的
:类DeletedAttributeError(AttributeError):
…:通过
...:  
...:  
…:类DeletedAttribute:
…:def uuu set u name uuuu(self,owner,name):
…:self.name=名称
...:  
…:def_uuuget_uuu(self、instance、owner):
…:cls\u name=所有者。\u\u name\u
如果实例不是其他f{cls_name!r}对象,则通过=f'type object{cls_name!r}访问
…:raise DeletedAttributeError(已删除{accessed_via}的f'attribute{self.name!r})
...:  
...:  
…:类Foo:
…:def hide_me(self):
…:通过
...:  
...:  
…:类栏(Foo):
…:hide_me=DeletedAttribute()
...:                                                                                       
在[2]中:Foo.hide\u me
出[2]:
在[3]中:Bar.hide\u me
---------------------------------------------------------------------------
DeletedAttributeError回溯(最近一次调用)
在里面
---->1巴。把我藏起来
in\uuuu get\uuuu(self、instance、owner)
10 cls_name=所有者__
11通过=f'type object{cls_name!r}'访问{u,如果实例不是其他f'{cls_name!r}对象'
--->12 raise DeletedAttributeError(通过!r}访问的{u的f'属性{self.name!r}已被删除')
13
14
DeletedAttributeError:已删除对象“Bar”类型的属性“hide_me”
在[4]:Bar()中隐藏我
---------------------------------------------------------------------------
DeletedAttributeError回溯(最近一次调用)
在里面
---->1巴()。隐藏我
in\uuuu get\uuuu(self、instance、owner)
10 cls_name=所有者__
11通过=f'type object{cls_name!r}'访问{u,如果实例不是其他f'{cls_name!r}对象'
--->12 raise DeletedAttributeError(通过!r}访问的{u的f'属性{self.name!r}已被删除')
13
14
DeleteDatTributeTError:“Bar”对象的属性“hide_me”已被删除

上述代码适用于Python 3.6+。

删除子类方法的用例是什么?您确定要在这种情况下使用类继承吗?您可以从第三个类C扩展A和B,该类C只有要显示的方法。然后您可以只在类A中实现methodToHide。@Selcuk看起来这是实现它的最简单的方法:)@Ffisegydd是的,因为根本不需要重复代码-不像Java那样需要与代码重复作斗争。但我想我的观点是“为什么您只想从超类部分继承?”如果它只订阅了部分功能,它真的会被认为是一个子类吗?这非常复杂,因为它所提供的价值很小。我认为对同一个问题的回答给出了一个更清晰的解决方案:@BryanOakley,这个答案更简单,但是
NotImplementedError
没有“隐藏”这个方法,它只是使它无法使用。这个答案对于属性也不起作用(无论如何,如果不涉及
@property
。@dilbert确实
未实现错误
不是我要问的。你的解释很好-看起来这是最好的答案!有时需要像您所说的那样编写隐藏方法的诅咒代码。顺便说一句,应该经常使用Seluck解决方案,但有时需要隐藏方法-使用
NotImplementedError
进行覆盖是错误的模式,因为错误类型无效,并建议使用其他方法-有效的是
AttributeError
。如果没有更好的解决方案,我会尽快给出答案。这是OO设计中最常见的解决方案和有效的模式——我将研究诅咒的解决方案,因为它隐藏了一些方法。
class C(object):
  def someMethodToShow():
    pass

class A(C):
  def someMethodToHide():
    pass

class B(C):
  pass
In [1]: class DeletedAttributeError(AttributeError): 
   ...:     pass 
   ...:  
   ...:  
   ...: class DeletedAttribute: 
   ...:     def __set_name__(self, owner, name): 
   ...:         self.name = name 
   ...:  
   ...:     def __get__(self, instance, owner): 
   ...:         cls_name = owner.__name__ 
   ...:         accessed_via = f'type object {cls_name!r}' if instance is None else f'{cls_name!r} object' 
   ...:         raise DeletedAttributeError(f'attribute {self.name!r} of {accessed_via} has been deleted') 
   ...:  
   ...:  
   ...: class Foo: 
   ...:     def hide_me(self): 
   ...:         pass 
   ...:  
   ...:  
   ...: class Bar(Foo): 
   ...:     hide_me = DeletedAttribute() 
   ...:                                                                                       

In [2]: Foo.hide_me                                                                           
Out[2]: <function __main__.Foo.hide_me(self)>

In [3]: Bar.hide_me                                                                           
---------------------------------------------------------------------------
DeletedAttributeError                     Traceback (most recent call last)
<ipython-input-3-240c91cc1fc8> in <module>
----> 1 Bar.hide_me

<ipython-input-1-0f699423deb7> in __get__(self, instance, owner)
     10         cls_name = owner.__name__
     11         accessed_via = f'type object {cls_name!r}' if instance is None else f'{cls_name!r} object'
---> 12         raise DeletedAttributeError(f'attribute {self.name!r} of {accessed_via!r} has been deleted')
     13 
     14 

DeletedAttributeError: attribute 'hide_me' of type object 'Bar' has been deleted

In [4]: Bar().hide_me                                                                         
---------------------------------------------------------------------------
DeletedAttributeError                     Traceback (most recent call last)
<ipython-input-4-9653f0da628c> in <module>
----> 1 Bar().hide_me

<ipython-input-1-0f699423deb7> in __get__(self, instance, owner)
     10         cls_name = owner.__name__
     11         accessed_via = f'type object {cls_name!r}' if instance is None else f'{cls_name!r} object'
---> 12         raise DeletedAttributeError(f'attribute {self.name!r} of {accessed_via!r} has been deleted')
     13 
     14 

DeletedAttributeError: attribute 'hide_me' of 'Bar' object has been deleted