[Tutor] remarkable features of Python

dman dsh8290@rit.edu
Thu, 8 Nov 2001 20:56:20 -0500


On Thu, Nov 08, 2001 at 03:16:44PM -0500, Pijus Virketis wrote:
| Hi all, 
| 
| Today Slashdot posted a long and interesting interview
| (http://slashdot.org/article.pl?sid=01/11/03/1726251&mode=nested) with Kent
| M. Pitman, expert on Lisp/Scheme. One of the questions compared Lisp to
| Python (pretty favourably, in fact :)): "Some of the Lisp-ish features in
| Python that spring right to mind are functions as objects, closures,
| garbage collection, and dynamic-yet-strong typing." Can someone who has a
| deeper understanding of Python briefly explain how it implements these
| things (give a little example?) for those of us, who have not taken a lot
| of hard-core CS.


Functions (and classes and modules) are objects.  They behave the same
as any other python object.

# here is a function being defined
def foo() : pass

print foo
a = foo
print a
print a is foo
print a == foo

def demo( obj ) :
    print obj
    print obj is a
    print obj is foo

demo( foo )
demo( a )


These statements attempt to show that the function object can be
bound to another name (assignment), passed as an argument to another
function, and compared with other objects.  In C/C++ a function is
basically a chunk of memory that contains executable code that can be
jumped too.  They allow taking the address of that memory and passing
it around as a pointer, but it is not as simple as in python.  Java
doesn't allow directly referencing a method (kinda, through reflection
but it is ugly), but instead has the inner-class hack to work around
it.



Garbage collection :

Have you ever used C or C++?  In C and C++ you (the programmer) needs
to explicitly request memory from the system in order to use it.  When
you are done you need to give it back to the system so that someone
else can use it.  (malloc/free and new/delete respectively)  If you
don't you have what is called a "memory leak".  Python (and Lisp and
Java) do this memory allocating and freeing for you.  When you create
an object you allocate memory.  When you no longer refer to it, the
system realizes it and returns the memory to the system.


Dynamic-yet-Strong typing :

You don't declare the type of a python object.  In Java you would
write, ex,

class Foo
{
    public int a_func( String s , float f )
    {
        int result = 0 ;
        System.out.println( s ) ;
        return result ;
    }
}


Notice how I needed to specify the type (int) returned by the method,
the arguments (String, float) taken by the method and the local
variable (int).  In python that would be written as

class Foo :
    def a_func( s , f ) :
        result = 0
        print s
        return result

There are no static (written by you, read by the compiler) type
declarations.

Now suppose I try to do something that would not be type-safe :

obj = "abcd" # a string, obviously
print obj.readline() # maybe want it to be a file

In python this fails because the string object has no readline()
method.  In Java this would be a compile-time error due to the static
typing.  In C/C++ you would have to "cast" (fake conversion) the
object first, but when it ran it would do really weird things and
hopefully crash.  C/C++ are not typesafe because they let you do
operations on objects that are not valid.

Perl and Sh also have dynamic typing but their typing is weak.  In
python, try this :

print "123" + 4
print 4 + "123"

Try it in perl

print "123" + 4 ;
print 4 + "123" ;
print "123" . 4 ;
print 4 . "123" ;

In python you will get a TypeError -- adding strings and numbers
doesn't make sense.  In perl, the interpreter magically converts
between the number and the string and gives you either the
concatenation ("1234") or the sum (127).  I don't remember which is
does, but I think it is related to the exact "addition" operator used.



I don't know too much about closures, other than they are the state of
a function at a given time.  Having closures allows concurrent things
like coroutines.  (See, for example, Stackless Python)


HTH,
-D