質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1071閲覧

Pythonでラベル名⇔値を相互に取得する方法

atabo

総合スコア9

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/11/18 10:31

編集2021/11/22 03:16

Pythonでラベル名⇔値を相互に取得したいとき、どのように書くのが良いかアドバイスを頂きたいです。

質問の詳細は以下になります。

class Config: label_a: int = 1 label_b: int = 0 label_c: int = -1

上記のようにしておくと、下記のようにして1という値を取得できます。

print(Config.label_a)

そこで逆に、1 という値がわかっているときにラベル名'label_a'を取得できるようにしておきたいのですが、

どのような方法が考えられますでしょうか?

下記のようにディクショナリで持たせておく方法も考えられると思いますが、

もう少しスマートな方法があるかも知れないと思い質問させていただきました。

label_map: Dict[str, str] = { 1: 'label_a', 0: 'label_b', -1: 'label_c', }

また、そもそもConfigクラスで下記のように書いておく方法もあるなとは思いました。

class Config: label2num Dict[str, int] = { 'label_a': 1, 'label_b': 0, 'label_c': -1, } num2label: Dict[int, str] = {v: k for k, v in label2num.items()}

クラス変数として持たせるときに上記がベストであれば私も今後そのようにしたいですが、

実は他の人が最近dataclass.dataclassを多用し始めており、

dataclassでディクショナリを定義しようとするとエラーになるようなので、

どうしようか・・・と考えているうちにわからなくなってきたため

皆さんがどう書くか、どう考えているか、色々な方のご意見を聞いて参考にしたいです。

よろしくお願いします。

追記(2021-11-22)

from dataclasses import dataclass, field from typing import Dict @dataclass(frozen=True) class Config: label_a: int = 1 label_b: int = 0 label_c: int = -1 _labels: Dict[int, str] = field(init=False) def __post_init__(self): object.__setattr__(self, '_labels', {v: k for k, v in vars(self).items()}) def get_label(self, val): return self._labels.get(val) config = Config() print(config.label_a) # 1 print(config._labels) # {1: 'label_a', 0: 'label_b', -1: 'label_c'} print(config.get_label(-1)) # label_c

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんな感じはいかがでしょう。

Python

1import dataclasses 2 3@dataclasses.dataclass(frozen=True) 4class Config: 5 label_a: int = 1 6 label_b: int = 0 7 label_c: int = -1 8 def key_of(self, val): 9 key = [k for k,v in vars(self).items() if v == val] 10 return key[0] if key else None 11 12config = Config() 13print(config.label_a) # 1 14print(config.key_of(1)) # label_a 15print(config.key_of(2)) # None

投稿2021/11/18 13:24

lehshell

総合スコア1147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atabo

2021/11/22 03:19

返事が遅くなりすみません、ご回答ありがとうございました!! 大変参考になり、頂いた内容をベースに少しだけ自分なりにアレンジしたものを上記の「追記」に記載しておりますが、 lehshellさんのおかげで一歩前進ができました。ありがとうございました!
lehshell

2021/11/22 07:46

参考までですが Python 3.9 以降であれば次のように書けます。 _labels: dict[int, str] = field(init=False) labels ではなく _labels としていますが、もし private 扱いを期待したいのであれば __labels にした方が良いと思います。 例として from dataclasses import dataclass, field @dataclass(frozen=True) class Config:     label_a: int = 1     label_b: int = 0     label_c: int = -1     __labels: dict[int, str] = field(init=False)     def __post_init__(self):         object.__setattr__(self, '_Config__labels', {v: k for k, v in vars(self).items()})     def get_label(self, val):         return self.__labels.get(val) config = Config() print(config.label_a) # 1 print(config.get_label(-1)) # label_c print(config.__labels) は AttributeError: 'Config' object has no attribute '__labels' にできます。 もちろん、以下でアクセスできてはしまいます。 print(config._Config__labels) # {1: 'label_a', 0: 'label_b', -1: 'label_c'}
atabo

2021/11/24 06:17

最後まで丁寧にありがとうございます! 頂いた内容に修正して使わせて頂きます!
guest

0

Pythonの文法ではConfig.label_b は書き換えることが可能です。
そのため

python

1>>> class Config: 2... label_a: int = 1 3... label_b: int = 0 4... label_c: int = -1 5... 6>>> print(Config.label_a) 71 8>>> Config.label_b = 1 9>>> print(Config.label_b) 101

となったときに、label_aもlabel_bも1になることになります。

逆に、1 という値がわかっているときにラベル名'label_a'を取得できるようにしておきたい
とのことですが、どちらも1のときには何を返せば良いのかがわかりませんね。

これをどうしたいのかが決っていないと実現しようがありません。

投稿2021/11/18 10:40

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atabo

2021/11/18 11:18

早速の回答ありがとうございます! 頂いた内容はなるほどと思いました。 そこで、今回実現したいこととしては、 冒頭に書いた事前に定義したラベル名と値を双方向で取得したいというものになるのですが、 この場合はどのような方法があるでしょうか?? やはりkeyがイミュータブルのディクショナリにすべきなのか、 dataclassでfrozen=Trueにするなどして別の方法があったりするのか? よろしくお願いします。
ppaul

2021/11/18 15:23

本当にやりたいことは何なのでしょうか? 「ラベル名」という言葉には文法的な意味はありません。 文字列を数字の対応をあらかじめ決めておいて、一方が与えられたら他方を取り出すようにしたいというだけであればいくらでも方法はあります。 なるべく簡単に書きたい、初期化は複雑でも良いから性能を出したい、絶対に改変されないようにしたい、というような条件は全てを満たすことは無理です。 どの条件を重視して、どの条件は満たさなくても良いかという説明無しに、「どのように書くのが良いか」と聞かれても、条件によります以上の答えはできないですよ。
atabo

2021/11/24 06:19

先日はご回答ありがとうございました! まだ勉強不足で明確に条件等を指定できずにすみません。 頂いた内容は大変に勉強になりました。 今後もこのサイトに質問することもあると思いますので今後ともよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問