Context manager to temporarily change the variable of a register [aka write swap(a,b)]

Evan Driscoll evaned at gmail.com
Tue Aug 25 22:47:17 CEST 2009


On Aug 25, 3:25 pm, "Diez B. Roggisch" <de... at nospam.web.de> wrote:
> Modifying locals isn't really allowed - it might stop working with
> certain implementations of python.
>
> And to be honest - I don't really see a use-case for your whole
> approache. Why don't you want to introduce a new name?

Wow, this actually was very helpful, because it forced me to clarify
what I'm doing to myself, and I *am* making it rather too complicated.

The reason that I can't introduce a new name is that I want to call
another function that refers to the old name. (Specifically, I'm using
this in a testing framework, and I want to mock out some things like
file I/O so want to replace 'open' and others temporarily. I don't
really want to make said function take an extra parameter which is
"the open function to use" or something like that.)

But then I don't need to modify locals. In fact, the references that I
want to affect are used in a function that isn't even on the stack
when the "with" statement is entered!

So I only need to modify a global, which is much easier than what I
was mucking about with.

So here is my simplified version that only works for globals:
    from contextlib import contextmanager

    @contextmanager
    def changed_value(var_name, temp_value):
        old_value = globals()[var_name]
        globals()[var_name] = temp_value
        try:
            yield None
        finally:
            globals()[var_name] = old_value


    x = 5
    print "5:", x
    with changed_value("x", 10):
        print "10:", x
    print "5:", x

    y = 7

    def test():
        print "5:", x
        with changed_value("x", 20):
            print "20:", x
            print "7:", y
        print "5:", x

    test()

    print "5:", x

How does that look?

And thanks for making me think about what I'm doing. :-)

Evan



More information about the Python-list mailing list