给定的
我有一个函数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的习惯用法和这个问题的本质。我仍然对它的可能性很感兴趣,我感谢任何愿意超越标准的人。
发布于 2018-07-21 08:35:07
这是一种欺骗,但是
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)
)
发布于 2018-07-20 06:31:36
虽然python会给你提供这样做的方法,但你真的不想这样做。函数/类/等不应该将其内部暴露给调用代码,因为这会破坏抽象并使代码变得脆弱。函数应该接受参数并返回输出值,但是内部算法,特别是变量名不应该公开。
https://stackoverflow.com/questions/51432553
复制相似问题