Call By Value and Call By Reference
Beginning programmers can skip this section. This is a digression
for experienced C and C++ programmers.
Most programming languages have a formal mechanism for determining
if a parameter receives a copy of the argument (call by
value) or a reference to the argument object (call
by name or call by reference). The
distinction is important because programming languages like C++ allow us
to provide a reference to a global variable as input to a function and
have that global variable updated by the function without an obvious
assignment statement.
The following scenario is entirely hypothetical for Python
programmers, but a very real problem for C and C++ programmers. Imagine we
have a function to2
, with this kind of definition in
C.
int to2( int *a ) {
/* set parameter a's value to 2 */
*a= 2;
return 0;
}
This function changes the value of the variable a
to 2. This would be termed a side-effect because it
is in addition to any value the function might return normally.
When we do the following in C
int x= 27;
int z= to2( &x );
printf( "x=%i, z=%i", x, z );
We get the unpleasant side-effect that our function
to2
has changed the argument variable,
x
, and the variable wasn't in an
assignment
statement! We merely called a function,
using x
as an argument. In C, the
&
operator is a hint that a variable might be
changed. Further, the function definition
should
contain the keyword
const
when the reference is
properly read-only. However, these are burdens placed on the programmer to
assure that the program compiles correctly.
Python does not permit this kind of call-by-reference problem in the
first place. The arguments to a function are always references to the
original underlying object, not the variable. In the Python version of the
above example, the variable x
is a reference to an
integer object with a value of 27. The parameter variable in the
to2
function is a copy of the reference, and it is
local to the function's scope. The original variable,
x
, cannot be changed by the function, and the original
argument object, the integer 27, is immutable, and can't be changed
either.
If an argument value is a mutable object, the parameter is a
reference to that object, and the function has access to methods of that
object. The methods of the object can be called, but the original object
cannot be replaced with a new object.
Programmers intimate with the implementation details behind C know
that manipulating a copy of a value directly can be far more efficient
than working through references. This is true only when the language has
some high-performance data types that would benefit from call by value
processing. Unlike C or Java, Python has no data types that benefit from
this kind of special case handling. All data elements are passed by
reference in a simple, uniform manner.
It also means that, in general, all variable updates must be done
explicitly via an
assignment
statement. This makes
variable changes clear.