質問するログイン新規登録
Python 3.x

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

Q&A

解決済

1回答

684閲覧

python3 可変長引数を持つ関数にて引数の合計及び平均を求めたい

Omihiro

総合スコア9

Python 3.x

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

0グッド

0クリップ

投稿2023/02/23 15:18

0

0

実現したいこと

可変長引数を持つ関数にて引数の合計及び平均を求めるコードについて理解を深めたい

前提

Pythonを学習し始めたてで、調べてもどうしてもわからないので、ここで質問させて頂きました。
実現したいことに記載されているコードは該当のソースコードに記述いたします。

発生している問題・エラーメッセージ

なし

該当のソースコード

python

1def calc(**items): 2 nums = items["nums"] 3 s = sum(nums) 4 if items["type"] == "sum": 5 return s 6 elif items["type"] == "avg": 7 return s / len(nums) 8 else: 9 return None

試したこと

items = {"nums":3 , "type":4 , "nums":7}
nums = items["nums"]
print(nums) ⇒7
このように、この場合のitems[]はそのキーに該当する値を取り出すのに対し、
該当のソースコード2行目では数値の入ったリストをnumsに格納しているということなのですが、
どうしてそういう解釈になるのでしょうか?

どなたか、ご教授頂けますと幸いです。
宜しくお願いします。

補足情報(FW/ツールのバージョンなど)

python3.8.8

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

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

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

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

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

melian

2023/02/23 15:37

おそらく、calc 関数の呼び出し方が、 calc(nums=[3, 4, 7], type="sum") や、 calc(**{"nums": [3, 4, 7], "type": "sum"}) となっているのでしょう。
Omihiro

2023/02/24 10:23 編集

