编程语言
首页 > 编程语言> > Python:在类方法上使用contextmanager的意外行为

Python:在类方法上使用contextmanager的意外行为

作者:互联网

参见英文答案 > “Least Astonishment” and the Mutable Default Argument                                    32个
>            Python constructor and default value                                     4个
我正在尝试使用Python中的with..as contruct来简化“可逆计算”代码的编写.但是,在类方法上使用@contextmanager似乎会更改未来类实例的默认初始化. Python 2.6和3.1具有相同的行为.以下是展示此行为的简单示例:

#!/usr/bin/env python

import contextlib

class SymList:
    def __init__(self, L=[]):
        self.L = L

    @contextlib.contextmanager
    def SymAdd(self, a):
        self.L.append(a)
        yield
        self.L.append(a)

SL = SymList()
with SL.SymAdd(3):
    SL.L.append(5)
print(SL.L) # Expect and see [3, 5, 3]
SL2 = SymList()
print(SL2.L) # Expect [] and see [3, 5, 3]

>为什么SL2不是SymList的新实例?
> SL2.L数据成员如何引用SL.L数据成员?

解决方法:

此行为是由于mutable default arguments如何在Python中工作.

尝试将SymList .__ init __()更改为以下内容:

    def __init__(self, L=None):
        if L is None:
             self.L = []
        else:
             self.L = L

当您在一个实例中修改self.L时,您还修改了传递给SymList .__ init __()的L,因此您的代码的结果是所有实例在首次初始化实例时将共享相同的L属性.

标签:python,with-statement,contextmanager
来源: https://codeday.me/bug/20190714/1455478.html