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

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

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

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

Q&A

解決済

2回答

998閲覧

pythonのキーワード引数とアンパックについてです

Ryoruri

総合スコア3

Python 3.x

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

1グッド

1クリップ

投稿2023/06/04 05:27

python3 についての質問です。

ボールドテキスト

お聞きしたい点が2つあります。
その2つがなぜ 実行後 そうなるのかを教えていただけると幸いです。
まずは1つ目の問題からです。
1つ目のスクリプトファイルはこちらです。

 def calcData (**arg) :
total = 0
for ky in arg :
print(ky + ' : ' +str(arg[ky])
total += arg [ky]
print( 'total: ' + str(total))

calcData(A=98, B=76, C=54, D=56, E=78,
F=90)

実行結果
A:98
B:76
C:54
D:56
E:78
F:90
total :452

・98がまずarg に代入されるとして、
なぜ def calcData(**arg): でargに
'A':98が代入されるのに、
for ky in arg: で argから kyに'A':98が入り
print('A':98 + ' : '+ str(98)
0 += 'A':98 [98]
.
. (略)
実行後
'A':98 : 98 (〜略)
とならないのか?

2つ目のスクリプトファイルはこちらです。
data= (50,100,5)
list(range(*data))
実行結果

[50,55,60,65,70,75,80,85,90,95]

なぜタプルのままではなくてアンパックをして3つの引数にしなければならなかったのか?アンパックしなくても実行結果は同じではないのか、ということです。

何か説明不足があるかもしれません、すみません。

xail2222👍を押しています

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

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

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

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

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

Ryoruri

2023/06/04 07:58

現在パソコンが使えない状況下において専門書を5冊用いても理解しかねるため質問をさせていただきました。
guest

回答2

0

質問のコードを実行した場合、argに代入されるのは、
{'A':98, 'B':76, 'C':54, 'D':56, 'E':78,'F':90} という辞書(dictオブジェクト)。

で、リストとは異なり、辞書({'A':98, 'B':76, 'C':54, 'D':56, 'E':78,'F':90})にたいしてfor ky in arg:のように、for文を使うと、
左のkyには、辞書の各要素の全体({'A':98})ではなく、辞書の各要素の「キー」({'A':98}のキーである'A')が順次代入される。

だから
print(ky + ' : ' +str(arg[ky])) を実行すると
'A':98 : 98 (〜略)
とならず
A : 98 (〜略)
となる。

辞書とリストで扱いが異なるのはなんでなの?って思うかもしれないけど、そういうものだと覚えるしかない。

なぜタプルのままではなくてアンパックをして3つの引数にしなければならなかったのか?アンパックしなくても実行結果は同じではないのか、

アンパックしなくても実行結果は同じではないのかって疑問を持つなら、アンパックせずに試してみればいい。

data= (50,100,5) print(list(range(data)))

これを実行すると
TypeError: 'tuple' object cannot be interpreted as an integer
(検索サイトによる翻訳「'Tuple'オブジェクトは整数として解釈できません」)
というエラーになる。

なんでかというと、range関数は、引数に、1個以上3個以下の「整数値」しか受け取れないから。

range関数に対して、
(50,100,5) というタプルをアンパックせずに渡すと、
「整数値」しか受け取れないrange関数にタプルという「整数値ではない」オブジェクトを渡すことになるから、エラーになる。

一方、 *をつけてdataを3つの整数値にアンパックした場合は、range関数に3つの「整数」の引数を渡すことになるんで、正常に実行できる。

(「3つ以下の要素を持つタプルを渡したら自動的にアンパックしてくれれば直感的で楽なのにどうしてそうなってないの?」って思うかもしれないけど、そういうものだと割り切るしかない)

投稿2023/06/04 06:17

編集2023/06/04 09:33
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Ryoruri

2023/06/04 08:22

ご回答感謝します 繰り返しになってもうしわけないのですが、 for ky in arg: のky には必ずキーのみがバインド(ひもづけられる)されてバリュー(値)は毎度無視されるということであっているでしょうか?
退会済みユーザー

退会済みユーザー

2023/06/04 09:12 編集

> for ky in arg: のky には必ずキーのみがバインド(ひもづけられる)されてバリュー(値)は毎度無視されるということであっているでしょうか? argが辞書(dictオブジェクト)の場合はそうなります。 あと別コメントの > data=(50,100,5,) のインデックス番号5の後ろにいくつ値があっても最初の"開始"に全て吸収されるかたちになる、という考え方で良いでしょうか? これはエラーになります。回答に書いてますけど、rangeは1個以上3個以下の引数しか渡せません。 たとえば、5の後ろにもう1つ追加して data=(50,100,5,99) で print(list(range(*data))) を実行すると TypeError: range expected at most 3 arguments, got 4(検索サイトによる翻訳:rangeは多くとも3つの引数が期待されていますが、4つを得ました) というエラーになります。 最初の質問もそうですが、どうなるかを聞く前に、まず自分で試す癖をつけてください。そのうえでエラーメッセージがでればそれを検索して調べ、調べてもわからなければ、そのエラーメッセージをコメントなり質問なりに書いて聞くようにしてください。
Ryoruri

2023/06/04 09:29

重ねてのご回答ありがとうございます。 Googlecolab にて実行のエラーおよび改善後の遂行を確認したのですが、なぜ遂行できているのかが調べたところ難解に感じ、砕いた説明が欲しくてこちらでの質問になりました。 読み解きの苦手、拙さでご不快にさせてしまいまして誠に申し訳ありません。
guest

0

ベストアンサー

1つめ
pythonでは、関数定義の仮引数にアスタリスク2つ(**)を使うことで、全てのキーワード引数(A=98のような形)を含んだ辞書として受け取ることができます。
def calcData (**arg) となっているので、 calcData(A=98, B=76, C=54, D=56, E=78,F=90)と呼び出すと、仮引数argには{'A':98, 'B':76, 'C':54, 'D';56, 'E':78, 'F':90}という値が設定されるのです。

その2
pythonでは、関数呼び出しの引数にアスタリスク1つ(*)を使うことで、リストをバラして関数に渡すことができます。

python

1data= (50,100,5) 2list(range(*data))

rangeの引数は、(開始,終了, ステップ)というリストです。 もし、ここで、range(data)としてしまうと、 最初の引数である「開始」に (50, 100, 5)が設定されてしまい、エラーとなりますが、「*data」とすることで、dataの内容をバラしてそれぞれを引数とすることができるのです。


2つの質問は仮引数の「**」と、実引数の「*」という違うものについてのものなので、ちょとわかりにくいかもしれません。
実引数と仮引数の「*」と「**」表記についていろいろ調べてみるといいでしょう。
公式だと、 用語集
https://docs.python.org/ja/3.5/glossary.html
の parameter(仮引数)のところと、argument(実引数)のところに説明があります。
いろいろなサイトで説明されているので、見てみるといいでしょう。

投稿2023/06/04 06:00

編集2023/06/05 00:53
TakaiY

総合スコア13788

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

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

Ryoruri

2023/06/04 08:31

ご回答感謝します その2 の部分について質問なのですが、 (開始,終了, ステップ)ということなので data=(50,100,5,) のインデックス番号5の後ろにいくつ値があっても最初の"開始"に全て吸収されるかたちになる、という考え方で良いでしょうか?
jbpb0

2023/06/04 14:39

TakaiYさん > 2つの質問は仮引数の「**」と、実引数の「*」という違うものについてのものなので、ちょとわかりにくいかもしれません。 実引数と仮引数の「*」と「**」表記についていろいろ調べてみるといいでしょう。 の「**」と「*」が、Markdownの記号と解釈されてるようで、見えなくなってます
Ryoruri

2023/06/04 23:53

jbpb0様 ご回答ありがとうございます。 みなさまのおかげで納得できました。 貴重なご意見ありがとうございます。
TakaiY

2023/06/05 00:54

気づくの遅くてすみません。 解決しているようですが、修正しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問