Mercurial > python-for-js-programmers
view PythonForJsProgrammers.txt @ 5:758a15a83be8
More stuff.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Thu, 05 Jun 2008 15:24:58 -0700 |
parents | ae28bd3be137 |
children | f8aa8d0494ed |
line wrap: on
line source
================================= Python for JavaScript Programmers ================================= I couldn't find anything on the web that attempted to teach Python to readers who already knew JavaScript, so I thought I'd give it a shot, since a number of my friends at Mozilla don't know much about Python but know JavaScript incredibly well. The languages actually aren't that dissimilar--in fact, some of JavaScript's latest features have been `borrowed directly from Python`_. .. _`borrowed directly from Python`: http://weblogs.mozillazine.org/roadmap/archives/2006/02/js_and_python_news.html Whitespace ========== This is coincidentally a good place to explain Python's design philosophy; hopefully it will give you a better idea of whether this is a language you'd like to use. While not syntactically enforced by many languages, whitespace is semantically meaningful during the reading and writing of code. Take the following example of C-like code:: if (someVar == 1) doSomething(); The line ``doSomething();`` is indented after the ``if`` statement to indicate that it should only be done if the statement it's below is true. Given this, consider what the following code does:: if (someVar == 1) doSomething(); doSomethingElse(); It's clear from the use of whitespace that ``doSomethingElse();`` should also only be executed if the statement it's indented under is true, but this is not the case for C-like languages. Indeed, the programmer must add additional code to tell the compiler what he or she means:: if (someVar == 1) { doSomething(); doSomethingElse(); } Why does the programmer have to write more code to tell the computer something it should already be able to understand from the use of whitespace? This is actually a violation of the `Don't Repeat Yourself`_ (DRY) principle popularized by Andy Hunt and Dave Thomas. Because unneeded extra work is required when moving from a single-line clause to a multiple-line clause, it's a constant source of errors in C-like languages, and many stylistic rules and arguments have been spawned as a result of this mistake in language design. Python is one of the few languages that takes the simpler and more humane approach: whitespace has a consistent semantic meaning to the humans who write code, so the computer should take this into account when it processes the code. This reduces the burden on the programmer from having to repeat their intent in multiple different ways. So, you won't see any brackets in Python. Instead, if a statement ends with a colon, the next statement needs to be indented and begins a new block. The block ends as soon as a line is encountered that's unindented at least one level, like so:: if someVar == 1: doSomething() doSomethingElse() else: doOtherThing() Also note that Python doesn't use semicolons, which is yet another language feature that reduces the cognitive burden on the programmer. Indeed, many of the language features covered below were designed with a very careful eye towards readability, reducing cognitive load, and making the process of programming as enjoyable as possible. .. _`Don't Repeat Yourself`: http://en.wikipedia.org/wiki/Don%27t_repeat_yourself The Interactive Shell ===================== Python, when executed with no parameters, just presents an interactive interpreter. It's similar to the SpiderMonkey shell and xpcshell if you're familiar with those. The code examples in this tutorial will be displayed as though they're being executed in it, like so: >>> 1 + 2 3 >>> # Here's a comment that does nothing. >>> print "hi!" hi! >>> print "This is a long " \ ... "statement that spans multiple lines." This is a long statement that spans multiple lines. The shell is also a useful way to explore Python's functionality; feel free to just use it as a desk calculator to get used to it. Expressions =========== Python's expression syntax is much like that of JavaScript, or any C-like language for that matter: >>> 9 & 1 # Bitwise operations 1 >>> 2 << 2 # Shifting 8 >>> 5 >= 3 # Comparisons True >>> 8 + 2 * (3 + 5) # Arithmetic 24 >>> 1 == 1 # Equivalence True Some C-like expression constructs have been substituted for more readable alternatives: >>> not True # 'not' instead of '!' False >>> True and True # 'and' instead of '&&' True >>> True or False # 'or' instead of '||' True But there's some elements of C-like expressions that aren't supported, because they tend to be more trouble than they're worth. The ``++`` and ``--`` unary assignment operators aren't part of the language, and nor is JavaScript's ``===`` comparison operator. Some constructs that can be used in expressions in C-like languages can only be used in statements in Python: >>> a = 5 # Assignment works in statements. >>> a += 1 # Add-assignment does too. 6 >>> if a = 1: # But you can't assign in an expression. ... pass Traceback (most recent call last): ... SyntaxError: invalid syntax Nothingness =========== Unlike JavaScript, Python doesn't have a concept of ``undefined``. Instead, things that would normally cause ``undefined`` to be returned by JavaScript simply end up raising an exception in Python: >>> "a string".foo Traceback (most recent call last): ... AttributeError: 'str' object has no attribute 'foo' Python does have an analog to JavaScript's ``null``: it's called ``None``. Functions ========= Functions are defined like so: >>> def foo(x): ... print "foo called with parameter: %s" % x They are called as you'd expect: >>> foo(5) foo called with parameter: 5 Unlike JavaScript, though, it's not possible to call them with fewer or more arguments than they'd expect: >>> foo() Traceback (most recent call last): ... TypeError: foo() takes exactly 1 argument (0 given) Though it is possible to provide defaults for arguments: >>> def bar(x, y=1, z=5): ... return x + y + z And it's also possible to specify arguments using keywords: >>> bar(1, z=6) 8 As in JavaScript, they're first-class citizens and can be passed around as parameters to other functions and so forth. Closures ======== Function closures are available in Python: >>> def myfunc(): ... a = 1 ... def wrapped(): ... return a ... return wrapped >>> myfunc()() 1 Unlike Javascript, however, the variable bindings in the closure are "read-only": >>> def myfunc(): ... a = 1 ... def wrapped(): ... a += 1 # Doesn't work! ... return a ... return wrapped >>> myfunc()() Traceback (most recent call last): ... UnboundLocalError: local variable 'a' referenced before assignment This means that closures can't be used to access private variables like they can in JavaScript; instead, everything is visible, and implementation-specific variables are conventionally preceded with one or two underscores. Lists ===== Lists are a lot like JavaScript arrays. Iterating through them is easy: >>> mylist = ["hello", "there"] >>> for i in mylist: ... print i hello there Tuples are just like lists, only they're immutable and differentiated from lists by using parentheses instead of brackets: >>> mytuple = ("hello", "there") >>> mytuple[0] = "bye" Traceback (most recent call last): ... TypeError: 'tuple' object does not support item assignment Tuples with a single item look a little weird, though: >>> mytuple = ("hello",) # Without the comma, it'd just be a string. It's also not possible for there to be "holes" in Python arrays like there are in Javascript ones: >>> a = [1, 2, 3] >>> del a[1] # Deletes '2' >>> a [1, 3] Indexing and Slicing ==================== Any item that is a sequence can be indexed as expected, but unlike Javascript, negative indexes may be used to denote items from the end of the sequence: >>> ["hello", "there", "dude"][-1] 'dude' Any indexable item can generally also be sliced; this is similar to ``String.slice`` in JavaScript, only built-in to the language: >>> "hello"[2:4] # Just like "hello".slice(2,4) in JS 'll' >>> "hello"[2:] # Just like "hello".slice(2) in JS 'llo' >>> "hello"[:4] # Just like "hello".slice(0,4) in JS 'hell' >>> [1, 2, 3][1:2] # Works on lists, too! [2] If the datatype is mutable, you can even assign to slices: >>> a = [1, 2, 3, 4] >>> a[1:3] = [5] >>> a [1, 5, 4] Dictionaries ============ Dictionaries are a lot like Object literals in JavaScript: >>> d = {"foo" : 1, "bar" : 2} >>> d["foo"] 1 Their properties can't be referenced using dot notation, though: >>> d.foo Traceback (most recent call last): ... AttributeError: 'dict' object has no attribute 'foo' Dictionaries generally aren't used to create arbitrary objects like they are in Javascript, though; they don't have prototypes, nor do they have meta-methods. Instead, classes are used to do that sort of thing. Classes ======= Classes are pretty straightforward: >>> class Foo(object): ... def __init__(self, a): ... self.a = a ... print "Foo created." ... def doThing(self): ... return self.a + 1 Here ``Foo`` is a subclass of ``object``, which is the root object class that any class should ultimately descend from. The constructor is always called ``__init__()`` and is invoked like so: >>> f = Foo(1) Foo created. So you don't need to use a ``new`` operator or anything as is the case with JS. Calling methods and accessing attributes is straightforward too: >>> f.a 1 >>> f.doThing() 2 Classes in Python get inheritance for free, but because they're not really prototype-based, it's not easy to dynamically add or remove methods to existing objects on-the-fly. An object's methods are also bound to the object itself, so--unlike in Javascript--if they're "disconnected" from the object, they still work: >>> f = Foo(5) Foo created. >>> doThing = f.doThing >>> doThing() 6 Coding Style ============ Python has a coding convention that's generally been embraced throughout the community; almost all libraries use it. It's contained in `PEP 8`_. .. _`PEP 8`: http://www.python.org/dev/peps/pep-0008