AlexPers
AlexPers

Reputation: 23

using "with" statement on class methods

I'm required to use "with" on a method of an object and not on the object itself.

Here is what I've already tried:

class LSTM:
    ...

    def run(self):
        def __enter__(self):
            do something

            return self

        def __exit__(self, type, value, tb):
            return self

An example of I want to use the function in main:

lstm = LSTM(...)
with lstm.run():
   ...

The error I get:

AttributeError: __enter__

Upvotes: 1

Views: 67

Answers (3)

Géry Ogam
Géry Ogam

Reputation: 8027

The context expression lstm.run() of your with statement does not evaluate to a context manager but to None, since there is no return statement in your run method.

Cf. https://docs.python.org/3/reference/compound_stmts.html#the-with-statement

Upvotes: 0

MisterMiyagi
MisterMiyagi

Reputation: 50076

The object returned by your method must be a context manager. Write your method as a generator and apply the contextlib.contextmanager decorator to automatically create the proper helper object:

from contextlib import contextmanager

class LSTM:
     @contextmanager
     def run(self):
         # prepare
         yield self
         # clean up

The object created by the decorator uses anything before the yield as __enter__, and anything after it as __exit__. Whatever is provided by yield is available for use in the as clause of the with statement. If an error terminates the context, it is raised at yield.

Upvotes: 3

rdas
rdas

Reputation: 21275

When you write:

with soemthing:

Then the object soemthing needs to have those __enter__ & __exit__ methods.

So for:

with lstm.run():

The object returned by lstm.run() needs to have the __enter__ and __exit__ methods - the fact that lstm has those methods is of no consequence.

What you should do will depend on what you're trying to achieve. But this:

with lstm:

Will call the __enter__ & __exit__ methods you have defined.

Upvotes: 1

Related Questions