melianさん その通りです。 とある講座の動画で該当ソースコード及び以下のcalc関数 の呼び出しを行っておりました。 calc(type="sum",nums=(1,2,3,4)  ⇒ 10(返り値) calc(nums=(1,2,3,4),type="sum") ⇒ 10(返り値) calc(type="avg",nums(1,2,3,4)) ⇒2.5(返り値) ただ、どうしても nums = items["nums"]がリストの要素を格納するにしか見えなくて。。
guest

回答1

0

ベストアンサー

このコードは質問者さんが書いたものではなさそうですね。
まずは質問に答えます。

どうしてそういう解釈になるのでしょうか?
プログラム中の s = sum(nums) の式でsum関数を使ってnumsの合計を計算しています。 sum関数は、引数にiterableを取ります。
https://docs.python.org/ja/3/library/functions.html?highlight=sum#sum

iterableとなるオブジェクトにはいくつかありますが、よく使うのはリストです。
https://docs.python.org/ja/3/library/stdtypes.html?highlight=list#iterator-types
https://docs.python.org/ja/3/library/stdtypes.html?highlight=list#sequence-types-list-tuple-range

質問のコードではこの中のどれかというと、この関数は引数で与えられた複数の数値の合計もしくは平均を計算するもののようですから、sum関数の引数になるのはその対象となる数値が入ったリストだろうということになります。

■ おまけ
プログラムについて思いついたことを書いてみます。

items = {"nums":3 , "type":4 , "nums":7}
pythonの辞書(dict)は同じキー、ここではnums、のエントリを複数持つことはできません。上のように初期化すると、右のものが上書きする形になり、 itemsの内容は {"type":4 , "nums":7} となります。

def calc(**items):
関数定義で引数に **を付けると、その引数の辞書のキーの文字列を引数に持つ変数が引数として割り当てられます。
しかし、その値を定義の中で使っていませんので、この**を削除するか、本体を書きなおす必要があります。

items["type"] == "sum":
itemのチーtype には sum か avg なので、質問のような{"nums":3 , "type":4 , "nums":7} では計算ができません。

可変長引数
タイトルを見ると、可変長引数と書いてありますが、どういう意味で使っていますか?
calc関数にどのように引数を渡したいのですか?


追記その1

また「nums = items["nums"]」について
下の方にある関数の呼び出しを例にとると、calc(type="sum",nums=(1,2,3,4)  ⇒ 10(返り値)
私は最初、"nums"というキーの要素をnumsに格納だと思ったのですが、calcの呼び出し例をみると、第二引数でnums=(1,2,3,4)、つまりキーがnumsで値がタプル(1,2,3,4)の場合だと、先ほどの「nums = items["nums"]」に当てはめて考えると、「辞書items」の「キーnums」の「値(1,2,3,4)」をnumsに格納するという意味でよろしいでしょうか?

はい。

だとすると、nums = items["nums"]ではくnums = items[nums]にならないのはなぜなのでしょうか?

items[nums] としたときの、nums は文字列ではなく変数名だからです。 その時点で変数numsにどのような値が入っているかによって、結果がかわります。 「"nums"」 は numsという文字列を表わします。
辞書を作る時も同様です。 「{"type":"sum", "nums":(1,2,3,4)} 」 と「 {type:"sum", nums:(1,2,3,4)}」は通常違う辞書です。 後者は type, numsは変数です。

関数定義のときの仮引数 type や nums と、 辞書のキー "type" や "nusms" を 混同しているのではないかと思います。 仮引数は変数名なので、""は無し、 辞書のキーには変数名は使えないので、この場合のように文字列を使うことが多いですね。
関数への引数に辞書を使うと、辞書のキー文字列と同じ名前の仮引数に値を設定することができるので、混同しているのでしょう。

※該当のソースコードは、とある講座のソースコードをそのまま貼り付けたもので、その際にcalc関数の呼び出しを行っておりました。以下がその呼び出しです。
calc(type="sum",nums=(1,2,3,4)  ⇒ 10(返り値)(type及びnumsの順序に決まりはない)
calc(nums=(1,2,3,4),type="sum") ⇒ 10(返り値)
calc(type="avg",nums=(1,2,3,4)) ⇒2.5(返り値)

なるほど。 この関数は不通に書けば、以下のような書き出しになるはずです。 この関数で上記の呼び出しは正常に動作します。

python

1def calc(type, nums): # 関数定義 の先頭のみ 2calc("sum", (1,2,3,4)) # 呼び出し1

pythonには、引数を辞書で受ける書き方があり、参考にしたサイトはそれを説明するためのものなのでしょう。

投稿2023/02/24 01:32

編集2023/02/24 14:51
TakaiY

総合スコア14570

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

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

Omihiro

2023/02/24 12:23 編集

早速のご回答、本当にありがとうございます。 ・sum()の引数はイテラブル、つまり一言で言うと「繰り返し可能なオブジェクト」のこと。  for文において、文字列や数字を繰り返すことが可能であり、「for i in A:のAの部分に用いることができるもの」といえる。 例えばリスト、タプルやrange関数で生成したオブジェクトなどがイテラブルに該当。  https://magazine.techacademy.jp/magazine/28147(こちらを参照しました) つまりsum()の()にはリストやタプル等が入ることは理解しました。 有難うございます。 また「nums = items["nums"]」について 下の方にある関数の呼び出しを例にとると、calc(type="sum",nums=(1,2,3,4)  ⇒ 10(返り値) 私は最初、"nums"というキーの要素をnumsに格納だと思ったのですが、calcの呼び出し例をみると、第二引数でnums=(1,2,3,4)、つまりキーがnumsで値がタプル(1,2,3,4)の場合だと、先ほどの 「nums = items["nums"]」に当てはめて考えると、「辞書items」の「キーnums」の「値(1,2,3,4)」をnumsに格納するという意味でよろしいでしょうか? だとすると、nums = items["nums"]ではくnums = items[nums]にならないのはなぜなのでしょうか? お手数おかけしますが、宜しくお願いいたします。 ■おまけ、で辞書が複数のエントリを持つことができないこと、そして複数ある場合は右側の方で上書きされるんですね。 とても参考になります。 items["type"] == "sum": これはキーtypeがsumの場合という意味なんですね。。。 (とあるリストの要素(文字列)が"sum"と等しい場合と解釈しておりました) ※該当のソースコードは、とある講座のソースコードをそのまま貼り付けたもので、その際にcalc関数の呼び出しを行っておりました。以下がその呼び出しです。 calc(type="sum",nums=(1,2,3,4)  ⇒ 10(返り値)(type及びnumsの順序に決まりはない) calc(nums=(1,2,3,4),type="sum") ⇒ 10(返り値) calc(type="avg",nums=(1,2,3,4)) ⇒2.5(返り値) タイトルを見ると、可変長引数と書いてありますが、どういう意味で使っていますか? ⇒講座のタイトルとして、引数にタプルおよび辞書の扱い方を習っておりました。講座では、 ・長さを自由に変えられる引数。 ・与える長さが一定ではない場合に用いる。 ・引数はタプルもしくは辞書として渡る。 と記載されていましたので、引数となる変数(オブジェクト)を複数使用する場合というイメージでしょうか。 calc関数にどのように引数を渡したいのですか? ⇒現在まだ学習中であり、いまはこういう風に引数に値を渡す書き方があるんだなということを学んでいければと思います。
Omihiro

2023/02/27 16:37

早々の返信ありがとうございます。 追記にて、 「関数への引数に辞書を使うと、辞書のキー文字列と同じ名前の仮引数に値を設定することができるので、混同しているのでしょう。」 確かに混同しております。。。 呑み込みが悪く申し訳ありません。 calc(type="sum",nums=(1,2,3,4)  のtype及びnumsは文字列という認識でよろしいでしょうか? それとも、仮引数なのでしょうか??
TakaiY

2023/02/28 02:31

仮引数ですよ。 以下、長くなっちゃいました。 def calc(type ,nums): のように定義したとき、 type と nums は仮引数です。 これを呼ぶとき通常は、以下のように書きますね。 calc("sum", (1,2,3,4)) 呼び出し時には通常は仮引数を書きません。 引数は左から順に仮引数に対する実引数として扱われます。 pythonでは、関数呼び出し時に仮引数を指定できます。 calc(type="sum",nums=(1,2,3,4)) これは仮引数を指定しないときと同じです。 calc(nums=(1,2,3,4), type="sum") 仮引数名を指定することで、順序を気にしなくてもよくなります。 定義時にデフォルトの値を設定することができます。 たぶんこれが、混乱の元だと思います。 def calc(type="sum",nums=[]): 定義に書かれているのも 仮引数ですね。 この形で定義すると、呼び出しで引数を飛ばすことができます。ただし、仮引数名の指定が必要です。 calc(nums=(1,2,3,4)) 引数を別途辞書で用意しておくことができます。 arg = {"type": "avg", "nums": (7,8,9)} calc(**arg) このとき、仮引数名は対応する**文字列** とします。 ここで {type: "avg", nums: (7,8,9)} 書いてしまうと、python文法的に、typeもnumsも変数名扱いになって、その時点での値になってしまいますから、いたしかないところ。 関数定義時に辞書として受け取ることを前提にすることもできます。 def calc(**items): これに、同じargを渡すと、 arg = {"type": "avg", "nums": (7,8,9)} calc(**arg) itemsに{"type": "avg", "nums": (7,8,9)} がわたされます。
Omihiro

2023/03/03 13:02

丁寧な解説有難うございます! 辞書に対するイメージが前より鮮明になりました! 分かりやすく例を交えて説明して頂けるだけではなく、こういう書き方もできるというプラスαで教えて頂き 本当にありがとうございました。 pythonの学習を初めてまだ、1か月程ではありますが、自分のやりたい分野に向けてこれからも頑張ります! 未経験からのエンジニアはハードルも高くかなりしんどいという話も聞きますが、とりあえずは自分ができること、好きなこと優先で頑張ります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問