[英]Return the enclosing scope variables in Python
特定
我有一個函數, scope
,可以在一個封閉的命名空間(即模塊 , 類或函數)中聲明 。 感興趣的變量位於該函數的外部。
如何一般性地訪問在任何封閉名稱空間中聲明的變量/參數及其值?
例
用於捕獲函數變量( b
)和參數( c
)的示例偽代碼:
a = 1
def func(c=3)
b = 2
def scope():
return ...
return scope()
預期產量
func()
# {'c': 3, 'b': 2}
嘗試
我在模塊級別取得了一定的成功,例如a = 1
:
# module-level
a = 1
def scope():
return {k: v for k, v in globals().items() if not k.startswith("_")}
scope()
# {'a': 1, ...}
我也可以從方法訪問類屬性,例如b = 2
:
# class-level
a = 1
class Klass:
b = 2
def scope(self):
obj = self.__class__
return obj.__dict__
Klass().scope()
# {'b': 2, ...}
我只能部分訪問封閉函數中的變量和參數:
# function-level
a = 1
def func(c=3):
b = 2
def scope():
obj = func
return obj.__code__.co_varnames
return scope()
func()
# ('c', 'b', 'scope')
盡管__code__.co_varnames
成功提供了封閉變量(不包括a
),但我也對這些值感興趣(例如{'c': 3, 'b': 2}
)。
我做了許多未提及的嘗試,包括inspect
函數,其他代碼對象方法, dir()
和對象特殊方法。 我的首選是實現更通用和慣用的代碼,以檢測封閉的命名空間中的變量,盡管可以理解任何建議。
我也知道Python的習慣用法和這個問題的性質。 我仍然對它的可能性感到着迷,並且我感謝任何願意超越常規的人。
盡管python將為您提供實現此目的的方法,但您確實不希望這樣做。 函數/類/等不應將其內部信息公開給調用代碼,因為這會破壞抽象並使代碼易碎。 函數應該接受參數並返回輸出值,但是內部算法,尤其是變量名不應該公開。
這有點作弊,但是
def scope(outer=locals()):
return outer
作品。 (之所以作弊,是因為默認參數是在定義時由定義代碼求值的,因此locals()
在封閉范圍內運行,因此實際上並不是scope
函數伸到封閉范圍內。)
請注意,在調用后修改相應范圍時,由locals()
返回的目錄可能會更改,也可能不會更改。 如果要在Python實現之間(甚至在不同用例之間)保持一致的行為,請在默認參數或scope
函數主體中進行深拷貝。
# module-level
a = 1
def scope(outer=locals()):
return outer
e = 5
result = scope()
f = 6
public_result = {k: v for k, v in result.items() if not k.startswith('_')}
assert (
# allowed:
public_result == dict(a=1)
or
# C-Python 3.6 behavior:
public_result == dict(a=1, scope=scope, e=5, result=result, f=6)
)
# class-level
a = 1
class Klass:
b = 2
@staticmethod
def _scope(outer=locals()): # Hidden from public result, because I have
return outer # no idea how to refer to it from the outside.
d = 4
e = 5
result = Klass._scope()
f = 6
public_result = {k: v for k, v in result.items() if not k.startswith('_')}
assert (
# allowed:
public_result == dict(b=2)
or
# CPython 3.6 behavior:
public_result == dict(b=2, d=4) # would also contain `scope` if it wasn't hidden
)
# function-level
a = 1
def func(c=3):
b = 2
def scope(outer=locals()):
return outer
return scope(), scope
d = 4
e = 5
result, scope_fu = func()
f = 6
assert (
# C-Python 3.6 behaviour:
result == dict(b=2, c=3)
or
# also allowed:
result == dict(b=2, c=3, scope=scope_fu, d=4)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.