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

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

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

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

Q&A

解決済

6回答

2421閲覧

pythonで宣言なのか代入なのか混乱する

ruei

総合スコア284

Python

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

0グッド

2クリップ

投稿2018/10/31 05:36

pythonを書くときに

var = hogehoge

としたとき、代入なのか宣言なのか混乱してしまい、困っています。

「宣言だと思って書いたら、すでに宣言されていた」
「代入だと思って書いたら、まだ定義されていなかった」
というときにエラーが出てほしいです。

このような機能はエディタの機能としてあるのでしょうか?

現在はEmacs23.4.1を何も入れずに使っています。

bash

1emacs --version 2GNU Emacs 23.4.1 3Copyright (C) 2012 Free Software Foundation, Inc. 4GNU Emacs comes with ABSOLUTELY NO WARRANTY. 5You may redistribute copies of Emacs 6under the terms of the GNU General Public License. 7For more information about these matters, see the file named COPYING.

python初心者です。

快適に書く方法があったら教えてください。

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

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

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

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

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

Udomomo

2018/10/31 05:42

Pythonでは、何も値を入れずに変数宣言だけすることはできません。コードを書くうえで何か問題が起こっているのでしょうか?
ruei

2018/10/31 05:45

一度目の代入と、二度目の代入を区別したい(文字の色をエディタのほうで変えてほしい)ということです。
guest

回答6

0

ベストアンサー

そもそもpythonに変数の宣言という概念はありません。「すべては代入」です。どのタイミングで変数が作られるかは実行時に決まります(動的言語とはそういうものです)。

極端な例

python

1import random 2 3tmp = random.randrange(10) 4if 0 <= tmp < 3: 5 hoge = 10.25 6elif 3 <= tmp < 6: 7 hoge = "fuga" 8elif 6 < tmp < 10: 9 hoge = tmp 10print(hoge)

どの条件がTrueになってどこでhogeが作られるか? は実行する前には神のみぞ知ります。

上のコードは実はバグを仕込んであり、tmp==6のときはhogeが作られずそのままprintのときにNameErrorになります。が、そうなるかどうかすらも実行時に決まります。


そもそもpythonの「変数」とは何かというと、ただの名前です。そして「代入」とは名前にオブジェクトを束縛することです。

Python には宣言がなく、コードブロックのどこでも名前束縛操作ができます。

4. 実行モデル — Python 3.6.5 ドキュメント


emacsならこの辺りを入れれば「undefined name ***」は実行前に出してくれるようになります(ただし冒頭のコードみたいなものを完全に扱える訳ではないので注意)。

もっと強い支援がほしければjediも検討してください。

両方入れれば21世紀のエディタと同程度の使い勝手は確保できます。

投稿2018/10/31 07:56

編集2018/10/31 08:11
hayataka2049

総合スコア30933

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

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

ruei

2018/10/31 08:07

この回答を見て、変数のスコープがifやforの外に出るということを初めて知りました。 変数が作られるタイミングが実行時まで不定というのが分かりました。 リンク先を読んでみます。ありがとうございます。
hayataka2049

2018/10/31 08:13

ifやforはスコープを作りません。関数、内包表記、クラスなどがスコープを作ります
otn

2018/10/31 12:53

この辺は言語に依りますね。Rubyだと、乱数が6だとhogeはnilです。
guest

0

指定した変数がすでに存在するかどうかは以下で確認できます。

python

1# ローカル変数 test が存在するかどうか 2if 'test' in locals(): 3 print('local variable `test` already exists.') 4To check the existence of a global variable: 5 6# グローバル変数 test が存在するかどうか 7if 'test' in globals(): 8 print('global variable `test` already exists.') 9 10# オブジェクト obj は属性 test を持っているかどうか 11if hasattr(obj, 'test'): 12 print('object has attribute `test`.')

「宣言だと思って書いたら、すでに宣言されていた」
「代入だと思って書いたら、まだ定義されていなかった」
というときにエラーが出てほしいです。
このような機能はエディタの機能としてあるのでしょうか?

C/C++/Java/C# など静的型付き言語は、int a となっていたら宣言、a だけであれば変数の参照と区別できますが、Python の場合はそのような区別がないため、コードをパースした段階では区別できません。

以下の例を見ていただけるとわかると思いますが、コードを実行するまでどちらのメソッドでオブジェクトの attribute 変数が作られたか判断できません。

python

1class Sample: 2 def hoge(self): 3 if hasattr(self, 'var'): 4 print('hoge() assign') 5 else: 6 print('hoge() declaration and initialzation') 7 self.var = 'test' 8 9 def fuga(self): 10 if hasattr(self, 'var'): 11 print('fuga() assign') 12 else: 13 print('fuga() declaration and initialzation') 14 self.var = 'fuga' 15 16sample1 = Sample() 17sample1.hoge() # hoge() declaration 18sample1.fuga() # fuga() assign 19 20sample2 = Sample() 21sample2.fuga() # fuga() declaration and initialzation 22sample2.hoge() # hoge() assign

