1 | initial version |

Unlike many languages, Python doesn't really have variables: only objects and names. (And namespaces, I guess.) For example,

```
sage: a = [1,2]
sage: a
[1, 2]
```

doesn't declare a variable a and set it to the list [1,2]. We sometimes talk like this, because it's often close enough for government work, but it's not really accurate. What happens is that a list object is created and the name `a`

is defined to refer to it (a process often called 'binding'). We can make other names refer to the same object:

```
sage: b = a
sage: b
[1, 2]
sage: b[0] = 17
sage: b
[17, 2]
sage: a
[17, 2]
sage: a is b
True
```

So in the case of a loop like this:

```
sage: a = [1,2]
sage: for item in a:
....: print item
....: item = 4
....:
1
2
sage: a
[1, 2]
```

a doesn't change because `item = 4`

isn't the equivalent of `(*item) = 4`

. `item`

isn't a pointer, it's just a name. `item = 4`

means "take the name 'item' and bind it to the integer object 4". From Python's perspective, why should alist care that you've decided to start using "item" to refer to the number 4?

If you want to affect `alist`

, you have to grasp one of the elements, say by getting an index:

```
sage: for i, item in enumerate(a):
....: print i, item
....: a[i] = item * 10
....:
0 1
1 2
sage: a
[10, 20]
```

Note that you *can* modify item directly, if the object referred to by item is mutable. For example:

```
sage: a = [[1,2], [3,4]]
sage: for item in a:
....: print item
....: item += [99]
....:
[1, 2]
[3, 4]
sage: a
[[1, 2, 99], [3, 4, 99]]
```

and so on.

2 | No.2 Revision |

Unlike many languages, Python doesn't really have variables: only objects and names. (And namespaces, I guess.) For example,

```
sage: a = [1,2]
sage: a
[1, 2]
```

doesn't declare a variable a and set it to the list [1,2]. We sometimes talk like this, because it's often close enough for government work, but it's not really accurate. What happens is that a list object is created and the name `a`

is defined to refer to it (a process often called 'binding'). We can make other names refer to the same object:

```
sage: b = a
sage: b
[1, 2]
sage: b[0] = 17
sage: b
[17, 2]
sage: a
[17, 2]
sage: a is b
True
```

So in the case of a loop like this:

```
sage: a = [1,2]
sage: for item in a:
....: print item
....: item = 4
....:
1
2
sage: a
[1, 2]
```

a doesn't change because `item = 4`

isn't the equivalent of `(*item) = 4`

. `item`

isn't a pointer, it's just a name. `item = 4`

means "take the name 'item' and bind it to the integer object 4". From Python's perspective, why should alist care that you've decided to start using "item" to refer to the number 4?

If you want to affect `alist`

, you have to grasp one of the elements, say by getting an index:

```
sage: for i, item in enumerate(a):
....: print i, item
....: a[i] = item * 10
....:
0 1
1 2
sage: a
[10, 20]
```

Note that you *can* modify ~~item ~~what item refers to directly, ~~if ~~*if* the object referred to by item is mutable. For example:

```
sage: a = [[1,2], [3,4]]
sage: for item in a:
....: print item
....: item += [99]
....:
[1, 2]
[3, 4]
sage: a
[[1, 2, 99], [3, 4, 99]]
```

and so on.

3 | No.3 Revision |

Unlike many languages, Python doesn't really have variables: only objects and names. (And namespaces, I guess.) For example,

```
sage: a = [1,2]
sage: a
[1, 2]
```

doesn't declare a variable a and set it to the list [1,2]. We sometimes talk like this, because it's often close enough for government work, but it's not really accurate. What happens is that a list object is created and the name `a`

is defined to refer to it (a process often called 'binding'). We can make other names refer to the same object:

```
sage: b = a
sage: b
[1, 2]
sage: b[0] = 17
sage: b
[17, 2]
sage: a
[17, 2]
sage: a is b
True
```

So in the case of a loop like this:

```
sage: a = [1,2]
sage: for item in a:
....: print item
....: item = 4
....:
1
2
sage: a
[1, 2]
```

