should the return value for `__enter__` method always be `self` in python
Asked Answered
D

1

10

Shouldn't the return value for the __enter__ method be self always.

Python documentation says :

object.__enter__(self) Enter the runtime context related to this object. The with statement will bind this method’s return value to the target(s) specified in the as clause of the statement, if any.

With this, to do anything practical, should't self be returned always from __enter__ method of a class as without it one would not be able to call other class methods on the context.

For example, in the following code, s.main() works fine but b1.main() errors out.

class a(object):
    def __init__(self):
        pass

    def __enter__(self):
        return self

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

    def main(self):
        print " in a::main self %d " , id(self)


class b(object):
    def __init__(self):
        pass

    def __enter__(self):
        return "something else"

    def __exit__(self ,type, value, traceback):
        pass

    def main(self):
        print "in b::main !! self id " , id(self)

with a() as s:
    s.main()

with b() as b1:
    b1.main()

s = a()
s.main()
Dismantle answered 9/7, 2016 at 12:35 Comment(4)
The question boils down to "can you imagine a case, where it would be practical to return something other than self from __enter__". And, well, that depends on your fantasy.Wiliness
Definitely not always: github.com/zzzeek/sqlalchemy/blob/…Conceptacle
I think anyone interested in this question might also benefit from MisterMiyagi's more detailed answer on my related questionUthrop
Another example is tempfile.TemporaryDirectory in the standard library.Antares
C
4

Not if it makes sense to use an attribute of the instance as the context manager:

class A:
    def __init__(self, useful_obj):
        self.useful_obj = useful_obj

   def __enter__(self):
       return self.useful_obj

   def __exit__(self):
       pass

with A(some_obj) as a:
    # magic done implicitly by a.useful_obj
    .
    .
    .

This situation can be seen in SqlAlchemy's code.

The code sample that you provided would work if you use any of the str methods, for example:

with b() as b1:
    print b1.upper()

>> SOMETHING ELSE
Conceptacle answered 9/7, 2016 at 12:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.