Skip to content

Instantly share code, notes, and snippets.

@AnchorBlues
Created May 19, 2021 02:34
Show Gist options
  • Save AnchorBlues/6fbc8e96de5c2f90b782aa6793e964fb to your computer and use it in GitHub Desktop.
Save AnchorBlues/6fbc8e96de5c2f90b782aa6793e964fb to your computer and use it in GitHub Desktop.
辞書の代わりに用いることが出来るオブジェクト比較
from collections import namedtuple
from typing import NamedTuple
from dataclasses import dataclass, asdict
# Python 3.7.3 で検証
D = namedtuple('D', ('a', 'b', 'c'))
# 一部のメンバだけデフォルト値指定、というのができない? また、mypyに怒られる(正式な書き方じゃない?)。
D.__new__.__defaults__ = (1, None, 0)
class TypingD(NamedTuple):
"""
記述がラク
"""
a: int
b: dict
c: int = 0
class ClassD:
"""
記述が面倒くさい...
"""
def __init__(self, a: int, b: dict, c: int = 0) -> None:
self.a = a
self.b = b
self.c = c
@dataclass
class DataClassD:
"""
記述がラク
"""
a: int
b: dict
c: int = 0
if __name__ == "__main__":
# 通常の辞書
d = {
'a': 1,
'b': {'d': 3},
'c': 0
}
print(d) # きれいな表示になる({'a': 1, 'b': 2})
print(d['a']) # 補完が効かない
# collections.namedtuple
d2 = D(1, {'d': 3})
print(d2) # きれいな表示になる(D(a=1, b={'d': 3}, c=0))
print(d2.a) # 補完が効く
print(d2._asdict())
# typing.NamedTuple
d3 = TypingD(1, {'d': 3}) # ここで補完が効かない!
print(d3) # きれいな表示になる(TypingD(a=1, b={'d': 3}, c=0))
print(d3.a) # 補完が効く
print(d3._asdict())
# クラス
d4 = ClassD(1, {'d': 3})
print(d4) # 汚い表示になる&中身が確認できない(<__main__.ClassD object at 0x000....)
print(d4.a) # 補完が効く
print(d4.__dict__)
# dataclasses.dataclass
d5 = DataClassD(1, {'d': 3})
print(d5) # きれいな表示になる(DataClassD(a=1, b={'d': 3}, c=0))
print(d5.a) # 補完が効く
print(asdict(d5))
@AnchorBlues
Copy link
Author

AnchorBlues commented May 19, 2021

サマリ:

定義の記述の楽さ メンバのデータ型の指定 デフォルト値の指定 インスタンス生成時の補完 メンバアクセス時の補完 辞書への変換
dict × × × × -
collections.namedtuple ×
typing.NamedTuple ×->○ (※)
class ×
dataclasses.dataclass

※ python 3.7.3 で検証した結果補完効かず、3.8.8 で検証した結果補完が効きました。

@AnchorBlues
Copy link
Author

d3 = TypingD(1, {'d': 3}) # ここで補完が効かない!
ということですが、python 3.8.8 で検証した結果、普通に補完が効きました。となると、NamedTupleとdataclassにほとんど差がないということになりそうですね。

@AnchorBlues
Copy link
Author

↑pythonのバージョンの問題じゃなくて、別の型アノテーション系のライブラリのバージョンとか、vscodeのバージョンとか、別の問題かもしれませんが。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment