Saturday, September 4, 2010

The Shebang Line

Well, this was an Easter Egg for me, so I will directly move on to what I
mean, without keeping you bewildered.

In computing, a shebang refers to the symbol '#!'. If it is used in a script,
it must come in the very beginning of the first line itself. Thus, the
common term shebang line.

The shebang line contains the absolute path of the interpreter binary for
the particular script you are running. On running executable script files,
the shebang will be automatically looked for and used, resulting in a 'smart
script', or so we can say.

The shebang line for Python scripts is,

#! /usr/bin python

As you might be wondering, this weird name comes from an inexact
combination of sharp (#) and bang (!), which are the Unix names of
the two characters. The other names are hashbang, hashpllng,  
poundbang, and crunchbang. Don't ask me... !!!

Interestingly, the shebang was introduced by Dennis Ritchie at Bell
Laboratories (Edition 8). It was then also added to BSD releases from
Berkeley's Computer Science Releases. 

If the absolute path for the interpreter binary remains the same in all the
machines that the script is run, then portability is achieved too.

More Easter Eggs:
1. When portability issues are encountered, the shebang line
    #! /usr/bin/env python
   may provide a solution.
2. The shebang actually represents a magic number in the executable
    file. This magic string is 0x23 0x21. Executable files that do not require
    an interpreter starts with other magic combinations.
3. The shebang line for Perl is,
    #! /usr/bin/perl

Wednesday, September 1, 2010

Python Tutorial, Release 2.7: Abridged (heavily!)

This tutorial is originally written by Guido van Rossum, and edited by Fred
L. Drake, Jr. . It is an excellent one, excluding some specific portions.

I felt the urge to keep a record of all the key points regarding Python, that
i grasped from this tutorial. So here goes..

1. The Python Interpreter
    Interactive mode: Ctrl + D, primary prompt, secondary prompt
    Non-interactive mode: 'python' command, sys.argv[ ]
    /usr/lib/python2.6 or /usr/lib/python3.1
2. Executable Python Script
    #! /usr/bin/ python
    $ chmod +x 
3. The  Startup File
    PYTHONSTARTUP environment variable 
    os.path(), os.environ.get(), execfile(), .join()
    sys.ps1, sys.ps2
4. Basics 
    #, numbers, , docstring (""' or """),
    sequence data types: str, unicode, list, tuple, buffer, xrange
    string (effects of ' and "), list  (don't ever forget slicing!)
    Mechanism of  slicing:
Courtesy: Python Tutorial, Release 2.7
    be wary of short circuit nature (e.g. and)
    if, elif, else, for in , range, break, continue, pass
5. Functions In Python
    def <function_name>(<argument(s)>): body
    call by value, first class, scope
    built-in higher order functions: map, filter, reduce, etc
    default argument values (evaluated only once!)
    keyword arguments: function (arg1, *arg2, **arg3)
                   *arg2  -> receives a tuple, **arg3 -> receives a dictionary
                    positional arguments before keyword arguments
    unpacking argument lists: *list_object or **dictionary_object
    lambda
6. Intermezzo Coding Style
    a, b = 10, 20 is valid (swapping is unimaginably easy!) 
    4-space indentation
    blanklines, comments, docstrings 
    spacing: a = f(1, 2) + g(3, 4) 
    self as name for first method argument
7. Functional Programming Tools
    list comprehension: >>> vec = [2, 4, 6]
                                        >>> 3*x for x in vec if x > 3   
                                        >>> [12, 18]
    del (for lists), push(), pop() and collections.deque (for strings)
    set (use it to eliminate duplicates on the fly !, thanks to Sumith) 
    dictionaries (.append(), .extend(), .keys(), .values(), .items())  
8. Modules 
    import <module_name>, 
    from <module> import <method>
    from <module> import * (not advised)
    the [if__name__ == "__main__":] clause
    PYTHONPATH, sys.path, dir() function, packages 
9. Input and Output
    regular expressions (regex)
    sys.stdin(), sys.stdout()
    repr(), str(), str.format()
    open(), close(), read(), readline(), readlines(), seek(), write()
    pickling: pickle.dump(), pickle.load()  
10. Error Handling
    try: ... except: ..., try: ... except: ... else: ..., try: except: finally: ...,
    try clause: if functions present, tries inside it too
    else clause: to prevent except from catching the error caused
                          by some other piece of code
    finally clause: always executed
                   1. on leaving the try: except:, 
                   2. when error raised by try: not handled by any except:
                   3. when there is an error in the except: itself       
    class MyClass (Exception): pass
    raise Exception (arguments)
    except Exception as inst: (arguments stored in instance.args),
    with open ('','') as :
11. Classes
     class <class_name>[(<baseclass(es)>)]:pass
     Python classes are objects
     both class and its objects are concrete
     no sense in concept of 'declaration'
     each function attribute has at least one argument named 'self'
                                                       by convention 
     __init__, __str__, __eq__, __iter__
     isinstance()
12. Mechanism of for
     this idea can be applied to any iterable in Python
Courtesy: Python Tutorial, Release 2.7

13. Concept of Generators
     yield -> return, THEN FREEZE THEN AND THERE UNTIL next()
Courtesy: Python Tutorial, Release 2.7
     "genex" -> generator expression
                           (e.g. generator in a list comprehension.
                               then replace [] with ())
                           >>> sum(i * i for i in range(0, 10))

Monday, August 30, 2010

"Pointers" in Python

Firstly, I want you to understand that, the term "pointers" used here, is a
misnomer.

In Python, there is no particular data type called a pointer; as in C. Even so,
some operations that we can perform in Python, are very similar to the
structure of a pointer.

Ok, I've been bragging till now about pointers, let me tell you what it is.

Visualize that, a new data type that you create has to be stored in a memory location in the hard disk. This memory location, has an address.
In C, a pointer can be defined whose value is such a memory 
address. Any valid operation done on this pointer, will be 
automatically reflected in the data present in that address. 

Now lets see, where this happens in Python.

Lets create a list and  copy it.
>>> a = [1,2,3]
>>>b = a 
Now lets change an element of a.
>>>a[1] = 10
>>>a
[1,10,3]
Now check the value of b.
>>>b
[1,10,3]

We can see that b has also changed. How did this happen? 

When the list a was created, it was stored in a memory location say 2000, 
and the value 2000  was put in a. When a was assigned to b, it meant that
now b too contain the value 2000. Then we changed the second element of
a, i.e, the data in the address 2000. Therefore, now if we print the value of  
a or b, we will only get the changed list, since both a and b are actually
"pointers" to the memory address 2000.

N. B.
1. Be careful with list assignments!
2. What I discussed above, does not hold for slicing operations on a list.
   When any list is sliced, first a copy of it is created in another memory
    location, and then the operations are performed. Thus, the changes won't
    reflect back in the original list.