user6182051
user6182051

Reputation:

Python variables scope in loops example

I am new with Python and confused regarding the scope of variables which are declared inside loops. I have seen some examples but it is hard for me to understand it in my specific case.

For example, I saw the following code segment here:

with ZipFile(self.archive_name, "r") as archive:
    for id, files in data.items():
        if files:
            print("Creating", id)
            dirpath = os.path.join(directory, id)

            os.mkdir(dirpath)

            for file in files:
                match = pattern.match(filename)
                new = match.group(2)
                new_filename = os.path.join(dirpath, new)

                content = archive.open(file).read()
            with open(new_filename, "wb") as outfile:
                outfile.write(content)

I basically have the above code repeated in very much the same way but with different statements executed inside the loops. These similar code segments are one after the other inside my __main__. My question is: in that repeated code do I need to give new names to the variables for archive, id, file, files, outfile or not? Will there be a clash or something? Are there any good-practice concerns to keep in mind?

Upvotes: 1

Views: 1587

Answers (2)

Steve Jessop
Steve Jessop

Reputation: 279225

Assuming this code is in a function then the scope of the variables is to the end of the function. If this code is at module-level then the scope of the variables is the module (aka global) scope.

You don't have to use different names. The following code will merely assign different objects to the archive variable at different times:

with ZipFile(self.archive_name, "r") as archive:
    print(id(archive))

with ZipFile(self.archive_name, "r") as archive:
    print(id(archive))

It's equivalent to this:

archive = ZipFile(self.archive_name, "r")
with archive:
    print(id(archive))
archive = ZipFile(self.archive_name, "r")
with archive:
    print(id(archive))

That is to say, the blocks associated with with statements and loops don't define a scope so far as variables are concerned, they are "just" assignments. You should see two different values printed for the ids of the different objects.

Beware that since your sample code uses id as a variable name, my example using the built-in function id should be used with care!

Are there any good-practice concerns to keep in mind?

At risk of straying into opinionated territory:

  • You rarely use the value of a loop variable outside the loop. So it's usually fine to use the same loop variable again in a new loop later in the function, but in general you should examine all uses of that variable name in the function before using it again, to be sure. For module-level code this is even worse: before adding the second loop you'd need to make sure that no external users of your module are relying on the variable having the value that the first loop left in it.
  • Unless the object is serving the exact same role in the two different places, then although it's safe to re-use a variable later in the function it can still be a little confusing.
  • Obviously before copy-pasting code twice into a function you want to be reasonably sure that in your particular case, repetition (presumably with some changes) really is better than defining another function and calling it twice.

Upvotes: 1

chepner
chepner

Reputation: 530902

In general, an indented block does not start a new scope. Only modules, classes, and functions define new scopes. (Well, almost. In Python 3, the indices in a list/set/dict comprehension are local to the comprehension.)

In your example, for instance, archive is in scope for the entire module/class/function in which the with statement occurs, as are any variable first assigned to within the body of the with statement. If the with statement is at module scope, then all assignments are to module globals. If it is at the top level of a class definition, they are all class attributes. If it is (as is likely) defined in a function or method declaration, then they are local to that function.

Upvotes: 1

Related Questions