60009


初心者の質問失礼します。

[code]

    def doubleChar(str):
        vessel = ''
        for i in range(len(str)):
            vessel += str[i]*2
        return vessel
    
[/code]

この関数は、以下のように  
doubleChar('The') → 'TThhee'  
パラメータで受け取った値を、連続して表示するものです

関数の前に変数を決めないといけません。例では、`vessel = ""`

なぜこれは必要なのでしょうか？関数の外にあってもダメで、中でないといけない理由も知りたいです。


CC BY-SA 4.0
2019-10-27T05:15:50.897
60008
2019-10-27T17:08:14.137
2019-10-27T05:35:49.333
19110
36091
question
python
for loopでの変数定義


### for loop の前に代入が必要な理由

まず、質問文にあるように for loop の前に `vessel = ""`
がある場合この関数はどう動作するでしょうか。`doubleChar("The")` が呼び出されたときの動作をひとつずつ追ってみましょう。

[code]

    ループの前
    str = "The"
    vessel = ""
    
    ループ
    vessel += str[i] * 2
    
     i | vessel
    --------------
     0 | "TT"
     1 | "TThh"
     2 | "TThhee"
    
    ループの後
    return "TThhee"
    
[/code]

`doubleChar` 関数はこのように動作することで想定した動作を行うことが想像できます。

では、逆に `vessel = ""` が無かったらどうなるでしょうか。この場合最初に `vessel` が使われるのはループの最初、`i = 0`
のときとなります。このとき次の動作をすることが想定されます。

[code]

    vessel += str[0] * 2
    
[/code]

ここで `+=` という演算子は次の動作を省略しているのでした。つまり、「今の `vessel` の内容に `str[0] * 2` を `+`
して、それを `vessel` に代入する」ということです。

[code]

    vessel = vessel + str[0] * 2
    
[/code]

しかし今 `vessel` はこの部分で初めて使われたのでした。したがって `vessel`
の内容はこの時点では決まっておらず、未定義なわけです。よって次のエラーが出ます。日本語に訳すと「ローカル変数 `vessel`
が代入の前に参照されています」というエラーです。

[code]

    UnboundLocalError: local variable 'vessel' referenced before assignment
    
[/code]

このように変数の最初の値を代入することを、変数の初期化と言います。

### 関数の外で初期化しても駄目な理由

変数の初期化が大事ということであれば、関数の外側であらかじめ 1
回初期化しておいて、それを使いまわせば良いのではないでしょうか。今回の場合、それでは駄目だということも説明します。

実際に関数の外で初期化して動かしてみると、同じように `UnboundLocalError` が出ます。Python
では、関数の外側の変数（グローバル変数）と内側の変数（ローカル変数）で使い方に差があります。特に、何も指定せずに関数の内側で変数を使おうとしたとき、それはローカル変数だと思われます。

したがって、次のように `doubleChar` 関数を定義した場合、`vessel += str[i] * 2`
の部分で使われようとしているのはグローバル変数 `vessel` ではなく、関数の内部で初期化されていることが期待されているローカル変数 `vessel`
です。ローカル変数 `vessel` は初期化されていないので `UnboundLocalError` が出たわけです。

[code]

    vessel = ""
    
    def doubleChar(str):
        for i in range(len(str)):
            vessel += str[i] * 2
        return vessel
    
[/code]

ちなみに、実際の動作とは異なりますがもし `vessel += str[i] * 2` の部分でグローバル変数 `vessel`
が参照されたとしても、動作がおかしくなります。というのも `doubleChar` 関数が最初に呼び出されたときは `vessel = ""`
なので良いのですが、2 回目以降の呼び出しでは前回の値が残ってしまっているので想定した値を返さないのです。

[code]

    # こんな感じになってしまいます
    doubleChar("The")  # ==> "TThhee"
    doubleChar("Two")  # ==> "TThheeTTwwoo"
    
[/code]


CC BY-SA 4.0
2019-10-27T06:05:09.940
60009
2019-10-27T17:08:14.137
2019-10-27T17:08:14.137
19110
19110
60008
answer