4

I'm confused about "x" in the python code below.

>>> # Grocery list
... grocery_list = ['apples', 'bananas', 'oranges', 'milk']
>>> for x in grocery_list:
...     print(x, len(x))

I am confused about x's role in the for statement above. Is "x" a variable that is being defined within the for statement, or is it something else? It just seems different than how I am used to defining a variable, but I noticed "x" can be anything, which makes me think it is, in fact, a user-defined variable.

Please help.

3
  • 1
    Time to read tutorial and documenation ;) Commented May 2, 2011 at 16:22
  • 1
    Python's for loop is different than many of the other common languages. It is much more like the foreach loop found in some languages, as it iterates over a list of objects instead of just incrementing an index. Commented May 2, 2011 at 16:39
  • 4
    My strong advice is to ban the word 'variable' in Python. Its only correct use is to mean 'identifier' or 'name', but this is ambiguous relatively to the meaning it has in other languages : 'chunk of memory whose content can change'. There are no variables in this sense in Python, there are only objects. So it's better to say 'identifier' each time it is necessary to designate an identifier, and 'object' each time it is necessary to designate an object. Such a fantastic looogic ! Commented May 2, 2011 at 16:53

8 Answers 8

8

Yes it's defined within the for statement. It's just a placeholder for an element in the list and can be called anything, e.g.

grocery_list = ['apples', 'bananas', 'oranges', 'milk']
for grocery in grocery_list:
  print(grocery, len(grocery))
Sign up to request clarification or add additional context in comments.

1 Comment

The name used is also defined in the rest of the scope containing the statement. Python has several name binding statements (for, def, class, with) in addition to simple assignment (=)
4

Python is a late-binding dynamic language. While Python programmers and the Python documentation frequently use the terms "variable" and "assignment" the more precise terms are "name" and "binding."

In your example x is a name of an object. At each iteration over the loop it's bound to the next object from your list. Python lists, and most other Python containers as well as many other Python object classes, feature iteration functions. That is to say that they define functions following a protocol which allows them to be used in for loops.

As you've noted a Python name (analogous to a "variable" in other languages) can be bound to any object of any type. A list can contain any mixture of object references. Thus, when you iterate over a list your "variable" (or loop name(s)) can be bound to objects of different types, potentially different types on each pass through the loop.

You can also have multiple names bound through "tuple unpacking" at each step through the iteration. For example the following snippet of code is a commonly used way to deal with dictionaries:

for key, value in some_dictionary.items():
   # do something with each key and its associated value

This form isn't specific to dictionaries. The .items() method of dictionaries returns a sequence of two item tuples and this form of for loop could be used with any list or sequence which returned two-item tuples (or even two-item lists). Similarly you could see tuple unpacking used on sequence consisting of items which contain a uniform number of items:

for category, item, quantity, price in some_invoice_query():
    # do something with these items, etc.

Conceptually a "variable" in most programming languages is a placeholder for data of a certain type (as well as a name by which that placeholder is referred throughout a program's source code). However, in Python (and other late-binding dynamic languages) a name is a reference to an object and conveys no constraint regarding the type or class of object to which the reference is made.

You can, rather crudely, think of Python names as if they were all void pointers in C.

3 Comments

Thanks Jim, your response is very informative. It took a couple of read-throughs, but I'm pretty sure I understand. Variables, by nature, are constraining in the sense that they typically limit the data they hold to only a certain type. Where as names are identifiers for objects, which in python can hold any data type without prior specification (or, in programming terms, type declaration).
MSey: You essentially have it. In Python values have type (they are objects). Names (variables) are not constrained to any type. It's the programmer's responsibility to ensure that they use objects in a meaningful away (that is to say that they access only those attributes and methods which they know should be supported by the objects they're manipulating and only using the proper calling signatures and semantics to them). Using exception handling or, if necessary, 'issubclass()' is considered more Pythonic then testing for class/type directly. Python3 has "abstract base class" support.
One other note worth making ... object instances in Python are first class data ... they can be manipulated just as you would numbers or strings. You can append an object to a list and dispatch calls or access attributes of those using the expected syntax (some_list[index].somemethod() ... for example). It also means that you can have classes, functions, or methods which dynamically create and return other classes or functions ... and you can have dictionaries and lists of objects, threads, etc without any syntactic fuss.
1

x is a name in your current namespace, and the objects in grocery_list are assigned to this name one after another.

Comments

1

I think it is okay for you to treat x as a variable that is being defined within the for statement. Anything else is okay too. Python does not require a seperated "define" process, any variable is "defined" the first time it has been given a value.

Comments

1

The variable will be assigned behind the scenes each of the values of the list, in order. If the list holds references, then the reference will be assigned to the loop variable, of course.

It's almost equivalent to:

for i in xrange(len(grocery_list)):
  x = grocery_list[i]
  # rest of code here

But much much cleaner and (potentially) faster. The name (x) is not signicifant, it can be whatever you please.

After the loop has executed, the variable remains in scope, with the value of the last iteration that ran. So if you use a break to get out of the loop, that will show:

>>> for i in xrange(100):
...   if i == 10: break
...
>>> i
10

2 Comments

"each of the values of the list" No. Each of the objects referenced in the list
Actually x is NOT local to the loop and the binding to x will still be in scope after the loop has been completed (including if the loop termination was via break or an exception). The binding ("assignment") performed by the for, and those performed with the loop's body (called a "suite" in Python parlance) are all in scope for the surrounding code.
1

x is a temporary variable that steps through a sequence. In lists, x will step through each item in the list.

>>> grocery_list = ['apples', 'bananas', 'oranges', 'milk']
>>> for x in grocery_list:
...     print(x, len(x))
...
apples 6
bananas 7
oranges 7
milk 4
>>> print(x)
milk

EDIT: Apparently x remains defined even after the for loop exits.

A few more examples should clear things up:

>>> for x in 'some string': # x is bound to each character in the string
...     print(x)
...
s
o
m
e

s
t
r
i
n
g
>>> for x in (0, 1, 2, 3): # x is bound to each number in the tuple
...     print(x)
...
0
1
2
3
>>> for x in [(0,0), (1,1), (2,2)]: # x is bound to each tuple in the list
...     print(x)
... 
(0, 0)
(1, 1)
(2, 2)

1 Comment

@user496713 Alas, I don't observe the error, nor in the command line nor in Edit IDLE. Anyway it is pointed out as a syntax error, that doesn't mean that the identifier doesn't exist any more
0

In your example, x is the user-defined variable to which each value in grocery_list will be assigned in turn.

1 Comment

Replace the word 'variable' with 'identifier', and 'value in grocery_list' with 'object referenced in grocery_list', and then your sentence will cease to be ambiguous and confusioning
0

One must remember what a Python variable stores. It stores a location in memory where the object is pointing at is present. In other words, Python variables are basically pointers (void*s). They "know how to find their objects."

If you have x = 5 y = 3

the assignment y = x actually hands a copy of the memory address where 5 is stored to y. Now x and y point at the copy of 3 in memory. Suppose you attempt this

x = [1,2,3] for k in x: k = 0 What happens? You hand k a copy of the memory address where each item is stored. You then assign k to point a 0. The items in x are left undisturbed.

Now do this

x = [[1,2,3], [4,5,6], [7,8,9]] for k in x: k[0] = 0

Then x holds the list

[[0, 2, 3], [0, 5, 6], [0, 8, 9]]

You can change state of a mutable object via its memory address.

The moral: Python variables know WHERE to find their objects because they know where they are located in memory. When you assign one variable to another, you hand the recipient variable a copy of the donor variable's address. The loop variable in a for loop is just another variable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.