如果`__enter__`方法的返回值总是在python中是`self`

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

__enter__方法的返回值不应始终为self

Python文档说:

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.

有了这个,为了做任何实际的事情,不应该始终从类的__enter__方法返回self,因为没有它,就不能在上下文中调用其他类方法。

例如,在以下代码中,s.main()工作正常,但b1.main()错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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()


如果使用实例的属性作为上下文管理器是不合理的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
    .
    .
    .

这种情况可以在SqlAlchemy的代码中看到。

如果您使用任何str方法,则您提供的代码示例将起作用,例如:

1
2
3
4
with b() as b1:
    print b1.upper()

>> SOMETHING ELSE