我继承了一个遗留单元测试,试图覆盖嵌套在另一个类中的自定义类的名称datetime
。我现在正在重构它(我同意这非常糟糕)但我不明白我所看到的特定错误。
我看到了一个UnboundLocalError
,我可以通过一个自包含的示例重现这一点:
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()
我明白了:
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
定义内部(这失败)。
凭借闭包,datetime
的值不应该由导入的模块提供,因为在inner_scope
函数中检查范围越来越高?< / p>
据我所知,我也没有尝试修改它,因为我已经看到了其他UnboundLocalError
有关修改变量的问题,这些变量可以通过闭包访问但不会更改,除非首先作为局部变量。
答案 0 :(得分:2)
此案例与您见过的与UnboundLocalError
相关的其他案例没有什么不同。由于您的内部类也被称为datetime
,Python的字节码编译器会将名称datetime
标记为局部变量。由于您尝试在类声明之前分配real_datetime = datetime
,因此会收到错误。
如果您考虑
,这可能会更清楚class datetime(datetime.datetime):
...
是对以下内容的等效声明:
datetime = type('datetime', (datetime.datetime), {...class members...})
作为此类事情的解决方法,您可以始终使用datetime
的其他名称作为模拟类。它可能与它的名称无关(如果它确实很重要,你仍然可以通过在创建类之后分配给它的__name__
属性来覆盖它。
在Python 3中,您只需声明nonlocal datetime
就像任何其他非局部变量一样。