70

Pythonでglobals()関数を使用する理由は何ですか?すでにグローバルであるグローバル変数の辞書のみを返すので、どこでも使用できます...私は好奇心からのみPythonを学ぼうとしています。

def F():
    global x
    x = 1

def G():
    print(globals()["x"]) #will return value of global 'x', which is 1

def H():
    print(x) #will also return value of global 'x', which, also, is 1

F()
G()
H()

ここでポイントがよくわかりませんか?私がそれを必要とするのは、ローカル変数とグローバル変数があり、両方に同じ名前が付いている場合だけでした。

def F():
    global x
    x = 1

def G():
    x = 5
    print(x) #5
    print(globals()["x"]) #1

F()
G()

ただし、同じ名前の2つの変数があり、両方を同じスコープ内で使用する必要があるという問題に遭遇することはありません。

4

9 に答える 9

90

Pythonは、実行環境を内省するための多数のツールをプログラマーに提供します。globals()はそれらの1つにすぎず、グローバルスコープに実際に含まれているオブジェクトを確認するためのデバッグセッションで非常に役立ちます。

locals()その背後にある理論的根拠は、関数で定義された変数を表示するために使用dirすること、またはモジュールのコンテンツやオブジェクトの属性を表示するために使用することと同じです。

C ++のバックグラウンドから来ているので、これらのことは不要に思えることを理解できます。静的にリンクされ、静的に型付けされた環境では、絶対にそうなります。その場合、コンパイル時に、どの変数がグローバルで、どのメンバーがオブジェクトに含まれるか、さらにはどの名前が別のコンパイルユニットによってエクスポートされるかが正確にわかります。

ただし、動的言語では、これらは修正されていません。コードのインポート方法に応じて、または実行時にも変更される可能性があります。少なくともそのため、デバッガーでこの種の情報にアクセスできることは非常に貴重です。

于 2012-10-02T16:07:15.847 に答える
41

関数の文字列名を使用して関数を呼び出す必要がある場合にも役立ちます。例えば:

def foo():
    pass

function_name_as_string = 'foo'

globals()[function_name_as_string]() # foo(). 
于 2013-09-23T17:46:34.623 に答える
8

およびコマンドの結果を、、およびコマンドに渡すglobals()ことができます。そうすることで、それらのコマンドが機能するための制限された環境が作成されます。locals()evalexecfile__import__

したがって、これらの機能は、現在のコンテキストとは異なる可能性のある環境を与えられることで恩恵を受ける他の機能をサポートするために存在します。たとえば、globals()これらの関数の1つを呼び出す前に、いくつかの変数を呼び出してから削除または追加することができます。

于 2012-10-02T16:11:58.063 に答える
6

globals()スコープeval()内の変数を参照するコードを評価する場合、それらの変数はグローバルまたはローカルのいずれかになります。


少し拡張するために、eval()組み込み関数は、与えられたPythonコードの文字列を解釈します。署名は次のとおりです。eval(codeString, globals, locals)、次のように使用します。

def foo():
    x = 2
    y = eval("x + 1", globals(), locals())
    print("y=" + y) # should be 3

インタプリタは変数のdictxからの値を取得するため、これは機能します。locals()もちろん、evalに変数の独自のdictを提供することもできます。

于 2012-10-02T15:47:35.123 に答える
1

'宣言型Python'で役立ちます。たとえば、以下のFooDefクラスBarDefは、一連のデータ構造を定義するために使用され、パッケージによって入力または構成として使用されます。これにより、入力内容に多くの柔軟性がもたらされ、パーサーを作成する必要がなくなります。

# FooDef, BarDef are classes

Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )

namelist = []
for i in range(6):
    namelist.append("nm%03d"%i)

Foo_other = FooDef("a third one", string_list = namelist )

Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')

この構成ファイルは、ループを使用して、の構成の一部である名前のリストを作成することに注意してくださいFoo_other。したがって、この構成言語には、利用可能なランタイムライブラリを備えた非常に強力な「プリプロセッサ」が付属しています。たとえば、複雑なログを検索したり、zipファイルからデータを抽出してbase64でデコードしたりする場合は、構成の生成の一部として行います(もちろん、入力が信頼できないソース...)