a doesn't change because `item = 4`

isn't the equivalent of `(*item) = 4`

. `item`

isn't a pointer, it's just a name. `item = 4`

means "take the name 'item' and bind it to the integer object 4". From Python's perspective, why should ~~alist ~~the `a`

list care that you've decided to start using "item" to refer to the number 4?

If you want to affect

, you have to grasp one of the elements, say by getting an index:~~alist~~a

```
sage: for i, item in enumerate(a):
....: print i, item
....: a[i] = item * 10
....:
0 1
1 2
sage: a
[10, 20]
```

Note that you *can* modify what item refers to directly, *if* the object referred to by item is mutable. For example:

```
sage: a = [[1,2], [3,4]]
sage: for item in a:
....: print item
....: item += [99]
....:
[1, 2]
[3, 4]
sage: a
[[1, 2, 99], [3, 4, 99]]
```

and so on.

4 | No.4 Revision |

```
sage: a = [1,2]
sage: a
[1, 2]
```

`a`

is defined to refer to it (a process often called 'binding'). We can make other names refer to the same object:

```
sage: b = a
sage: b
[1, 2]
sage: b[0] = 17
sage: b
[17, 2]
sage: a
[17, 2]
sage: a is b
True
```

So in the case of a loop like this:

```
sage: a = [1,2]
sage: for item in a:
....: print item
....: item = 4
....:
1
2
sage: a
[1, 2]
```

a doesn't change because `item = 4`

isn't the equivalent of `(*item) = 4`

. `item`

isn't a pointer, it's just a name. `item = 4`

means "take the name 'item' and bind it to the integer object 4". From Python's perspective, why should the `a`

list care that you've decided to start using "item" to refer to the number 4?

If you want to affect `a`

, you have to grasp one of the elements, say by getting an index:

```
sage: for i, item in enumerate(a):
....: print i, item
....: a[i] = item * 10
....:
0 1
1 2
sage: a
[10, 20]
```

Note that you *can* modify what item refers to directly, *if* the object referred to by item is mutable. For example:

```
sage: a = [[1,2], [3,4]]
sage: for item in a:
....: print item
....: item += [99]
....:
[1, 2]
[3, 4]
sage: a
[[1, 2, 99], [3, 4, 99]]
```

and so on.

UPDATE:

Here's an example of how we would handle things like this in Python via a dictionary, without dynamically creating local variables:

```
sage: set_random_seed(3)
sage: vv = [var("x%d" % i) for i in [0..5]]
sage: vv
[x0, x1, x2, x3, x4, x5]
sage: vals = [random() for v in vv]
sage: vals
[0.43088005103813976, 0.8358366908518607, 0.8023253357960184, 0.4891524489091327, 0.7822037482240924, 0.7607638369816612]
sage: vdict = dict(zip(vv, vals))
sage: vdict
{x5: 0.7607638369816612, x3: 0.4891524489091327, x2: 0.8023253357960184, x0: 0.43088005103813976, x4: 0.7822037482240924, x1: 0.8358366908518607}
sage: some_expr = sum(random() * v**i for v in vv)
sage: some_expr
0.6925472846314387*x0^5 + 0.19968616753011514*x1^5 + 0.9416651257671081*x2^5 + 0.9556540407131406*x3^5 + 0.7656492351180494*x4^5 + 0.584583199716608*x5^5
sage: some_expr.subs(vdict)
0.804750970712524
```

Regarding the comments:

I'm afraid I don't understand what is meant by 'manually referring to variable names'. As opposed to what other methods of referring to them?

When the variables (or names) are kept in a dictionary I can do all sorts of nice things to them as a collection. Not so much if I rebind the local names something else. For example, say I do what you suggest, and type "A=B". I don't think it'll do what you want:

```
sage: var("A B")
(A, B)
sage: expr = A + B
sage: expr
A + B
sage: A = B
sage: A
B
sage: expr
A + B
```

You can give the name "A" to anything you like, but it won't affect the object to which A refers, so I don't really the the point. What I mean by "manually" is that because of the above fact, namely, that existing references to the object don't change because you changed a name, the only way you can actually take advantage of the change later is if you actually execute a command like

