Actually i think about languages as python or java as only having pointers to objects.
while function can not rebind to what object closure 'points' in walk_vertices, if the object closure 'points' to is mutable it can of course change it. In your example you talk about a sum. That would of course be an integer or floating point number. These are immutable in python, so closure would point to an object but you can't mutate it:
x = 5
def something(ref):
# you can't change where x points to from here.
# and because an int is immutable you can't change it.
ref = 10 # rebinds ref, but not x
something(x)
print(x) # still 5
But, if you pass a mutable object you can actually store information. One way to have a very simple mutable object is just to use a list of size 1.
x = [5]
def something(ref):
# you can't change where x points to from here.
ref = 5 # rebinds ref, but not x
something(x)
print(x) # still [5]
def something2(ref):
# ref is a mutable object, so
ref[0] = 10 # ref points to the same list, but contents of list is now 10
something2(x)
print(x) # now [10]
The same construction works with any mutable object. So a dict or a class are usable as well.
class EmptyClass:
pass
x = EmptyClass()
x.data = 5
def something(ref):
ref.data = 10
something(x)
print(x.data) # now prints 10
To sum it up, python always passes something comparable to pointers. But because it has some types that are immutable you can't always use that to pass data back. You have to pass a mutable object.
Also python has no equivalent of taking the pointer of a local variable. So while everything is a pointer to an object you can't get a pointer to an pointer without having an object in between like in the list case (pointer to list of pointer).
What you can do is use 'reflection' to change the value of a local variable via locals()
x = 5
def something(d):
d['x'] = 10
something(locals())
print(x) # now prints 10