Если возвращаемое значение для метода `__enter__` всегда будет` self` в python

Должно ли возвратное значение для метода __enter__ быть self всегда.

Документация Python говорит:

object.__enter__(self)Введите контекст времени выполнения, связанный с этим объект. Оператор with свяжет эти методы с возвращаемым значением. target (s), указанные в предложении as, если таковые имеются.

При этом, чтобы делать что-либо практическое, shouldtt self всегда возвращалось из метода __enter__ класса, так как без него нельзя было бы вызвать другие методы класса в контексте.

Например, в следующем коде s.main() работает нормально, но ошибки b1.main() отсутствуют.

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

Нет, если имеет смысл использовать атрибут экземпляра в качестве менеджера контекста:

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 code.

Пример кода, который вы предоставили, будет работать, если вы используете какой-либо из методов str, например:

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

>> SOMETHING ELSE