- 締切済み
pythonの辞書型「ペア」のバリエーション
pythonの辞書型「ペア」のバリエーション pythonの辞書型は、わたしの集めた情報だと次のような書き方というか認識をしていました 「辞書型はキーと値のペアを要素とするデータの型」 :でペアをつくり、{}で記述をはさむ # 例 my_dict = {"key1": "ichigo", "key2": "apple", "key3": "orange"} print(my_dict["key1"]) # 出力 ichigo ところが次のコードは、keywords引数にあたるところに = で要素が入っています #---コード---------------- def shop(name, *arguments, **keywords): print("店名", name) for arg in arguments: print(arg) print("===おすすめ===") keys = sorted(keywords.keys()) for kw in keys: print(kw, ":", keywords[kw]) shop("らーめん八郎","11時開店","20時閉店",osusume1="醤油ラーメン", osusume2="チャーシュー麺",osusume3="わんたん麺") #---コード---------------- この記述が謎だったため、Bing AIに聞いたところ、これ(osusume1="醤油ラーメン"...)も辞書型とのことです 質問 {}で記述をはさんでいない、かつ、[]でキー指定もしていいない(print(my_dict["key1"]) のような) ですが、これはこれは正しいですか?(辞書型ですか?) これが辞書型なら、他にも「キーと値のペア」を書くバリエーションがあったらご教示ください
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- notnot
- ベストアンサー率47% (4900/10358)
> my_dict = {"key1": "ichigo", "key2": "apple", "key3": "orange"} いやべつに、 my_dict = {} my_dict["key1"]="ichigo" my_dict["key2"]="apple" my_dict["key3"]="orange" でも同じ結果です。 辞書データを作るには色々な方法があります。 shop("らーめん八郎","11時開店","20時閉店",osusume1="醤油ラーメン", osusume2="チャーシュー麺",osusume3="わんたん麺") の osusume1="醤油ラーメン" とかは、「キーワード引数」です。 def shop(name, *arguments, **keywords): の、** という記号が、「キーワード引数を辞書データに変換して変数に入れる」という意味を持っています。
- cametan_42
- ベストアンサー率62% (162/261)
> 最初の必須はわかるとして、どうやって arguments と keywordsの違いを実行環境が認識(区別)しているかがわかれば、後者をキーワードとして認識できる理由をわたしが納得できると考えました うん、発想はいい。 でもなかなかそれは難しいでしょう(笑)。出来ない、たぁ言わないけど、プログラミング言語の「実装方法」を知らないとならない。 一般的には、インタプリタには ・読み込み部(Read) ・評価部(Eval) ・出力部(Print) と大きく3つの部品があって、読み込み -> 評価 -> 出力の順でループする。 これをREAD-EVAL-PRINT Loop、略してREPLと呼びます。 また、読み込み部(READ)も2部分で構成されていて、それらは「字句解析部」と「構文解析部」に分かれる。 字句解析ってのは単純に、貴方が書いたプログラムのテキストを(それだけじゃないけど大まかには)「分かち書き」として単語毎に分割する。スペースやカッコで区切られた単語をバラバラにする。そして次にその単語に「意味」を与えるのが構文解析です。defと言う単語を見つけたら「関数定義がここから始まったな」と言う情報を付加する。そうして「構文木」を呼ばれるモノを生成していくんです。 この校舎の「構文解析」時点で、例えばdefがあったら「関数定義」、次に続くのが「関数名」、そして引数リストが存在して、そこで = を見つけると「キーワード引数だ」とタグをペタペタ貼って、それらデータの塊(それを抽象構文木(AST = Abstract Syntax Tree)と呼ぶ)を評価部に渡して「計算させる」わけです。 この理屈を今覚えるのはちと早いかもしんない。でも「いつか覚えた方がいい」ってのも事実です。貴方が決める事ですが。 このREPLと言う「仕組み」は実は言語インタプリタだけ、の机上の空論じゃなくって、「ソフトウェア設計」の要です。だから「いつか覚えないと」ならない事だけ、は事実です。別にプログラミング言語を作る必要はないけど、ソフトウェアが「入力」「計算」「出力」を持ってる以上構造的には同じなんで避けられません。 古い文書でPython2.x用ですが、参考文書を挙げておきます。 ((Pythonで) 書く (Lisp) インタプリタ): http://www.aoky.net/articles/peter_norvig/lispy.htm 極端に言うと、似たような事をPythonのインタプリタも中で行ってるわけです。
お礼
ありがとうございます 言語において=は代入式の代入演算子だとおもいこみがありましたが、=をみつけているということで、キーワード引数が動作するイメージができました わたしはテスターで、プログラマーではないので深くつっこんで理解する予定はないですが、pythonはExcel VBAよりはるかに奥深いのでまた質問させてください
- cametan_42
- ベストアンサー率62% (162/261)
う〜んとね・・・・・・。 まず、 >pythonの辞書型は、わたしの集めた情報だと次のような書き方というか認識をしていました > >「辞書型はキーと値のペアを要素とするデータの型」 >:でペアをつくり、{}で記述をはさむ これは正しい、です。 んでだ。 まず最初に言うと、(Python用語じゃないけど)オプショナル引数、とかキーワード引数ってのが「プログラミング言語に現れた」ってのは歴史的には結構新しいんです。 少なくとも(アメリカ国内の話だけど)、公式に「言語仕様」として定義されたプログラミング言語としてはANSI Common Lispと言うプログラミング言語が最初か、あるいは最初の一つでした。 Common Lisp: https://ja.wikipedia.org/wiki/Common_Lisp Common Lispが出るまで、オプショナル引数とか、キーワード引数を備えた関数定義、なんて無かったか、あるいは似たような事をやろうとするとクソメンド臭かった。 んで、90年代に登場したPythonとか、あるいはライバルのRubyなんつーのは、このCommon Lispの言語設計にある程度、もしくは物凄く影響を受けている。 事実、C言語とか、あるいは、Rubyより登場が遅いJavaなんかにはこういう機能がありません(Javaも仕様がちょこちょこ変わってるけど、確か無かったと思う)。 んで、だ。 最初に言っておくと、「データ型の仕様」と、内部的に「関数定義法をどーするか」と言った「実装の問題」は別問題です。 平たく言うと、「Pythonは関数定義法でキーワード引数を辞書型を利用して実装してる」とは言えるけどそれ以上の意味はないです。 ちと見てみようか。 例えば次のような関数を定義してみる。 def spam(*arguments): return arguments 一般的に、オプショナル引数は(必ずしもそうじゃないけど)可変長引数を解決する手段として提供される。 「可変長引数」ってのは「関数に何個引数が渡されるか分からない」って事。通常はプログラマ側が「引数がx個ある関数を定義」するんだけど、たまに「何個でも引数が欲しい」って場合があるんだな。Pythonではそれを解決する場合、引数の先頭にアスタリスク(*)をつける。 で、上の関数は引数をそのまま返す、と。 すると実行時、どうなるか、と言うと。 >>> spam() () 引数を何も与えないと空のタプルが返る。つまり、Pythonの実装上、関数定義時に「可変長引数」を使った場合はそれらは「タプルにまとめられる」様に「実装してる」ってこった。 従って、次のような実行結果になる。 >>> spam(1, 2, 3) (1, 2, 3) >>> spam(1, 2, 3, 4, 5) (1, 2, 3, 4, 5) ここで知るのは、「タプルの定義方法」と「関数定義の可変長引数はタプルとしてまとめられるように設計されてる」ってのはコッチ側(ユーザー側)にとっては関係ねぇ、って事だ。平たく言うと、「こうなってる」ってのはプログラミング言語設計者側の「趣味」であって(笑)、要は「理論的根拠がある」って話ではない。 もうちょっと難しく言うと、ユーザーが関数定義をすると、Pythonインタプリタ内でその関数定義を「構文解析」して、可変長引数を見つけるとタプルに変換するように「設計してる」って事だ。そしてこれは「ユーザーが出来る」範疇にない、ってのが原則。だからPythonが内部的に出来る事が貴方が出来るとは限らない(何故なら貴方はPythonの外部に存在するから、だ)。 同様に、キーワード引数も「実装上」、辞書に「内部的に」変換される、って事だ。 def spamspam(**keywords): return keywords >>> spamspam() {} 何だか知らんが「空のキーワード引数」を与えると関数spamspamwは空の辞書を返す。 つまり、Pythonの内部に於ける「構文解析上」、キーワード引数はタプルの代わりに辞書型へと「まとめて」変換されるけど、貴方がPython内部にいない限り、この動作は関係ない、って事。 要は、 >>> spamspam(hoge = 'foo', fuga = 'bar', piyo = 'baz') {'hoge': 'foo', 'fuga': 'bar', 'piyo': 'baz'} と関数定義時に'='を利用して記述すると、Pythonインタプリタが「構文解析」して内部的には「辞書型に変換してる」だけで、貴方が同様の事をしても「辞書型になる」わけじゃないんだ。 単なる設計者の「都合」でそういう実装にしてるだけ、です。 このように、ユーザーに許された「データ型の定義法」、とプログラミング言語設計上の「決定」そしてその「実装」は直接は関係ないんで、あまり囚われない方がいいです。設計者とユーザーは通常同じ立ち位置にはいません。
お礼
ありがとうございます 投稿のあとリファレンスサイトと、AI使い、そもそも何を理解できてないのかずっと調べていました 最初の「必須」と「キーワード引数」のあいだにあるargument(s)について、タプルの最初の必須はわかるとして、どうやって arguments と keywordsの違いを実行環境が認識(区別)しているかがわかれば、後者をキーワードとして認識できる理由をわたしが納得できると考えました 結論としては、AIがいうには、 必須、位置引数、キーワード引数 の形になっているらしいです これでリファレンスページにある >関数を kwarg=value という形式の キーワード引数 を使って呼び出すこともできます わかったので質問削除しようと開いたところ、回答いただきました ありがとうございます あと年男です。よろしくお願いします笑
お礼
ありがとうございます >** という記号が、「キーワード引数を辞書データに変換して変数に入れる」 実は* や**の動作がいまいちイメージできてないので、別質問をたてるとおもいます またよろしくお願いします