Python のネストされた関数の変数スコープ [重複] 質問する

Python のネストされた関数の変数スコープ [重複] 質問する

このトピックに関する他の質問をほぼすべて読みましたが、私のコードはまだ機能しません。

Python 変数のスコープについて何かが欠けていると思います。

これが私のコードです:

PRICE_RANGES = {
                64:(25, 0.35),
                32:(13, 0.40),
                16:(7, 0.45),
                8:(4, 0.5)
                }

def get_order_total(quantity):
    global PRICE_RANGES
    _total = 0
    _i = PRICE_RANGES.iterkeys()
    def recurse(_i):
        try:
            key = _i.next()
            if quantity % key != quantity:
                _total += PRICE_RANGES[key][0]
            return recurse(_i) 
        except StopIteration:
            return (key, quantity % key)

    res = recurse(_i)

そして私は

「グローバル名 '_total' が定義されていません」

問題は割り当てにあることはわかっています_totalが、その理由がわかりません。recurse()親関数の変数にアクセスできないのでしょうか?

Python 変数スコープについて私が何を見逃しているのか、誰か説明してくれませんか?

ベストアンサー1

Python 3では、nonlocal声明非ローカル、非グローバルスコープにアクセスします。

このnonlocalステートメントにより、変数定義は最も近いスコープ内で以前に作成された変数にバインドされます。次に例をいくつか示します。

def sum_list_items(_list):
    total = 0

    def do_the_sum(_list):
        for i in _list:
            total += i

    do_the_sum(_list)

    return total

sum_list_items([1, 2, 3])

上記の例は、次のエラーで失敗します:UnboundLocalError: local variable 'total' referenced before assignment

を使用するとnonlocal、コードを動作させることができます:

def sum_list_items(_list):
    total = 0

    def do_the_sum(_list):

        # Define the total variable as non-local, causing it to bind
        # to the nearest non-global variable also called total.
        nonlocal total

        for i in _list:
            total += i

    do_the_sum(_list)

    return total

sum_list_items([1, 2, 3])

しかし、「最も近い」とはどういう意味でしょうか? 別の例を挙げます。

def sum_list_items(_list):

    total = 0

    def do_the_sum(_list):

        # The nonlocal total binds to this variable.
        total = 0

        def do_core_computations(_list):

            # Define the total variable as non-local, causing it to bind
            # to the nearest non-global variable also called total.
            nonlocal total

            for i in _list:
                total += i

        do_core_computations(_list)

    do_the_sum(_list)

    return total

sum_list_items([1, 2, 3])

上記の例では、は関数total内で定義された変数にバインドされdo_the_sumsum_list_items関数で定義された外部変数にはバインドされないため、コードは を返します0。ただし、次のように二重ネストを行うことは可能です。上記の例でtotalが宣言されている場合は、期待どおりに動作します。nonlocaldo_the_sum

def sum_list_items(_list):

    # The nonlocal total binds to this variable.
    total = 0

    def do_the_sum(_list):

        def do_core_computations(_list):

            # Define the total variable as non-local, causing it to bind
            # to the nearest non-global variable also called total.
            nonlocal total

            for i in _list:
                total += i

        do_core_computations(_list)

    do_the_sum(_list)

    return total

sum_list_items([1, 2, 3])

上記の例では、非ローカル割り当ては、totalローカルな変数を見つける前に 2 レベル上まで移動しますsum_list_items

おすすめ記事