web-dev-qa-db-ja.com

データクラスオブジェクトの属性を置き換える

dataclass インスタンスの属性を置き換えたいのですが、これはnamedtuple._replace()に類似しています。つまり、元のオブジェクトの変更されたコピーを作成します。

from dataclasses import dataclass
from collections import namedtuple

U = namedtuple("U", "x")

@dataclass
class V:
    x: int

u = U(x=1)
u_ = u._replace(x=-1)
v = V(x=1)

print(u)
print(u_)
print(v)

これは次を返します:

U(x=1)
U(x=-1)
V(x=1)

データクラスオブジェクトでこの機能を模倣するにはどうすればよいですか?

9
BayerSe

Pythonデータクラスモジュールには、データクラスインスタンスのフィールド置換用のパブリックAPIがあり、文書化されています ここ 。この機能は、モジュールレベルのヘルパー関数によって提供されます。

from dataclasses import replace

使用法はcollections.namedtupleとは異なります。この機能は、生成された型のメソッドを介して提供されていました(補足:namedtuple._replace は文書化/公開されています。この名前の選択は、作成者によって「後悔」と呼ばれていました。回答の最後にあるリンクを参照してください)。

使用例:

>>> from dataclasses import dataclass, replace
>>> @dataclass
... class V:
...     x: int
...     y: int
...     
>>> v = V(1, 2)
>>> v_ = replace(v, y=42)
>>> v
V(x=1, y=2)
>>> v_
V(x=1, y=42)

設計の背景については、PyCon 2018のトークを参照してください- データクラス:すべてのコードジェネレーターを終了するコードジェネレーターreplace AP​​Iについては、namedtupledataclassesの間の他の設計上の違い、およびいくつかのパフォーマンスの比較とともに、詳細に説明されています。

8
wim

dataclassは、特別な__init__メソッドと、型注釈付き属性に基づく他の「ボイラープレート」メソッドのホストを自動的に作成するための単なる構文糖衣です。

クラスが作成されると、他のクラスと同じようになり、その属性を上書きしたり、インスタンスをコピーしたりできます。

import copy

v_ = copy.deepcopy(v)
v_.x = -1

属性が何であるかに応じて、copy.copyのみが必要になる場合があります。

0
ely