Python 将参数传递给u_enter__

Python 将参数传递给u_enter__,python,with-statement,Python,With Statement,只是通过陈述来学习 问题是,我可以把一个参数传递给\uuuuuu enter\uuuuu 我有这样的代码: class clippy_runner: def __enter__(self): self.engine = ExcelConnection(filename = "clippytest\Test.xlsx") self.db = SQLConnection(param_dict = DATASOURCES[STAGE_RELATIONAL])

只是通过陈述来学习

问题是,我可以把一个参数传递给
\uuuuuu enter\uuuuu

我有这样的代码:

class clippy_runner:
    def __enter__(self):
        self.engine = ExcelConnection(filename = "clippytest\Test.xlsx")
        self.db = SQLConnection(param_dict = DATASOURCES[STAGE_RELATIONAL])

        self.engine.connect()
        self.db.connect()

        return self

我想将filename和param_dict作为参数传递给
\uuuu enter\uuuu
。那可能吗?

不,你不能。将参数传递给
\uuuu init\uuuu()


您是否可以通过类构造函数将值传递给
\uuuu init\uuu


    #!/usr/bin/env python

    class Clippy_Runner( dict ):
        def __init__( self ):
            pass
        def __call__( self, **kwargs ):
            self.update( kwargs )
            return self
        def __enter__( self ):
            return self
        def __exit__( self, exc_type, exc_val, exc_tb ):
            self.clear()

    clippy_runner = Clippy_Runner()

    print clippy_runner.get('verbose')     # Outputs None
    with clippy_runner(verbose=True):
        print clippy_runner.get('verbose') # Outputs True
    print clippy_runner.get('verbose')     # Outputs None

您可以使用contextmanager装饰器传递参数:


我觉得使用
contextmanager
可以提供参数,但不能将参数提供给
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>会让人感到困惑,我认为使用
contextlib

更多详细信息,请参见下文

一个简单的例子 你的例子 输出

Carson
1
{'key': 'item_1'}
Carson: age=28
inside
__exit__
outside
ExcelConnection connect
SQLConnection connect
do something...
ExcelConnection disconnect
SQLConnection disconnect
关于
contextmanager
上下文管理器(基本上)做三件事:

  • 它在代码块之前运行一些代码
  • 它在代码块之后运行一些代码
  • 或者,它会抑制在代码块中引发的异常
  • 被接受的答案(我觉得是不正确的)说你不能,你应该这样做

    class Comedian:
        def __init__(self, *jokes):
            self.jokes = jokes
        def __enter__(self):
            jokes = self.jokes
            #say some funny jokes
            return self
    
    …虽然这通常是你会做的,但它并不总是最好的解决方案,甚至不是唯一的解决方案,而且肯定不是唯一的解决方案

    我假设你想要的是能够做类似的事情

    funny_object = Comedian()
    with funny_object('this is a joke') as humor:
        humor.say_something_funny()
    
    如果是这样的话,它并不比这复杂,那么你可以这样做

    class Comedian:
        def __enter__(self):
            jokes = self.jokes
            #say some funny jokes
            return self
        def __call__(self, *jokes):
            self.jokes = jokes
    
    …这样,您仍然可以使用所需的任何参数初始化对象,并像通常一样对对象执行任何其他操作,但当您将对象用作上下文管理器时,首先调用其调用函数,并为上下文管理器设置一些参数

    这里重要的是要准确地理解上下文管理器在Python中是如何工作的

    在Python中,上下文管理器是定义enter方法的任何对象。执行此操作时会自动调用此方法

    with object as alias:
        alias.do_stuff()
        ..
    
    …注意对象后面没有几个“()”,它是一个隐式函数调用,并且不接受任何参数

    您可能会想到将参数传递给enterfrom

    with open(filename) as file:
        "do stuff with file..
    
    但这与重写enter不同,因为“open”不是一个对象,而是一个函数

    一个很好的练习是打开一个交互式python控制台并键入“open”+[ENTER]

    >>> open
    <built-in function open>
    
    …您可以用同样的方法定义自己的上下文管理器功能,甚至可以覆盖“打开”的定义

    但是,在我看来,如果您需要创建一个对象,然后将其用作带有参数的上下文管理器(…我所做的),那么最好的做法是为该对象提供一个方法,该方法返回一个临时对象,该对象定义了一个enter方法,如下所示

    class Comedian:
        def context(audience):
            class Roaster:
                context = audience
                def __enter__(self):
                    audience = self.__class__.context
                    # a comedian needs to know his/her audience.
            return Roaster(audience)
    
    funny_thing = Comedian()
    with funny_thing.context('young people') as roaster:
        roaster.roast('old people')
    
    本例中调用链的顺序为; 喜剧演员。init()->喜剧演员。上下文(args)->烘焙者。输入(


    我觉得这个答案在这一部分中不见了,所以我加了上去。

    我很困惑。因为您只是在
    \uuuu init\uuuu
    传递
    ,所以您是否建议在
    \uuuuu init\uuuu
    函数中提供传递给
    参数
    <代码>定义初始化(self,filename,param_dict):self.filename=filename self.param_dict=param_dict
    def\u输入(self):self.filename…
    为什么这是公认的答案?我似乎不是唯一一个认为这是最糟糕的答案的人。“不,你不能,你把参数传递给init…”这根本不是真的,当然通过init传递参数是一种方法,但绝不是唯一的方法,也不总是最有意义的方法。。如果要将参数传递给位于的上下文管理器,请使用。。作为。。像OP这样的行,然后你肯定可以,这通常是最有意义的,取决于应用程序。(见所有其他答案)我支持这一点。我有一些只与上下文相关的设置。将它们传递给
    \uuuuu init\uuuuu
    是愚蠢的。这似乎是my的正确答案,因为您不需要在with语句中创建变量,但可以使用一个容易创建的对象(如锁)并将变量传递给with语句。回答得好!回答得很好!这应该被接受,因为它可以在
    for
    循环中使用,例如,无需每次迭代都实例化一个新对象
    with object as alias:
        alias.do_stuff()
        ..
    
    with open(filename) as file:
        "do stuff with file..
    
    >>> open
    <built-in function open>
    
    @contextmanager
    def open(..):
        ...
    
    class Comedian:
        def context(audience):
            class Roaster:
                context = audience
                def __enter__(self):
                    audience = self.__class__.context
                    # a comedian needs to know his/her audience.
            return Roaster(audience)
    
    funny_thing = Comedian()
    with funny_thing.context('young people') as roaster:
        roaster.roast('old people')