Should loops be in their own scope? [poll]

If it actually at least was a full solution that would almost be ok, but autodelete still isn’t loop scope. And a mypy solution isn’t either and still isn’t python and isn’t always practical always. You either get a declaration keyword in the language or you probably have a hacked half-solution to something that wasn’t a big deal anyway

1 Like

The way I would describe dataclasses is that they behave as a template, you create a class representing your record or struct, and the dataclass uses that class definition as a template to automatically fill in special methods.

The scoping rules are no different:

  • the datasclass decorator is just a plain old function, it obeys the same rules as the rest of Python;
  • and the dataclassed class created is a plain old class, it too obeys the same scoping rules as the rest of Python.

We can say that the decorator programmatically takes annotated class attributes and uses them as a template for instance attributes with the same name, which I guess is a change of scope in some sense.

Yep, that’s the usual meaning of runtime :slight_smile:

For completeness, if we’re rolling our own brackets, you can of course just do this:

i=0
def foo():
    for i in range(5):
        pass
foo()
print(i)
i=30
def foo():
    for i in range(10):
        pass
foo()
print(i)

And it’s fewer keystrokes than with autodelete(…), more transparent, and actually produces true controllable loop scope.

If we want to add a local scope to the for loop, I think the cleanest way would be to have something like for local i in range(5):.

1 Like

or

local for i in range

to not confuse that it’s on the whole loop, not the i. One possibility for implementation is that it translates to the def foo above, but I don’t know the downsides, performace, etc.

@MRAB I just wanted to point out that local i has another (maybe rare?) use: make Jupyter notebooks safer. One of the nastiest bugs when prototyping in a notebook is accidentally reusing a variable from a different cell. This is because unlike real python code that rarely uses module-level code, notebooks often do use cell-level (=module-level) code to help in debugging, etc. If local became part of the language, Jupyter could treat them as cell-local, preventing those bugs.

I think an even better keyword could be something like:

blockscope for i in range(5):
  ...

The point would really be to define a scope, not a single scoped variable.

Overriding the behavior of a language keyword would mean Jupyter’s behavior would diverge even more from real Python code, building up the walls of the Jupyter garden even higher. For the tutorials, reports and quick data analysis scripts for which Jupyter was designed, it can be a great tool. However, it has many similar issues with using it for “real” code.

As such, I’m not totally sure what the motivation is for doing so when there are a number of other scientific environments/tools (e.g. Spyder, which I help maintain) that offer generally similar or in some cases more sophisticated interacting computing and data exploration capabilities using regular, “real” Python code that can be organized into proper modules and packages, plus most of the core capabilities of a competent editor/IDE.

But that’s getting a little off topic, sorry.

2 Likes

Unfortunately, autodelete will only work in the global namespace, where locals() and globals() is the same object. In a local namespace, it won’t work, since vars() is the same as locals(), and whether modifying locals() affects the local namespace is implementation-dependent (and specifically in CPython, it has no effect). I was hoping to find a way to do that, but to the best of my knowledge it is impossible unless python exposes a new API that allows deleting a variable whose name is only known at runtime. If you know of a workaround (even CPython-specific), would be great to know!

Just to clarify what I meant:

def f():
  with autodelete('x', vars()):
    for x in range(3):
      pass
  print(x)

f()  # prints 3

The Enclosure approach in Kazuya’s comment would run into the same problem.

1 Like