关于python:嵌套类中的模块出现意外的unboundLocalError

Unexpected UnboundLocalError for a module within nested class

我继承了一个旧的单元测试,它试图为嵌套在另一个类中的自定义类重写名称datetime。我现在正在重构它(我同意这非常糟糕),但我不理解我看到的特定错误。

我看到的是一个UnboundLocalError,我可以用一个独立的例子来复制它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import datetime
class Foo(object):

    def inner_scope(self):

        real_datetime = datetime
        class datetime(datetime.datetime):
            @staticmethod
            def convert():
                return"blah"

        x = datetime(2012, 1, 1)
        y = x.convert()
        return x, y

f = Foo()
f.inner_scope()

我明白这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [439]: f.inner_scope()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-439-c5053fb49b64> in <module>()
----> 1 f.inner_scope()

<ipython-input-437-222b3997ec2c> in inner_scope(self)
      3     def inner_scope(self):
      4
----> 5         real_datetime = datetime
      6         class datetime(datetime.datetime):
      7             @staticmethod

UnboundLocalError: local variable 'datetime' referenced before assignment

我试着添加print语句来打印type(datetime)type(datetime.datetime),直接在类定义(本作品)内和直接在inner_scope定义(本失败)内。

由于闭包,导入的模块不应该提供EDOCX1的值(0),因为它是从inner_scope函数在更高级别和更高级别的范围内检查的?

据我所知,我也不想修改它,因为我看到过其他UnboundLocalError问题,这些问题与修改变量的尝试有关,这些变量可以通过闭包访问,但除非首先作为局部变量进行修改,否则不会更改。


这个案例与你所看到的其他与UnboundLocalError相关的案例没有什么不同。由于您的内部类也被称为datetimepython的字节码编译器将把名称datetime标记为局部变量。因为您试图在类声明之前分配real_datetime = datetime,所以会得到错误。

如果你考虑的话,这可能会更清楚

1
2
class datetime(datetime.datetime):
    ...

相当于:

1
datetime = type('datetime', (datetime.datetime), {...class members...})

作为解决这类问题的方法,对于模拟类,您可以使用与datetime不同的名称。它的名称可能并不重要(如果它真的很重要,您仍然可以通过在类创建后分配给它的__name__属性来覆盖它)。

在python 3中,您只需声明nonlocal datetime,就像声明任何其他非局部变量一样。