Pythonの親クラスにあるメソッドの一部を継承しない方法


子クラスで親クラスに一部メソッドを許可し、ほかを不許可としたいです。

[code]

    class A():
      def a(self):
        print('a')
    
     def b(self):
       print('b')
    
    class B(A):
      def b(self):
        super().b()
        print('bb')
    
[/code]

このようなコードの場合、class Bのインスタンスでは、メソッドaを呼び出せないようにしたい。  
なお、既定のパッケージから継承するので、メソッド名に `__` をつけて回避する方法がとれません。




基底クラスを変更できない場合、pythonで完全に継承元メソッドを隠ぺいすることはできないと思います。  
ただしコメントのリンク先にある方法など、対応方法はいくつか考えられます。

### raise 実行時エラー

[How to perform partial
inheritance](https://stackoverflow.com/a/11204743)の回答にあるように、関数呼び出しで例外を発生させれば有無を言わせずに関数呼び出しが中断させられます。  
下記のコードでは class B の a関数に`raise NotImplementedError`を記述しています。

[code]

    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      def a(self):
        raise NotImplementedError
    
      def b(self):
        super().b()
        print('bb')
    
    a1 = A()
    a1.a()
    b1 = B()
    b1.a()
    print("done.")
    
[/code]

**例外の例**

[code]

    例外が発生しました: NotImplementedError
    exception: no description
      File "C:\hoge.py", line 10, in a
        raise NotImplementedError
      File "C:\hoge.py", line 19, in <module>
        b1.a()
    NotImplementedError: 
    
[/code]

### debtcollector 実行時警告

関数を呼び出した時に、エラーを出して強制終了するほどではないけれど警告を出したい場合は、[debtcollector](https://pypi.org/project/debtcollector/)パッケージを導入するときれいに警告を記述できます。  
下記のコードでは class B の a関数の上に `@removals.remove`デコレータを記述し、`b1.a()`を実行した時に警告を表示します。

[code]

    from debtcollector import removals
    
    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      @removals.remove(message="Bクラスのa関数は使用禁止です")
      def a(self):
        super().a()
        print('aa')  
    
      def b(self):
        super().b()
        print('bb')
    
    a1 = A()
    a1.a()
    b1 = B()
    b1.a()
    print("done.")
    
[/code]

**出力例**

[code]

    a
    C:\hoge.py:23: DeprecationWarning: Using function/method 'B.a()' is deprecated: Bクラスのa関数は使用禁止です
      b1.a()
    a
    aa
    done.
    
[/code]

### Facadeパターンもどきでエラー

どうしてもBクラスのa関数を呼び出したくないというか、むしろBクラスはb関数しか呼び出したくないなど、呼び出す関数やプロパティが非常に少ないならば、呼び出しを限定する窓口クラスに処理を移譲する方法があります。  
下記のコードでは class Bdash が class B を内部的に保持して、 b関数のみ公開しています。

[code]

    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      def b(self):
        super().b()
        print('bb')
    
    class Bdash:
      def __init__(self):
        self.b1 = B()
    
      def b(self):
        self.b1.b()
    
    a1 = A()
    a1.a()
    b1 = Bdash()
    b1.a()
    print("done.")
    
[/code]

**例外の例**

[code]

    例外が発生しました: AttributeError
    'Bdash' object has no attribute 'a'
      File "C:\hoge.py", line 26, in <module>
        b1.a()
        ^^^^
    AttributeError: 'Bdash' object has no attribute 'a'
    
[/code]




基底クラスを変更できない場合、pythonで完全に継承元メソッドを隠ぺいすることはできないと思います。  
ただしコメントのリンク先にある方法など、対応方法はいくつか考えられます。

### raise 実行時エラー

[How to perform partial
inheritance](https://stackoverflow.com/a/11204743)の回答にあるように、関数呼び出しで例外を発生させれば有無を言わせずに関数呼び出しが中断させられます。  
下記のコードでは class B の a関数に`raise NotImplementedError`を記述しています。

[code]

    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      def a(self):
        raise NotImplementedError
    
      def b(self):
        super().b()
        print('bb')
    
    a1 = A()
    a1.a()
    b1 = B()
    b1.a()
    print("done.")
    
[/code]

**例外の例**

[code]

    例外が発生しました: NotImplementedError
    exception: no description
      File "C:\hoge.py", line 10, in a
        raise NotImplementedError
      File "C:\hoge.py", line 19, in <module>
        b1.a()
    NotImplementedError: 
    
[/code]

### debtcollector 実行時警告

関数を呼び出した時に、エラーを出して強制終了するほどではないけれど警告を出したい場合は、[debtcollector](https://pypi.org/project/debtcollector/)パッケージを導入するときれいに警告を記述できます。  
下記のコードでは class B の a関数の上に `@removals.remove`デコレータを記述し、`b1.a()`を実行した時に警告を表示します。

[code]

    from debtcollector import removals
    
    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      @removals.remove(message="Bクラスのa関数は使用禁止です")
      def a(self):
        super().a()
        print('aa')  
    
      def b(self):
        super().b()
        print('bb')
    
    a1 = A()
    a1.a()
    b1 = B()
    b1.a()
    print("done.")
    
[/code]

**出力例**

[code]

    a
    C:\hoge.py:23: DeprecationWarning: Using function/method 'B.a()' is deprecated: Bクラスのa関数は使用禁止です
      b1.a()
    a
    aa
    done.
    
[/code]

### Facadeパターンもどきでエラー

どうしてもBクラスのa関数を呼び出したくないというか、むしろBクラスはb関数しか呼び出したくないなど、呼び出す関数やプロパティが非常に少ないならば、呼び出しを限定する窓口クラスに処理を移譲する方法があります。  
下記のコードでは class Bdash が class B を内部的に保持して、 b関数のみ公開しています。

[code]

    class A():
      def a(self):
        print('a')
    
      def b(self):
        print('b')
    
    class B(A):
      def b(self):
        super().b()
        print('bb')
    
    class Bdash:
      def __init__(self):
        self.b1 = B()
    
      def b(self):
        self.b1.b()
    
    a1 = A()
    a1.a()
    b1 = Bdash()
    b1.a()
    print("done.")
    
[/code]

**例外の例**

[code]

    例外が発生しました: AttributeError
    'Bdash' object has no attribute 'a'
      File "C:\hoge.py", line 26, in <module>
        b1.a()
        ^^^^
    AttributeError: 'Bdash' object has no attribute 'a'
    
[/code]