パッケージは、次のようなものを使用して構成を読み取ります。

conf_globals = {}  # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef  # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef  # ... on .DefBase

fname = "user.conf"
try:
    exec open(fname) in conf_globals
except Exception:
    ...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).

defs = {}
for nm,val in conf_globals.items():
    if isinstance(val,mypkgconfig.DefBase):
        defs[nm] = val

したがって、最終的に要点を理解することは、globals()そのようなパッケージを使用するときに、一連の定義を手続き的に作成する場合に役立ちます。

for idx in range(20):
    varname = "Foo_%02d" % i
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)

これは書き出すのと同じです

Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...

Pythonモジュールから一連の定義を収集して入力を取得するパッケージの例はPLY(Python-lex-yacc)http://www.dabeaz.com/ply/ です。この場合、オブジェクトはほとんど関数です。オブジェクトですが、関数オブジェクトのメタデータ(名前、docstring、定義の順序)も入力の一部を形成します。を使用するための良い例ではありませんglobals()。また、その逆ではなく、「構成」(後者は通常のPythonスクリプト)によってインポートされます。

私が取り組んできたいくつかのプロジェクトで「宣言型Python」を使用globals()し、それらの構成を作成するときに使用する機会がありました。これは、構成「言語」の設計方法の弱点によるものであると確かに主張できます。このように使用globals()しても、明確な結果は得られません。ほぼ同一のステートメントを12個書き出すよりも維持しやすい結果だけです。

また、名前に従って、構成ファイル内で変数に重要性を与えるために使用することもできます。

# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist  = BarDef( foo_k , method = "kset")

このメソッドは、多くのテーブルと構造を定義するPythonモジュールに役立ち、参照も維持することなく、データにアイテムを簡単に追加できるようになります。

于 2015-06-20T23:34:42.360 に答える
0

また、文字列からクラス'classname'のインスタンスを取得するために使用することもできます。

class C:
    def __init__(self, x):
        self.x = x
        print('Added new instance, x:', self.x)


def call(str):
    obj = globals()[str](4)
    return obj

c = call('C')
print(c.x)
于 2018-03-30T13:34:43.640 に答える
0

作成したばかりのモジュールをインポートしたい場合に便利です。

a.py

[...]

def buildModule():
    [...code to build module...]
    return __import__("somemodule")

[...]

b.py

from a import buildModule

def setup():
   globals()["somemodule"] = buildModule()
于 2019-11-15T13:38:09.053 に答える
0

あまり。Pythonが実際に持っているグローバル変数は、モジュールスコープの変数です。

# a.py
print(globals())

import b
b.tt()
# b.py
def tt():
    print(globals())

実行するpython a.pyと、の少なくとも2つの出力globals()['__name__']が異なります。

Githubのcpythonのコードはそれを示しています

于 2020-03-05T09:18:56.237 に答える
0

globals()値が設定されているかどうかを確認するために使用することについて、回答には何も気づきませんでした。デバッグする場合にのみ値を設定するか、設定を忘れて例外が発生しないようにしたい場合があります。ただしlocals()、グローバルスコープへのアクセスを回避し、ローカルスコープのみにアクセスする場合は、より適切な解決策になる可能性があります。

# DEBUG = True
if 'DEBUG' in globals():
    print(f'We found debug flag and it has value {DEBUG}.')
else: 
    print(f'Debug flag was not found.')

また、と組み合わせて使用​​するとget()、変数が見つからなかった場合のデフォルト値を設定できます。

# VARIABLE = "Value of var"
my_var = globals().get("VARIABLE", "Value was not found")
print(my_var)    # Prints: "Value was not found"
print(VARIABLE)  # Raises NameError

VARIABLE = "Value of var"
my_var = globals().get("VARIABLE", "Value was not found")
print(my_var)    # prints: "Value of var"
print(VARIABLE)  # prints: "Value of var"
于 2021-03-29T14:28:25.240 に答える