1

In C and variants, when you have something like this:

{
  tmp1 <- 5
  tmp2 <- 2
  print(tmp1 + tmp2)
}

a 7 will be printed, but the tmp1 and tmp2 variables will be removed from stack once the scope } ends. I sometimes want similar functionality in python so that I do not have to clean up (many) temporary variables after some point in time.

In R one can use local({insert piece of code}) for exactly this purpose.

How do we get similar but readable behavior in python?

Davor Josipovic
  • 5,296
  • 1
  • 39
  • 57
  • 4
    Don't try to program C in Python. Python does not have block scope, don't try to simulate it. You don't need to clean up variables. – Daniel Roseman Jul 16 '18 at 09:58

5 Answers5

2

There is not any special syntax for that, but you can achieve something like that, by deleting the variables manually:

tmp1 = 5
tmp2 = 2

print(tmp1 + tmp2)

del tmp1
del tmp2

If you don't like this syntax you can use:

def local(f): 
  f()

@local
def block(): 
  tmp1 = 5
  tmp2 = 2
  print(tmp1 + tmp2)

That is basically same as:

def block(): 
   ...
local(block)

(https://hackernoon.com/decorators-in-python-8fd0dce93c08)

But the point is really unidiomatic.

Jan Matula
  • 135
  • 1
  • 1
  • 10
  • Interesting answer. Since I was hoping for something readable/comprehensible, I can not accept it. But you could further improve your answer by explaining why the definition evaluates. – Davor Josipovic Jul 16 '18 at 10:23
1

Actually, you can implement something tricky to simulate.

import inspect
from contextlib import contextmanager


@contextmanager
def Local():
    enter_locals = set(inspect.currentframe().f_back.f_back.f_locals.keys())
    yield
    exit_locals = set(inspect.currentframe().f_back.f_back.f_locals.keys())
    substract = exit_locals - enter_locals
    for variable in substract:
        del inspect.currentframe().f_back.f_back.f_locals[variable]

with Local():
    a = 1
    b = 2
    print(a + b)

print(a + b)

# 3
# ...
# ----> 6 print(a + b)
#
# NameError: name 'a' is not defined

But it is really not recommended. Why you want to simulate other languages in Python? Python is Python, no block scope, is no block scope.

Sraw
  • 18,892
  • 11
  • 54
  • 87
  • Python is (mis)used in many different contexts. I am aware that there is no block scope (neither there is in R), but it doesn't mean that there are no ways to get similar behavior. Hence the question. – Davor Josipovic Jul 16 '18 at 10:19
  • 1
    The code snippet given in answer shows a simple simulation. – Sraw Jul 16 '18 at 10:22
1

OK an engineered solution finally, with which you can still intentionally leak selected variables.

from scoping import scoping
a = 2
with scoping():
    assert(2 == a)
    a = 3
    b = 4
    scoping.keep('b')
    assert(3 == a)
assert(2 == a)
assert(4 == b)

https://github.com/l74d/scoping

l74d
  • 177
  • 1
  • 2
0

See https://stackoverflow.com/a/292502/51685 for the skinny on Python's variable scoping rules.

Variables exiting scope are cleaned up automatically, but you can also delete references to them using the del keyword.

very_large_data = 'x' * 1_000_000_000  # a gigabyte of x!
# do things...
del very_large_data  # that gigabyte will be garbage-collected soon after

If you're worried about "scope pollution" for making debugging and so on easier, just refactor your code into smaller functions and/or classes (so you can stash shared state in self.)

AKX
  • 152,115
  • 15
  • 115
  • 172
0

from What's the scope of a variable initialized in an if statement?

Python variables are scoped to the innermost function, class, or module in which they're assigned. Control blocks like if and while blocks don't count, so a variable assigned inside an if is still scoped to a function, class, or module.

So if you are wondering why this works:

for i in range(0, 3):
    a = i
print(a)

>> 2

and why is a accessible outside the for loop then the answer is, this is python and not c++ or R. Deleting them would be a non-pythonic way of doing things yet you can clearly do so forcefully by looking at the other answers

Ishan Srivastava
  • 1,129
  • 1
  • 11
  • 29