Temporarily changing a variable's value in Python

Python 3.4 provides this neat tool for temporarily redirecting stdout:

# From https://docs.python.org/3.4/library/contextlib.html#contextlib.redirect_stdout
with redirect_stdout(sys.stderr):
    help(pow)

The code is not too complicated, but I would not want to write it again and again, especially since some thoughts went into it to make it a repeated participant:

class redirect_stdout:
    def __init__(self, new_target):
        self._new_target = new_target
        # We use a list of old targets to make this CM re-entrant
        self._old_targets = []

    def __enter__(self):
        self._old_targets.append(sys.stdout)
        sys.stdout = self._new_target
        return self._new_target

    def __exit__(self, exctype, excinst, exctb):
        sys.stdout = self._old_targets.pop()

I am wondering if there is a general way to use the operator withto temporarily change the value of a variable. Two other use cases from sys: sys.stderrand sys.excepthook.

In an ideal world, something like this would work:

foo = 10
with 20 as foo:
    print(foo) # 20
print (foo) # 10

I doubt that we can do this work, but maybe something like this is possible:

foo = 10
with temporary_set('foo', 20):
    print(foo) # 20
print (foo) # 10

I can somehow make it work by rooting in globals(), but it will not want to be used by anyone.

: , "foo = 10" , , . :

  • stderr, redirect_stdout
  • sys.excepthook. , - excepthook ( , , ), , - . . .
+7
3

@arthaigo, :

from contextlib import contextmanager

@contextmanager
def temporary_assignment(object, new_value):
  old_value = eval(object)
  globals()[object] = new_value
  yield
  globals()[object] = old_value
+1

, , , :

class test_context_manager():
    def __init__(self, old_object, new_object):
        self.new = new_object
        self.old = old_object
        self.old_code = eval(old_object)
    def __enter__(self):
        globals()[self.old] = self.new
    def __exit__(self, type, value, traceback):
        globals()[self.old] = self.old_code

, , , , .

:

x = 5
print(x)
with test_context_manager("x", 7):
    print(x)

print(x)

:

5
7
5

:

def func1():
    print("hi")

def func2():
    print("bye")

x = 5
func1()
with test_context_manager("func1", func2):
    func1()

func1()

:

hi
bye
hi
+6

closure?

.

#!/usr/bin/python

def create_closure(arg):
    var = arg

    def hide_me():
        return var

    return hide_me


x = 10
clo = create_closure(x)

x *= 2
x2 = clo()
x += 1

print "x: {0}".format(x)
print "x2: {0}".format(x2)

:

x: 21
x2: 10

, , , , , .

+1

Source: https://habr.com/ru/post/1540138/


All Articles