human
I am working on the file "Living_in_a_noisy_world_with_James_Powell_rwatch_module.ipynb".
The first task is:
Defining a generic noisy context manager
This will be a very simple change from the previous one, by letting the Noisy class accept any noisy function, which takes obj and return a noisy version of obj, only for complex-valued objects.
Can you write Python code for it?

=====
Can you provide a the Python code you requested?
assistant
#Here is the Python code you requested.

class Noisy(object):
    def __init__(self, noise):
        def add_white_noise_to_complex(frame, obj):
            if isinstance(obj, complex):
                info = getframeinfo(frame)
                if '<stdin>' in info.filename or '<ipython-' in info.filename:
                    return noise(obj)
            return obj

        self.rwatch = add_white_noise_to_complex

    def __enter__(self):
        setrwatch(defaultdict(lambda: self.rwatch))

    def __exit__(self, exc_type, exc_val, exc_tb):
        setrwatch({})

print(1j)
with Noisy(lambda obj: obj + np.random.normal()):
    print(1j)
print(1j)

print(1j)
with Noisy(lambda obj: obj * np.random.normal()):
    print(1j)
print(1j)

print(1j)
with Noisy(lambda obj: obj + np.random.normal(10, 0.1) + np.random.normal(10, 0.1) * 1j):
    print(1j)
print(1j)