2

子関数と親関数の間でリストではない変数を交換する方法はありますか?

#parent

list=[0]*1
singlevalue = 0

#child - 0
def test():
    list[0]= list[0]+1
    return list

#parent
test() #>>1 
test() #>>2


#child - 1
def test():
    singlevalue = singlevalue +1
    return singlevalue

#parent
test() >>
#    singlevalue = singlevalue +1
#UnboundLocalError: local variable 'singlevalue' referenced before assignment

この例は、 list を使用して 1 を出力し、次の実行のためにそれを保持することを示しています。単一値の方法が異なるのはなぜですか?

4

3 に答える 3

2

これまでのところ、どちらの回答も解決策を示唆していますが、これは投稿のポイントではありませんでした。違いは、リストに関しては、参照を操作していて、 のように「バインドされた」変数を操作していないことですsinglevaluel = l + [1]たとえば、境界を変更しようとするとl、同じエラーが発生します。これは、Python でのスコーピングの仕組みによるものです。

要するに

singlevalue [local variable] = singlevalue [actually a global variable but access to locally stored variable] + 1 [constant]

singlevalue はローカルに保存されます。ここで、割り当てられていないため、まだ値を持たないローカルに保存された変数にアクセスしたいと考えています。グローバルに保存したい場合は、globalキーワードを使用する必要があります。

list[0] [slot in a referenced list] = list[0] [still same slot, which has a value already]+1

したがって、問題ありません。:)

より詳細に:

ここで Python のバイトコードを見て、読み込みの違いを確認できます。

>>> def m():
...  y = 1
...  def test():
...   y = y + 1
...   return y
...  test()
>>> m()
UnboundLocalError: local variable 'y' referenced before assignment
>>> dis.dis(m)
  [... cur here ... Inside of test()]
              # <-- here the value of the constant is loaded from the local namespace
  3           6 LOAD_CONST               2 (<code object test at 02A067B8, file "<pyshell#33>", line 3>)                   
              9 MAKE_FUNCTION            0
             12 STORE_FAST               1 (test)
  [... cut here ...]

>>> def l():
...  li = [1]
...  def test():
...   li[0] = li[0] + 1
...   return li
...  test()
>>> l()
[... cut here ... Inside of test()]
              # <-- here a reference is loaded!
  3           9 LOAD_CLOSURE             0 (li)
             12 BUILD_TUPLE              1
             15 LOAD_CONST               2 (<code object test at 02A06698, file "<pyshell#28>", line 3>)
             18 MAKE_CLOSURE             0
             21 STORE_FAST               0 (test)
[... cut here ...]

この投稿は長くなりすぎるため、上記のコマンドを実行して、http: //docs.python.org/2/library/dis.htmlを参照して違いを確認することをお勧めします。

ただし、物事の保存方法の主な違いは、最初のブロックで発生します。

  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (y) # <- push loaded constant to stack

  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               1
              6 STORE_DEREF              0 (li) # <- stores the value in the list

ここを見てください!

これが違いを解消するのに役立つことを願っています。乾杯!

于 2013-06-17T07:58:05.883 に答える
1

引数を渡す方法について関数を定義する方法を調べてみると役に立ちますか?

引数を渡すことは、グローバルにアクセス可能で変更可能であることを望んでいる「変数」を操作するよりも信頼性が高い場合があります。

実際、「変数」は(特定の)名前空間内の参照の名前であり、確認する場合

print id(ll)    # as suggested by others: please don't name your list list ;)
print id(singlevalue)

関数では、変更されていないことがわかります。したがって、任意の関数で名前singlevalueを参照し、問題なく出力できます。

それらの値を変更しようとすると、状況が変わります。

リストは変更可能なオブジェクトであり、参照を変更せずに (任意の関数で) いじることができます。それらを引数として渡すことがより良い/よりセクシーな/よりPythonicなアイデアであるかどうかは別のポイントです。

ただし、文字列は不変です。関数内で、singlevalueの値を別の名前に割り当てると、両方の名前が同じ参照を持つことになります。しかし、新しい名前の値を変更すると、新しい参照が作成されます!

したがって、できるだけ怠け者になることをお勧めしますが、「周囲の」名前空間をいじるよりもデータを渡すほうがよいでしょう。最善を尽くしてください ;)

于 2013-06-17T07:51:28.063 に答える
0

グローバル変数を使用しないでください。変数の値を毎回再割り当てするだけです。

some_variable = 0
def test():
    return some_variable + 1


some_variable = test()  # 1
some_variable = test()  # 2

対話型インタープリターでのテスト セッション:

>>> a = 0
>>> def test():
...     return a + 1
... 
>>> a = test()
>>> a
1
>>> a = test()
>>> a
2
于 2013-06-17T08:01:42.103 に答える