ローカル変数を設定し、それを関数から参照し、操作した値をメインスコープ(またはそれが呼び出されたものに戻すことができる; 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
関数は、関数の呼び出し元のスコープを知っている必要はありません。関数のポイントは、異なる場所から複数回呼び出すことができる再利用可能なコードのブロックを作成することです。
関数への情報の伝達は、入力変数を介して関数を渡します。関数は、情報を返すことにより、呼び出し元に情報を返します。
スコープの変数の管理は、そのスコープ内のコードの仕事ですnotそれが呼び出すすべての関数。変数を関数によって決定された値に設定する必要がある場合は、関数にそれらの値を返させ、それらを使用して変数を設定します。関数が計算する値が、呼び出しスコープ内にある変数の値に依存している場合は、それらを引数として関数に渡す必要があります。呼び出す関数は、使用している変数を知っている必要はありません。また、変数をいじる必要もありません。
これらすべてをまとめると、あなたがしたいことは次のようなものです:
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
グローバル変数または可変データ構造を操作してこれを回避する方法はありますが、最終的にはプログラムの柔軟性が低下し、特定が困難なエラーが含まれる可能性が高くなります。これらの手法には場所がありますが、関数との間で情報をやり取りするために最初に到達する方法は、実際には引数を渡し、戻り値を受け取ることです。
#!/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
1つのアプローチは、dictやリストなどの変更可能な値を使用することです。
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をラップすること)に行きます。