12

呼び出し関数内の変数が呼び出された関数内で見えるように、Python でスコープを管理する方法はありますか? 次のようなものが欲しい

z = 1

def a():
    z = z * 2
    print z

def b():
    z = z + 1
    print z
    a()
    print z

b()

次の出力を取得したい

2
4
2

この問題の本当の解決策は、単に z を変数として渡すことです。私はこれをしたくありません。

私は、さまざまなレベルの専門知識を持つユーザーを含む大規模で複雑なコードベースを持っています。彼らは現在、1 つの変数を渡すように訓練されており、別の変数を追加する必要があります。すべての関数呼び出しで2番目の変数を一貫して渡すとは信じていないので、インターフェイスを維持する代替手段を探しています。これが不可能である可能性は十分にあります。

4

5 に答える 5

13

これがあなたが探しているものだと思います。内部関数を制御していて、探している変数が既に呼び出しチェーンのどこかのスコープ内にあるが、ユーザーが呼び出し自体に変数を含める必要がない場合。global内部割り当てが外部スコープに影響を与えたくないため、明らかにキーワードは必要ありません。

モジュールを使用するinspectと、呼び出しコンテキストにアクセスできます。(ただし、多少壊れやすいことに注意してください。おそらく、CPython のスレッド化されていない場合にのみ使用する必要があります。)

import inspect

def calling_scope_variable(name):
  frame = inspect.stack()[1][0]
  while name not in frame.f_locals:
    frame = frame.f_back
    if frame is None:
      return None
  return frame.f_locals[name]

z = 1

def a():
  z = calling_scope_variable('z')
  z = z * 2
  print z

def b():
  z = calling_scope_variable('z')
  z = z + 1
  print z
  a()
  print z

b()

これにより、次の正しい答えが得られます。

2
4
2
于 2013-02-04T19:40:38.610 に答える
6

これはクラスに適した場所かもしれません:

class MyClass(object):
    def __init__(self, z):
        self.z = 1

    def a(self):
        self.z = self.z * 2
        print self.z

    def b():
        self.z = self.z + 1
        print self.z
        self.a()
        print self.z

グローバルでも同じ効果が得られますが、独自の別の名前空間 (クラスなど) を作成し、それをスコープに使用することをお勧めします。

于 2013-02-04T17:40:09.907 に答える
3

これは少し醜いですが、グローバルの使用を回避し、テストしたところ動作します。ここにある選択された回答のコードを使用すると、関数getSetZ()には、渡された値を格納するために使用できる「静的」変数があり、関数がNoneパラメーターとして呼び出されたときに取得されます。特定の制限はNone、z の可能な値ではないと想定し、スレッドを使用しないことです。getSetZ()呼び出し元の関数を使用できるようにする関数を呼び出すたびに、呼び出しの直前に呼び出しz、値を取得しgetSetZ()てその関数のローカル変数に入れることを覚えておく必要があります。

def getSetZ(newZ):
    if newZ is not None:
        getSetZ.z = newZ
    else:
        return getSetZ.z

def a():
    z = getSetZ(None)
    z = z * 2
    print z

def b():
    z = getSetZ(None)
    z = z + 1
    print z
    getSetZ(z)
    a()
    print z

getSetZ.z = 0
getSetZ(1)
b()

これが役立つことを願っています。

于 2013-02-04T18:40:26.973 に答える
2

一般に、最善の解決策は常に値を渡すことです。これは、はるかに予測可能で自然であり、操作とデバッグが容易になります。

def a(z):
    z = z * 2
    print z

def b():
    global z
    z = z + 1
    print z
    a(z)
    print z

b()

a()で定義してb()、同様のことを行うことができます。

def b():
    global z
    z = z + 1
    print z
    def a():
        z = z * 2
        print z
    a()
    print z

ただし、これは実際には最適ではありません。

于 2013-02-04T17:29:06.387 に答える
2

あなたが達成しようとしていることはよくわかりませんが、これは 2, 4, 2 を出力します:

z = 1

def a():
    global z
    y = z * 2
    print y

def b():
    global z
    z = z + 1
    print z
    a()
    print z

b()
于 2013-02-04T18:25:08.640 に答える