如何使用上下文管理器原子地(在退出时)在列表中附加值?

问题描述 投票:0回答:2

[对于初学者,我是Python的新手。

我正在尝试编写自己的上下文管理器,它将在退出时将值附加到我的列表中。我创建了列表的副本,但似乎无法正常使用。

这是我的代码:

import time
import copy

a = [1,2,3]


class contextmanager():
    def __init__(self, var):
        self.abc = var

    def current(self):

        b.append(98325)



        return b

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('Current list: {}'.format(self.current()))

with contextmanager(a) as t:
    time.sleep(1)
    b = copy.deepcopy(a)

    print("Changed list: {}".format(t.current()))
    time.sleep(2) 

我想在退出时添加值,例如:

当前-[1,2,3]

append-[4,5,6]

退出前-[1,2,3]

exit-[1,2,3,4,5,6]

但是它无法解决问题,我明白了:

当前-[1,2,3,4,5,6]

append-[4,5,6]

exit-[1,2,3,4,5,6,4,5,6]

我在做什么错?我该如何解决?如果您向我展示我需要更改代码的内容,我将非常高兴。

我似乎还不太了解Python。感谢您的帮助。

python python-3.x contextmanager
2个回答
1
投票

这不是您要使用上下文管理器的方式。最初的OO原则建议具有适当的封装,这意味着用户不必知道实现细节。

我将提出以下设计:

  • 上下文管理器将列表作为其创建参数
  • 它提供2种方法:
    • append(val),其中[[准备将val附加到列表并返回自身以允许链接]][appending()返回要追加的项目列表
  • 准备的项目仅在未引发例外的情况下才附加
  • 可能的实现:

    class contextmanager(): def __init__(self, var): self.orig = var self.cur = [] def append(self, val): self.cur.append(val) return self def appending(self): return self.cur def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is None: self.orig.extend(self.cur)

    用法示例:

    a = [1,2,3] print("initial", a) with contextmanager(a) as t: t.append(4) print("appending", t.appending()) t.append(5).append(6) print("appending", t.appending()) print("first pass", a) try: with contextmanager(a) as t: t.append(7) t.append(8) print("appending", t.appending()) raise Exception() t.append(9) print("appending", t.appending()) except Exception as e: print("Exception", e) print("final", a)

    给出:

    initial [1, 2, 3] appending [4] appending [4, 5, 6] first pass [1, 2, 3, 4, 5, 6] appending [7, 8] Exception final [1, 2, 3, 4, 5, 6]


  • 0
    投票
    您的代码是两次附加。您的第一个追加内容位于Contextmanager的语句块中(此行:print("Changed list: {}".format(t.current()))
    © www.soinside.com 2019 - 2024. All rights reserved.