8

ローカル変数を設定し、それを関数から参照し、操作された値をメイン スコープに戻すことができるスクリプトを作成しようとしています (またはそれが呼び出されたものは何でも; Python は初めてです)。

モジュールからローカルを関数ブロックにインポートするという、私が達成しようとしていることの基本を示すためにコードを単純化しました。

を使用してこれを機能させましglobalsたが、それは最善の解決策ではありません。. .

chambersinreactor = 0;
cardsdiscarded = 0;

def find_chamber_discard(): 
    """Find chambers and discard in row (reads each player slot)"""
    chambersinreactor = 0; # Resets the variable, not what I want
    cardsdiscarded = 0; # Resets the variable, not what I want
    chambersinreactor += 1
    cardsdiscarded += 1
    return # Don't know what to put here

find_chamber_discard()

print chambersinreactor # prints as 0, should be 1
print cardsdiscarded    # prints as 0, should be 1
4

3 に答える 3

21

関数は、呼び出されたスコープを知る必要はありません。関数のポイントは、さまざまな場所から複数回呼び出すことができる再利用可能なコード ブロックを作成することです。

入力変数を介して情報を渡すことにより、情報を関数に伝達します。この関数は、情報を返すことによって呼び出し元に情報を伝えます。

スコープの変数を管理することは、スコープが呼び出す関数ではなく、そのスコープ内のコードの仕事です。関数によって決定された値に変数を設定する必要がある場合は、関数にそれらの値を返させ、それらを使用して変数を設定します。関数が計算する値が、呼び出しスコープにある変数の値に依存する場合は、それらを引数として関数に渡す必要があります。呼び出している関数は、使用している変数を知る必要はなく、それらを台無しにすることはできません。

それをすべてまとめると、あなたがやりたいことは次のようなものです:

def find_chamber_discard(chambersinreactor, cardsdiscarded):
    chambersinreactor += 1
    cardsdiscarded += 1
    return (chambersinreactor, cardsdiscarded)

chambersinreactor = 0;
cardsdiscarded = 0;

chambersinreactor, cardsdiscarded = find_chamber_discard(chambersinreactor, cardsdiscarded)

print chambersinreactor
print cardsdiscarded

グローバル変数や変更可能なデータ構造を操作することでこれを回避する方法がありますが、最終的にはプログラムの柔軟性が低下し、見つけにくいエラーが含まれる可能性が高くなります。これらの手法を使用する場所はありますが、関数との間で情報をやり取りするために到達する最初の方法は、実際には引数を渡し、戻り値を受け取る必要があります。

于 2012-05-11T03:44:52.597 に答える
2

1 つのアプローチは、辞書やリストなどの変更可能な値を使用することです。

settings = dict(
    chambersinreactor = 0,
    cardsdiscarded = 0
)

def find_chamber_discard():
    settings['chambersinreactor'] += 1
    settings['cardsdiscarded'] += 1

find_chamber_discard()

print settings['chambersinreactor']
print settings['cardsdiscarded']

ただし、何らかの状態を変更する関数がある場合は、それをすべてクラスにラップする方がよいでしょう。それが目的だからです。

class CardCounter(object):
    def __init__(self):
        chambersinreactor = 0
        cardsdiscarded = 0

    def find_chamber_discard(self, hand):
        for card in hand:
            if card.is_chamber:
                self.chambersinreactor += 1
            if card.is_discarded:
                self.cardsdiscarded += 1

あなたがしていることが数えているなら、多分カウンターを使うことができます:

from collections import Counter

def test_for_chamberness(x): return x == 'C'
def test_for_discarded(x): return x == 'D'

def chamber_or_discard(card):
    if test_for_chamberness(card):
        return 'chambersinreactor'
    if test_for_discarded(card):
        return 'cardsdiscarded'

hand = ['C','C','D','X','D','E','C']

print Counter(
    x for x in (chamber_or_discard(card) for card in hand) if x is not None
)

個人的には、関連するすべての機能を一緒に保持するため、おそらく Counter をラップするクラス アプローチを使用します。

于 2012-05-11T05:45:04.497 に答える
2
#!/usr/bin/env python
chambersinreactor = 0; cardsdiscarded = 0;

def find_chamber_discard():
    chambersinreactor = 0
    cardsdiscarded = 0
    chambersinreactor += 1 
    cardsdiscarded += 1 
    return(chambersinreactor, cardsdiscarded)

#Here the globals remain unchanged by the locals.
#In python, a scope is similar to a 'namespace'
find_chamber_discard()

print chambersinreactor #prints as 0
print cardsdiscarded 

#I've modified the function to return a pair (tuple) of numbers.
#Above I ignored them. Now I'm going to assign the variables in the 
#main name space to the result of the function call.
print("=====with assignment===")
(chambersinreactor, cardsdiscarded) = find_chamber_discard()

print chambersinreactor #  now prints as 1
print cardsdiscarded 

# Here is another way that doesn't depend on returning values.
#Pass a dictionary of all the main variables into your function
#and directly access them from within the function as needed

print("=======using locals===")
def find_chamber_discard2(_locals):
    _locals['chambersinreactor'] += 1
    _locals['cardsdiscarded'] += 1
    return

find_chamber_discard2(locals())

print chambersinreactor #incremented the value, which was already 1
print cardsdiscarded 
于 2012-05-11T03:53:02.420 に答える