結論というと、コードを書いている段階では構文のパースは行っていてもコードを実行しているわけではないので、その段階でエディタでは宣言か代入かは判断できないので実現不可能となります。

追記

一応、Visual Studio Code の pylint で定義していない変数の参照は検出できるようです。

イメージ説明

投稿2018/10/31 07:03

編集2018/10/31 08:12
tiitoi

総合スコア21956

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

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

0

そもそも、なぜ、
「宣言だと思って書いたら、すでに宣言されていた」
「代入だと思って書いたら、まだ定義されていなかった」
を区別する必要を感じられているのでしょうか?

「異なる意味を持つはずの変数に同じ名前を割り当ててしまうミス」をご心配なら、より長く意味が判るような名付けの工夫などが必要なのではないでしょうか?

投稿2018/10/31 05:59

hiro-k

総合スコア902

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

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

ruei

2018/10/31 06:12

区別できたほうが見通しよく書けると思いますし、 これはエディタ側で解決するべき問題だと思います。
hiro-k

2018/10/31 06:26

他の回答へのコメントで「コード上では同じですが、プログラムの動きとしては異なりませんか?」とありますが、python では、変数に型が無いため、= での代入はその変数が新たに使われるものなのか?過去に使われたものなのか?によって、代入後の中身が異なるということはありません。つまり、他の場所で実数を代入した変数に整数を代入した場合にpythonでは実数にはならず整数になります。別の言い方をすると、代入する前に変数に入っていた情報は全て忘れられます。それでも区別をするべきなのでしょうか?
ruei

2018/10/31 06:36

自分の不勉強で意味が分からないのですが、 「コード上では同じで、プログラムの動きとしても同じ」 という主張ですか?
ruei

2018/10/31 06:38

動的型付けだから、区別の必要がないというのは、理由がわからないです。
hiro-k

2018/10/31 07:50

> 「コード上では同じで、プログラムの動きとしても同じ」という主張ですか? 例えば、 a=1 a=1.0 という場合に、上のa=1の有無はa=1.0以降に対しては何ら影響は与えず(内部的なメモリ割り当て・解放の動作は変わり得ますが)プログラムの動きとして論理的には同じになります。 >動的型付けだから、区別の必要がないというのは、理由がわからないです。 質問に質問で返して申し訳ありませんが、区別できることによって具体的にどのようなメリットを見出しているのでしょうか?
ruei

2018/10/31 08:01

数十行のコードの中から、すでに使った変数を機械的に探せないのは不便です。 新しくコードをつけ足すときにすでに前後の行でaを別の意味で使っていると困ります。 「より長く意味が判るような名付けの工夫」には限界があります。 ヒューマンエラーは起きないのですか? 機械的に判断してもらえるのならそうしてほしいです。 a=1 a=1.0 という書き方ができるからと言って a=1 a="りんご" という書き方はしないと思います。 後者のようなコードを書きたくないです。
guest

0

「宣言だと思って書いたら、すでに宣言されていた」

「代入だと思って書いたら、まだ定義されていなかった」
というときにエラーが出てほしいです。

おそらく、不可能ではないかと思います。「宣言(1度目の代入)」も「2回目以降の代入」も全く同じ形なので、「宣言だと思って」や「代入だと思って」という意思を読み取るのは、極めて困難です。

投稿2018/10/31 05:42

maisumakun

総合スコア145183

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

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

ruei

2018/10/31 05:49

コード上では同じですが、プログラムの動きとしては異なりませんか?
ruei

2018/10/31 05:50

例えば、EclipseでJavaを書くとき、var=1とすると、int var = hogeをエディタが探しに行って、存在しなければ、警告が出ます。同様の働きをpythonでするエディタはないのでしょうか。
maisumakun

2018/10/31 05:50

どちらも正当な動作ですから、「エラー」を出すべきではない箇所です。
maisumakun

2018/10/31 05:51

「var=1」と書いた時点で、エディタに「すでに存在するvarに再代入しようとしている」のか「varという変数を作ろうとしている」のか、Pythonという条件で見分けさせるのは不可能です。
ruei

2018/10/31 05:51

一度目の代入の変数だけ、アンダーラインとか太字とか色が変わるとかもないんでしょうか。
guest

0

VSCodeやAtomなどの高機能エディタにpython関係のプラグインを入れたりすると、ソースコードレベルでエラーチェックやインテリセンスなどやってくれます。
また、そこで実行やデバッグなんかもできるようになるので、ここらへんのキーワードでぐぐってみたらどうでしょう。

まあ、便利に使おうとすると、その環境構築がちと難しいのが玉に瑕ですが、苦労してみる値打ちはあると思います

投稿2018/10/31 05:53

編集2018/10/31 05:55
y_waiwai

総合スコア87774

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

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

0

Spacemacs(Emacsディストリビューション)を1ヶ月ほど使っていたものです。

MELPAパッケージ管理システムで python-mode をインストールすると、もしかすると補完機能で既に使った変数が候補に出てくるので、そこをみて、
「あ、もうこの変数名使ってた……」
という確認ができるのではと思いました。

いかがでしょう?

投稿2018/10/31 06:31

manzyun

総合スコア2244

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問