view source/know-in-python.rst @ 201:b6864a86e876 default tip

Przetłumaczone getting-started
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Sun, 15 Jul 2012 13:27:27 +0200
parents 1ba803131dd9
children
line wrap: on
line source

What do you need to know in Python
==================================

Global and local scopes
-----------------------

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*.

.. code-block:: python

    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.


Default scope
-------------

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.


Functions passed as parameters
------------------------------

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:

.. code-block:: python

    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.

Method binding
--------------

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.

.. code-block:: python

    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.

Closures
--------

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.

.. code-block:: python

    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:

.. code-block:: python

    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.


Star arguments
--------------

You can define a function that takes a variable number of arguments:

.. code-block:: python

    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:

.. code-block:: python

    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:

.. code-block:: python

    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.