What is a reference

Many people confuse pointer and reference and use terms interchangeably. Reference is a more general term. a value by any id. 

What is a pointer?

pointer=”address in memory”,  A pointer is an integer that contains a memory address of the first byte of a value.

What is a reference?

Reference is a general term for usage of some identifier to access a value.

Reference can be based on, some value ( for example an ordinal value) like: connection id, or process id, address of value in memory (pointer). in python values are referenced by object id – I guess it is the id of an object in the garbage collection table.

a demonstration that it is really an id behind every value:

import ctypes
def objects_by_id(id_):
    #this might work only as long as object still exists
    return ctypes.cast(id_, ctypes.py_object).value

x="my value"
print("id is:", id(x) )
print("found it by id, it is:", objects_by_id( id(x) ) )


id is: 1987162860976
found it by id, it is: my value

Dereferencing is accessing the value of the reference. 

Dereference happens also, each time the “dot” accessor is used, like in my_object.my_property it does dereference behind the scenes.

In the advanced optimization, The fewer levels of dereferencing the faster the program works, This is why for speed in python we use NumPy ndarray (a reference to a chunk of bytes) and do operations on this one reference with NumPy matrix operation functions that process the ndarray as a whole.

Introduction to data model of python:

here is an even better explanation than mine (suggested to read):

here is new version but it vary bolted and large (no need to read at the moment):

Use of references and values

( In other languages, like c++ there are “primitive” data types like integer, float, and fixed-length small values. and The others are objects – that are “data structures” that are implemented using pointers. Behind the scenes, an object is a primitive value, that contains a pointer to the first byte of the value. So everything that is an object is a pointer or a reference. )

Contrary to other languages, in python, everything is a reference and passed by reference even the simple data types. however some data types are mutable (modifiable) and some data types are immutable (not modifiable, only replaceable)

It is possible to copy a reference [for a value] to many variable names. it will still point to the same value. 

an alias in English means a different name for the same thing.

References with function call: (Because in python all values are “references”) python passes arguments also as a copy of the references. Then inside the function, when accessing the value of parameters (they are still references) it accesses the same value [and can modify the same value] of the references. The parameters store a local copy of the references.  To modify a mutable value, I need to be careful to not replace the reference in the local variable or parameter. rather work on the reference. like call the methods of the variable

def modify_my_set(a_set):
    a_set.add('a') # operate on the variable
    # a_set="123" # not replace the reference in the local variable my_set={1,2,3} print("before:", my_set) modify_my_set(my_set) print("after:", my_set) output: before: {1, 2, 3} after: {'a', 1, 2, 3}

If to put a different reference in a local variable or parameter,  only that variable will contain a different reference. it will not modify other variables that still will hold old references.

but sometimes it is desired to replace the reference.
To work on a copy of a value it is not possible to just assign them to a different name (it will not work). need to re-create the object. For example, if I wish to use a parameter as a local temporary variable, I need to create a new object with the same content, otherwise, it will modify the passed in parameter. 

#examply copy method:
mycopy=parameter_list.copy() # need python 3.3
mycopy=parameter_list[:]     # create copy
def variation_of_a_set(a_set):
    a_set=a_set.copy() # create copy and replace the local reference
    return a_set

print("before:", my_set)
print("the returned set  with 4 is " ,variation_of_a_set(my_set) )
print("after:", my_set)


before: {1, 2, 3}
the returned set  with 4 is  {1, 2, 3, 4}
after: {1, 2, 3}

If a value (which is as always passed by reference and) used multiple times, it is modified inside a function, it might create confusing bugs. so sometimes need to copy variable to prevent these bugs.

Comparison of values

==, !=

Equivalence comparison “==” is an operator of a class (a property of a class definition) it usually acts on the value (but it depends on the implementation of the class)

is ,is not

there is an id function it returns the id of the object

print(id("a")) 1987129376640 

The keyword “is” is identity comparison

 if object_a is object_b:

it compares that values have the same id, like:

 if id(object_a)==id(object_b): 

 It is like a comparison of pointers that both variables point to the same object.
 (similarly, there is “is not”)

 if object_a is not object_b:

the id() function and the “is” operator are currently (python 3.7) not overloadable