はじめに
Twitterで一時期流行していた 100 Days Of Code なるものを先日知りました。本記事は、初学者である私が100日の学習を通してどの程度成長できるか記録を残すこと、アウトプットすることを目的とします。誤っている点、読みにくい点多々あると思います。ご指摘いただけると幸いです!
今回学習する教材
-
- 8章構成
- 本章216ページ
今日の進捗
- 進行状況:79-86ページ
- 第3章:クラスと継承
- 本日学んだことの中で、よく忘れるところ、知らなかったところを書いていきます。
プライベート属性よりはパブリック属性が好ましい
Pythonのクラスの属性の可視性にはパブリックとプライベートがあります。
アンダーバーを2つ付けることでプライベートとして扱われます。
classブロックの内部で宣言されるもののみ、プライベートにアクセスできます。
例えば、サブクラスからは親クラスのプライベートにアクセスできません。
class MyObject(object):
def __init__(self):
# パブリック
self.public_field = 2
# プライベート
self.__private_field = 4
def get_private_field(self):
return self.__private_field
パブリックはどこからでもドット演算子でアクセスできます。
obj = MyObject()
print(obj.public_field)
# 2
プライベートは.演算子でアクセスしようとすると例外が発生します。
print(obj.__private_field)
出力結果
AttributeError: 'MyObject' object has no attribute '__private_field'
__dict__
を用いてオブジェクトの属性を確認してみます。
print(obj.__dict__)
# {'public_field': 2, '_MyObject__private_field': 4}
パブリックは同じ属性名ですが、プライベートは __private_field
ではなく、_MyObject__private_field
になっています。
Pythonでは、プライベート属性の振る舞いを単純な属性名の変換で行っているためおきています。
そのため、以下のようにすればプライベートにも簡単にアクセスできます。
print(obj._MyObject__private_field)
# 4
しかし、この方法を用いても親の親のプライベートクラスにはアクセスできないです。
Pythonのプライベートは無理やり外部からアクセスできる点、多重継承になるとアクセスできなくなる点からそもそも、サブクラスを締め出すのではなく、
内部APIと属性を利用できるように考慮すべきであり、保護フィールドについてドキュメンテーションで説明した方がいいようです。
サブクラスとの名前の衝突を避けるときのみプライベートの使用を考慮すべきなようです。
カスタムコンテナ型は collections.abc を継承する
カスタムコンテナ型を正しく実装するには多数のメソッドが必要になります。
そのため、自分のコンテナ型を定義するのはかなり困難です。
それらを解消するために存在するモジュールが collections.abc です。
このモジュールはコンテナ型の典型的なメソッドをすべて提供す抽象基底クラスを定義しています。
この抽象基底クラスを作って、必要なメソッドを実装し忘れていると、モジュールが指摘してくれます。
from collections.abc import Sequence
class BadType(Sequence):
pass
foo = BadType()
# TypeError: Can't instantiate abstract class BadType with abstract methods __getitem__, __len__