タプルの型を調べようとしたらTypeError: 'type' object is not subscriptable
というエラーが出ました。結論としてはタプルじゃないものに添字演算子を使っていことが原因でした。
例:my_tuple[0]
※今回載せているソースはインタプリタ(ipython 3.1.0)上で実行したものです。そのためprint関数を使わなくても評価値が出力されます。
エラーを確認
原因は一言で言い表せますが、ここからタプルというものを調べていくと興味深いことがわかりました。まずは今回起きたエラーを見てみましょう。
foo = (object)
type(foo)
# => type
type(foo[0])
# => TypeError: 'type' object is not subscriptable
# 要素を2つにする
foo = (object, str)
foo[0]
# => object
type(foo)
# => tuple
数値でも試してみましたが、同じ結果が得られます。これはpythonがすべてはオブジェクトであるということから起きていると思います。
bar = (0)
type(bar)
# => int
bar[0]
# => TypeError: 'int' object is not subscriptable
# 要素を2つにする
bar = (1,2)
bar[0]
# => 1
type(bar)
# =>tuple
タプルにはどの型も入れれることを念のため確認。
foo = (object, 1)
type(foo)
# => tuple
要素が1つのタプルはどう定義する?
要素が1つのタプルはどう定義するのか?答えは公式ドキュメントにありました。
単要素のタプルにはカンマを使う: a, or (a,)
4. 組み込み型 — Python 3.4.3 ドキュメント
さっそく試してみました。
foo = (object,)
type(foo)
# => tuple
foo[0]
# => object
タプルを作っているのはカンマである
カンマを付けるとタプルと認識されるのですね。**「なるほど!丸括弧( )とカンマ,の組み合わせでタプルは作られるのか!」と思ったら間違いです。**ここがひっかかりやすいです。ですが、公式ドキュメントにご丁寧な説明がありました。
タプルは丸括弧で作成されるのではなく、カンマによって作成されることに注意してください。例外は空のタプルで、この場合には丸括弧が 必要です — 丸括弧のつかない “何も記述しない式 (nothing)” を使えるようにしてしまうと、文法があいまいなものになってしまい、よくあるタイプミスが検出されなくなってしまいます。
6. 式 (expression) — Python 3.4.3 ドキュメント
「カンマによって作成される」。これについて確かめていきましょう。
※ もちろん空のタプルの時は、カンマではなく丸括弧で作られます。
()
# => ()
type(())
# => tuple
1,2
# => (1, 2)
type(1,2)
# => TypeError: type() takes 1 or 3 arguments
type((1,2))
# => tuple
foo = 1,
foo
# => (1,)
type(foo)
# => tuple
なんと空のタプル以外では丸括弧は必要ありませんでした。ただし、関数の引数に渡す際にその場でタプルを生成しようとするときは丸括弧をつけないと複数の引数だと認識されてしまいます。上記の引数での丸括弧は、先にタプルを生成してから引数として渡すという、優先順位の高くするための演算子として使われています。
また、丸括弧なしで空のタプルが定義できてしまったら、空白(半角スペースではない)が作れないですね。空行とか末尾、そこらじゅうで空のタプルが量産されるかもしれません。
丸括弧の意味とは?
カンマがなかった時は何が返っていていたのでしょう?確認しみてましょう。
foo = (object)
foo
# => object
bar = (1)
bar
# => 1
(object)
# => object
(1)
# => 1
引数がそのまま返ってきていました。これについても公式ドキュメントに書いてありました。
丸括弧で囲われた式のリストは、個々の式が表現するものになります: リスト内に少なくとも一つのカンマが入っていた場合、タプルになります; そうでない場合、式のリストを構成している単一の式自体の値になります。
6. 式 (expression) — Python 3.4.3 ドキュメント
そういえば算術演算を行う際に、+や-の優先順位を上げるために丸括弧を使いますが、あれも丸括弧内の式の評価値を返しているのですよね。
1 + 3 * 2
# => 7
(1 + 3) * 2
# => 8
pythonの関数呼び出しに使う丸括弧は演算子ではないのか?
公式ドキュメントの字句解析のデリミタの一覧に丸括弧が載っていて、演算子は載っていませでした。pythonでは関数を呼び出す丸括弧は「関数呼び出し演算子」ではないのでしょうか?
wikipediaのC言語を見てみると、やはり丸括弧( )は「関数呼出し」という演算子となっています。誰か分かる人がいたら教えてください。