V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
northisland
V2EX  ›  问与答

请教各位, Python 能实现这种 with 类么?

  •  
  •   northisland · 2018-10-29 17:30:33 +08:00 · 1876 次点击
    这是一个创建于 2218 天前的主题,其中的信息可能已经有所发展或是发生改变。
    with Tag('这就是一个简单说明', will_run=True):
    	codes...
    

    就是这样will_runFalse 的话, 后面的代码就不执行,或者执行但是无效。

    我想不出怎么用 __init____enter____exit__搞定

    所以来问一下大家。

    我 1 楼的思路,测试下来被打脸了:

    In [1]: class Tag(object):
       ...:     def __init__(self, comment, will_run=True):
       ...:         self.will_run = will_run
       ...:     def __enter__(self):
       ...:         if not self.will_run:
       ...:             return
       ...:     def __exit__(self, *exec_info): pass
       ...:
    
    In [2]: with Tag('这是一个实验', will_run=True):
       ...:     print(123456)
       ...:
    123456
    
    In [3]: with Tag('这是一个实验', will_run=False):
       ...:     print(123456)
       ...:
    123456
    

    请教这要怎么搞?

    8 条回复    2018-10-29 19:14:16 +08:00
    northisland
        1
    northisland  
    OP
       2018-10-29 17:35:27 +08:00
    ```
    class Tag(object):
    def __init__(self, comment, will_run=True):
    self.will_run = will_run

    def __enter__(self):
    if self.will_run==False:
    return

    def __exit__(self, *exec_info): pass
    ```

    是这样么?我去执行试试~~对 enter 理解不深入。
    laobubu
        2
    laobubu  
       2018-10-29 17:50:56 +08:00
    __enter__ 应该是不能控制 with 后面的块的吧。我能想到的就是 raise 个异常,让后面的代码全部都不能跑。
    说回来,我觉得优雅点的做法可以 with Tag("xxx") as tag: 然后下一行就是 if tag.will_run:
    misaka19000
        3
    misaka19000  
       2018-10-29 17:55:15 +08:00
    感觉应该做不到
    lolizeppelin
        4
    lolizeppelin  
       2018-10-29 18:00:15 +08:00 via Android
    enter 里直接 raise
    lolizeppelin
        5
    lolizeppelin  
       2018-10-29 18:00:52 +08:00 via Android
    有需要再套一层不就得了
    Trim21
        6
    Trim21  
       2018-10-29 18:06:42 +08:00   ❤️ 1
    考虑用装饰器?
    def tag(name, with_run: bool = False):
    def wrapper(func):
    if with_run:
    func()

    return wrapper


    def main():
    @tag("this is a tag", with_run=False)
    def f1():
    print("f1")

    @tag("this is a tag", with_run=True)
    def f2():
    print("f2")


    if __name__ == '__main__':
    main()
    lance6716
        7
    lance6716  
       2018-10-29 19:01:09 +08:00
    运行过程不会影响其他过程,除非抛异常
    Wincer
        8
    Wincer  
       2018-10-29 19:14:16 +08:00
    ```python
    from contextlib import contextmanager

    @contextmanager
    def test(will_run=True):
    if will_run:
    yield 233
    else:
    return ""

    try:
    with test(will_run=False) as q:
    print(1234)
    except RuntimeError:
    pass
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3078 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:43 · PVG 08:43 · LAX 16:43 · JFK 19:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.