```
sage: A + B
2*B
```

where you have an explicit reference to the name `A`

.

It's worth rememebering that "assignment" in Python *is* using a dictionary. Type `locals()`

, for example, to see the locals() dict.

5 | No.5 Revision |

```
sage: a = [1,2]
sage: a
[1, 2]
```

`a`

is defined to refer to it (a process often called 'binding'). We can make other names refer to the same object:

```
sage: b = a
sage: b
[1, 2]
sage: b[0] = 17
sage: b
[17, 2]
sage: a
[17, 2]
sage: a is b
True
```

So in the case of a loop like this:

```
sage: a = [1,2]
sage: for item in a:
....: print item
....: item = 4
....:
1
2
sage: a
[1, 2]
```

a doesn't change because `item = 4`

isn't the equivalent of `(*item) = 4`

. `item`

isn't a pointer, it's just a name. `item = 4`

means "take the name 'item' and bind it to the integer object 4". From Python's perspective, why should the `a`

list care that you've decided to start using "item" to refer to the number 4?

If you want to affect `a`

, you have to grasp one of the elements, say by getting an index:

```
sage: for i, item in enumerate(a):
....: print i, item
....: a[i] = item * 10
....:
0 1
1 2
sage: a
[10, 20]
```

Note that you *can* modify what item refers to directly, *if* the object referred to by item is mutable. For example:

```
sage: a = [[1,2], [3,4]]
sage: for item in a:
....: print item
....: item += [99]
....:
[1, 2]
[3, 4]
sage: a
[[1, 2, 99], [3, 4, 99]]
```

and so on.

UPDATE:

Here's an example of how we would handle things like this in Python via a dictionary, without dynamically creating local variables:

```
sage: set_random_seed(3)
sage: vv = [var("x%d" % i) for i in [0..5]]
sage: vv
[x0, x1, x2, x3, x4, x5]
sage: vals = [random() for v in vv]
sage: vals
[0.43088005103813976, 0.8358366908518607, 0.8023253357960184, 0.4891524489091327, 0.7822037482240924, 0.7607638369816612]
sage: vdict = dict(zip(vv, vals))
sage: vdict
{x5: 0.7607638369816612, x3: 0.4891524489091327, x2: 0.8023253357960184, x0: 0.43088005103813976, x4: 0.7822037482240924, x1: 0.8358366908518607}
sage: some_expr = sum(random() * v**i for v in vv)
sage: some_expr
0.6925472846314387*x0^5 + 0.19968616753011514*x1^5 + 0.9416651257671081*x2^5 + 0.9556540407131406*x3^5 + 0.7656492351180494*x4^5 + 0.584583199716608*x5^5
sage: some_expr.subs(vdict)
0.804750970712524
```

Regarding the comments:

I'm afraid I don't understand what is meant by 'manually referring to variable names'. As opposed to what other methods of referring to them?

When the variables (or names) are kept in a dictionary I can do all sorts of nice things to them as a collection. Not so much if I rebind the local names to something else. For example, say I do what you suggest, and type "A=B". I don't think it'll do what you want:

```
sage: var("A B")
(A, B)
sage: expr = A + B
sage: expr
A + B
sage: A = B
sage: A
B
sage: expr
A + B
```

You can give the name "A" to anything you like, but it won't affect the object to which A refers, so I don't really ~~the ~~see the point. What I mean by "manually" is that because of the above ~~fact, ~~fact -- namely, that existing references to the object don't change because you changed a ~~name, ~~name -- the only way you can actually take advantage of the change later is if you actually execute a command like

```
sage: A + B
2*B
```

where you have an explicit reference to the name `A`

~~.~~. And that means in one way or another you're hardcoding the reference.

It's worth rememebering that "assignment" in Python *is* using a dictionary. Type `locals()`

, for example, to see the locals() dict.

[Note that one could use `exec`

to achieve your goal, but I didn't even want to mention it until I'd had a run at convincing you this is not the way to go.]

Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license.