Whenever you reference a name in Python, it looks for it in several scopes. First it tries to find it in the local scope, which is usually the body of the function that is being currently executed. If the name is not there, Python tries the global scope, which is the body of the module. When that fails, it tries the buildins.
import os
# The name *os* gets defined in the *global* scope.
g = 3
# Define variable *g* in the *global* scope with value 3.
def my_function(x):
# The name *x* gets defined in *local* scope of *my_function*
# *x* is found in the *local* scope and its value is
# assigned to new variable *y* created in *local* scope.
y = x
# The name *os* is not found in the *local* scope, so the *global*
# scope is tried. A new variable *os* is created in the *local* scope
# with value of the *os* from the *global* scope.
os = os
# The name *g* from *global* scope is imported into the *local* scope.
global g
# The *global* variable *g* is assigned the value of *local*
# variable *x*
g = x
my_function(3)
In JavaScript you have a whole hierarchy of scopes – each new nested function creates a new scope. The scopes are searched beginning from the innermost up to the global object.
In Python, when you create a new name, it goes by default to the local scope (when you are at the module scope, it’s equal to the global scope). You don’t need to do anything special to make that happen.
In JavaScript, variables go to the global object by default. You have to use the var keyword to have them defined locally.
Everything is an object in Python. In particular, a function is an object. This means that you can assign a function to a variable or pass it as a function argument. This may be useful when you want to have some generic algorithms. This is used in the sort method so that you can, for example, sort strings in case-insensitive way:
def lowercase(s):
return s.lower()
my_list = ['a', 'B', 'c']
my_list.sort(key=lowercase)
print my_list
You can pass functions as parameters and assign them to variables in JavaScript too, although there is one important detail that is different about methods.
Methods in Python are bound to object instances. This means that you can pass them around as shown above, and they will still remember what object they belong to.
def call_with_a(method):
method('a')
my_list = []
call_with_a(my_list.append)
print my_list
This is not true for JavaScript. In JavaScript the functions and methods don’t know where they came from, and they get the reference to their object at the moment when they are called.
You can define a function inside other function in Python. That new function then has access to all the variables in the local scope of the initial function. Moreover, if you return that new function from the original function, all the variables in the original function’s scope are still alive – because the new function still has access to them. This saved scope is called a closure.
An example use of a closure is a “private” variable that can be only accessed by get and set functions.
def create_get_set():
"""
Get a pair of functions for getting and setting a hidden value.
Using a closure.
"""
value = None
def get():
return value
def set(new_value):
value = new_value
return get, set
The value variable stays in the memory even after create_get_set finishes, because the get and set functions still hold a reference to it. Because they are the only objects holding reference to it, the variable is effectively hidden from other code. You could have a similar effect by using an object:
class GetSet(object):
def __init__(self):
self.value = None
def get(self):
return self.value
def set(self, new_value):
self.value = new_value
def create_get_set():
"""
Get a pair of functions for getting and setting a hidden value.
Using a closure.
"""
getset = GetSet()
return getset.get, getset.set
Here instead of a closure we have an explicit getset object. Again, this object stays in memory because the bound methods get and set hold a reference to it. This couldn’t be done in JavaScript.
You can define a function that takes a variable number of arguments:
def average(*args):
total = 0
for arg in args:
total += arg
return float(total)/len(args)
And you can even have a function that takes keyword arguments:
def get_arguments(*args, **kwargs):
return args, kwargs
get_argumenst(1, 2, 3, four=5)
You can also call a function and pass it a dictionary or list as the argument:
my_list = [1, 2, 3]
my_dict = {'four': 5}
get_arguments(*my_list, **my_dict)
In JavaScript there are other mechanisms for doing that: the arguments keyword has the list of all parameters passed to a function. These are all positional arguments, JavaScript doesn’t have keyword arguments. The apply method of a function lets you pass an array of parameters in a function call.