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

use*_*421 3 python with-statement contextmanager

我正在尝试使用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]
Run Code Online (Sandbox Code Playgroud)


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

And*_*ark 14

此行为是由于Python中的可变默认参数的工作原理.

尝试更改SymList.__init__()为以下内容:

    def __init__(self, L=None):
        if L is None:
             self.L = []
        else:
             self.L = L
Run Code Online (Sandbox Code Playgroud)

self.L在一个实例中进行修改时,您还要修改L传入的实例SymList.__init__(),因此代码的结果是所有实例L在首次初始化实例时将共享相同的属性.