1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

pythonのprivate関数について

Posted at

1. private関数とは?

Pythonにおける「private関数」とは、クラスやモジュールの内部でのみ使用することを意図した関数のことです。他のプログラミング言語(例えばJavaやC++)とは異なり、Pythonにはアクセス修飾子(private, protectedなど)が存在しません。しかし、慣習的にアンダースコア(_)を関数名の先頭に付けることでprivate関数の役割を担っています。

2. private関数の定義方法

private関数は、以下のようにアンダースコアを先頭に付けて定義します。

class SampleClass:
    def __init__(self, value):
        self.value = value
    
    def _private_method(self): # private関数
        return f"This is a private method. Value: {self.value}"

    def public_method(self):
        return self._private_method()

obj = SampleClass(42)
print(obj.public_method())  # 呼び出し可能
print(obj._private_method())  # 一応呼び出せるが推奨されない

_private_method() はprivateメソッドとして定義されていますが、実際には obj._private_method() で外部からもアクセス可能です。しかし、アンダースコアが付いていることで「内部専用」という意図を伝えることができます。

3. ダブルアンダースコア(__)による名前マングリング

Pythonでは、アンダースコア2つ(__)で始まる関数名は、クラスの名前をプレフィックスとして付加される「名前マングリング」が適用されます。
名前マングリングの動作は、クラス内で __private_method のように定義すると、Pythonは内部的に _<クラス名>__private_method に変換します。

class Example:
    def __private_method(self):
        return "This is a name-mangled method"
    
    def public_method(self):
        return self.__private_method()

obj = Example()
print(obj.public_method())  # 正常に呼び出せる
print(obj.__private_method())  # AttributeError: 'Example' object has no attribute '__private_method'

このように、__private_method() に直接アクセスしようとするとエラーになります。しかし、名前マングリングにより、実際には _Example__private_method() という名前に変換されているため、以下のようにアクセスすることは可能です。

print(obj._Example__private_method())  # 正常に呼び出せる

外部からのアクセスを完全に禁止するものではないですが、_とは異なり、より強い「外部から使うべきではない」という意図を示せます。

4. private関数の用途

private関数は、主に以下のような場面で利用されます。

  • 内部処理を隠蔽する: 外部に公開する必要がない関数を隠す。
  • 内部ロジックの保護: ユーザーが直接変更すべきでない関数を明示する。
  • クラスの一貫性を保つ: 一部のメソッドをカプセル化し、データの整合性を保つ。

例えば、数値を処理するクラスで、データの前処理をprivate関数として実装することができます。

class DataProcessor:
    def __init__(self, data):
        self.data = data
    
    def _normalize(self):
        return [x / max(self.data) for x in self.data]
    
    def process(self):
        normalized_data = self._normalize()
        return [x**2 for x in normalized_data]

processor = DataProcessor([10, 20, 30])
print(processor.process())  # [0.1111111111111111, 0.4444444444444444, 1.0]

ここでは _normalize() をprivateメソッドとして定義することで、外部のコードがデータの正規化処理を直接操作するのを防ぎます。

5. モジュールレベルのprivate関数

クラスのメソッドだけでなく、モジュールレベルでもprivate関数を定義できます。

# mymodule.py

def _private_function():
    return "This function is intended for internal use only"

def public_function():
    return _private_function()

_private_function() はモジュール内でのみ使用されることを意図していますが、
外部のコードから mymodule._private_function() としてアクセスすることは可能です。

6. private関数のベストプラクティス

private関数を使用する際には以下の点を考える必要があります。

  • 本当に外部からアクセス不可にするべきか?

    • ただの慣習なので、外部からアクセス可能であることを認識しておく。
  • ダブルアンダースコアの過信は禁物

    • 名前マングリングを回避するための仕組みであり、完全なアクセス制限にはならない。
  • 適切なドキュメント化

    • private関数であることをコメントなどで明示すると、より分かりやすくなる。
  • __all__ で制限をかける(モジュールの場合)

    • __all__ = ['public_function'] を指定すると、
      from mymodule import *public_function のみが公開される。

7. まとめ

Pythonでは、private関数は「アクセス不可」ではなく「内部専用として設計された関数」です。適切に活用することで、コードの可読性や保守性を向上させることができます。

ポイントまとめ

・ アンダースコア _ をつけることでprivate関数とみなされる
__ をつけると名前マングリングされるが、完全に隠蔽されるわけではない
・ モジュールレベルのprivate関数も _ をつけることで区別できる
・ private関数を適切に設計することでコードの一貫性と保守性が向上する

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?