使用类作为局部变量的容器对象,以替代Python中的“非局部”

2024-05-08 00:56:10 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

在Python中,如果我有一个带有局部变量和嵌套函数的函数,我可以借助非局部变量在嵌套函数中分配这些变量:

def f():
    x = 0
    def _g():
        nonlocal x
        x = 1
    def _h():
        x = 2
    _g()
    _h()
    print(x)
f() # 1

这个解决方案的问题是,如果我在f()中有许多局部变量,那么使用非局部变量是冗长的,而且更令人不安的是,很容易忘记变量的非局部性,并且在嵌套函数中创建局部变量而没有注意到它(例如,我在上面的h()函数中真正的意思是什么?)。你知道吗

我看到并使用了另一种方法:

def f():
    class state:
        x = 0
    def _g():
        state.x = 1
    def _h():
        x = 2
    _g()
    _h()
    print(state.x)
f() # 1

If使用Python中的类实际上也是一个对象这一事实。以这种方式使用“class”实际上是为本地值创建可变容器的最简单的方法(我相信)。你知道吗

我认为这种模式有两个值得怀疑的方面:

  • “class”关键字的这种特殊用法可能被认为是一种黑客行为。你知道吗
  • 由于容器有点人造,所以有时很难为它找到一个好名字(我甚至测试了“self”这个名字的用法,但这看起来更像是一个黑客攻击)。你知道吗

这是个好模式吗?你通常用什么替代品?你知道吗

如果StackOverflow不是这个问题的合适论坛,请在您认为更适合的其他论坛上提出建议(我确实阅读了常见问题解答,但我并不清楚这个问题的正确论坛是什么)。你知道吗

提前谢谢。你知道吗

附言

为了完整起见,至少还有一种选择,感觉更像黑客:

class f:
    def __init__(self):
        self.x = 0
        self._g()
        self._h()
        print(self.x)
    def _g(self):
        self.x = 1
    def _h(self):
        x = 2
f() # 1

这是因为在Python中,类实例化与函数调用具有相同的语法。你知道吗

回答

请参阅下面接受的答案。有关函数需要返回值时解决方案的讨论,请参见there。你知道吗


Tags: 方法函数self用法def模式解决方案名字
2条回答

你的“最后一招”alernative当然更干净——如果你能在共享一个状态的扁平化方法中完成它,那就比嵌套函数更容易阅读代码来完成同样的工作。”“扁平比嵌套好”。你知道吗

除此之外,您正在创建一个具有命名空间的类。您可以简单地创建一个对象作为名称空间使用,它将作为名称空间使用—这更常见。唯一的问题是,如果您只是创建一个object本身的实例,它就不能作为名称空间使用,因为它没有__dict__,所以您不能自由地为它指定对象的属性。你知道吗

这就是为什么stdlib中的types模块中有一个名为SimpleNamespace的类正好适合这个用例。你知道吗

只要做:

from types import SimpleNamespace

def f():
    state = SimpleNamespace()
    state.x = 0
    ...

(但前提是你不改变主意,选择更干净的基于类的解决方案)。你知道吗

为什么不直接使用dict而不是类呢。这消除了一些“hackynes”,并且与Python 2兼容:

def f():
    state=dict(x=0)

    def _g():
        state["x"] = 1

    def _h():
        x = 2
    _g()
    _h()
    print(state["x"])
f() # 1

相关问题 更多 >