Q:

__enter__ , __exit__ , with block is not working

When I try to execute this code , it returns this error 
Traceback (most recent call last):
  File "with.py", line 13, in <module>
    with A as a:
AttributeError: __enter__"

I searched and found that this error occurs when I haven't define __enter__ or __exit__  methods. but I defined both, and still getting this error
class A:
    def __enter__(self):
        self.t='printing from enter variable t'
        return self.t

    def fun(self):
        print("inside fun")
        print(self.t)

    def __exit__(self, exception_type, exception_value, traceback):
        print("exiting.........")
        print(exception_type, exception_value, traceback)

with A as a:
    a.fun()

A:

There are two things wrong here. The error message you are getting is because you are trying to use the class itself as a context manager instead of an instance.
with A() as a: # uses an instance of A

instead of
with A as a: # uses the class A

The class A has no __enter__ and __exit__ methods as it is an instance of type.
The second is that a will be bound to the return value of the __enter__ method, in this case the string.
A string has no fun method so will raise an attribute error. I imagine you want to return self from your __enter__ method.

