Fill out python doc

This commit is contained in:
ldinh 2013-06-27 00:29:07 -07:00
parent 160ca481e8
commit 3afa1ee104

View File

@ -4,302 +4,280 @@ author: Louie Dinh
author_url: http://ldinh.ca
---
Python was created by Guido Van Rossum in the early 90's. It is not one of the most popular languages in existence.
```clojure
; Comments start with semicolons.
; Clojure is written in "forms", which are just
; lists of things inside parentheses, separated by whitespace.
;
; The clojure reader assumes that the first thing is a
; function or macro to call, and the rest are arguments.
;
; Here's a function that sets the current namespace:
(ns test)
Python was created by Guido Van Rossum in the early 90's. It is now one of the most popular languages in existence.I fell in love with Python for it's syntactic clarity. It's basically executable pseudocode.
; More basic examples:
; str will create a string out of all its arguments
(str "Hello" " " "World") ; => "Hello World"
```Python
# Single line comments start with a hash.
""" Multiline comments can we written
using three "'s
"""
; Math is straightforward
(+ 1 1) ; => 2
(- 2 1) ; => 1
(* 1 2) ; => 2
(/ 2 1) ; => 2
----------------------------------------------------
-- 1. Primitive Datatypes and Operators
----------------------------------------------------
; Equality is =
(= 1 1) ; => true
(= 2 1) ; => false
# You have numbers
3 #=> 3
; You need not for logic, too
(not true) ; => false
; Nesting forms works as you expect
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
# Math is what you would expect
1 + 1 #=> 2
8 - 1 #=> 9
10 * 2 #=> 20
35 / 5 #=> 7
; Types
;;;;;;;;;;;;;
; Clojure uses Java's object types for booleans, strings and numbers.
; Use `class` to inspect them.
(class 1) ; Integer literals are java.lang.Long by default
(class 1.); Float literals are java.lang.Double
(class ""); Strings always double-quoted, and are java.lang.String
(class false) ; Booleans are java.lang.Boolean
(class nil); The "null" value is called nil
; If you want to create a literal list of data, use ' to make a "symbol"
'(+ 1 2) ; => (+ 1 2)
; You can eval symbols.
(eval '(+ 1 2)) ; => 3
; Collections & Sequences
;;;;;;;;;;;;;;;;;;;
# Division is a bit tricky. It is integer division and floors the results automatically.
11 / 4 #=> 2
; Vectors and Lists are java classes too!
(class [1 2 3]); => clojure.lang.PersistentVector
(class '(1 2 3)); => clojure.lang.PersistentList
# Enforce precedence with parentheses
(1 + 3) * 2 #=> 8
; A list would be written as just (1 2 3), but we have to quote
; it to stop the reader thinking it's a function.
; Also, (list 1 2 3) is the same as '(1 2 3)
# Boolean values are primitives
True
False
; Both lists and vectors are collections:
(coll? '(1 2 3)) ; => true
(coll? [1 2 3]) ; => true
# negate with not
not True #=> False
not False #=> True
; Only lists are seqs.
(seq? '(1 2 3)) ; => true
(seq? [1 2 3]) ; => false
; Seqs are an interface for logical lists, which can be lazy.
; "Lazy" means that a seq can define an infinite series, like so:
(range 4) ; => (0 1 2 3)
(range) ; => (0 1 2 3 4 ...) (an infinite series)
(take 4 (range)) ; (0 1 2 3)
# Equality is ==
1 == 1 #=> True
2 == 1 #=> False
; Use cons to add an item to the beginning of a list or vector
(cons 4 [1 2 3]) ; => (4 1 2 3)
(cons 4 '(1 2 3)) ; => (4 1 2 3)
# Strings are created with " or '
"This is a string."
'This is also a string.'
; Use conj to add an item to the beginning of a list,
; or the end of a vector
(conj [1 2 3] 4) ; => [1 2 3 4]
(conj '(1 2 3) 4) ; => (4 1 2 3)
# Strings can be added too!
"Hello " + "world!" #=> "Hello world!"
; Use concat to add lists or vectors together
(concat [1 2] '(3 4)) ; => (1 2 3 4)
# A string can be treated like a list of characters
"This is a string"[0] #=> 'H'
; Use filter, map to interact with collections
(map inc [1 2 3]) ; => (2 3 4)
(filter even? [1 2 3]) ; => (2)
# None is an object
None #=> None
; Use reduce to reduce them
(reduce + [1 2 3 4])
; = (+ (+ (+ 1 2) 3) 4)
; => 10
; Reduce can take an initial-value argument too
(reduce conj [] '(3 2 1))
; = (conj (conj (conj [] 3) 2) 1)
; => [3 2 1]
----------------------------------------------------
-- 2. Variables and Collections
----------------------------------------------------
; Functions
;;;;;;;;;;;;;;;;;;;;;
# Printing is pretty easy
print "I'm Python. Nice to meet you!"
; Use fn to create new functions. A function always returns
; its last statement.
(fn [] "Hello World") ; => fn
; (You need extra parens to call it)
((fn [] "Hello World")) ; => "Hello World"
# No need to declare variables before assigning to them.
some_var = 5 # Convention is to use lower_case_with_underscores for variables
some_var #=> 5
; You can create a var using def
(def x 1)
x ; => 1
# Accessing a previously unassigned variable is an exception
some_other_var # Will raise a NameError
; Assign a function to a var
(def hello-world (fn [] "Hello World"))
(hello-world) ; => "Hello World"
; You can shorten this process by using defn
(defn hello-world [] "Hello World")
# Lists store sequences
li = []
# You can start with a prefilled list
other_li = [4, 5, 6]
; The [] is the list of arguments for the function.
(defn hello [name]
(str "Hello " name))
(hello "Steve") ; => "Hello Steve"
# Add stuff to the end of a list with append
li.append(1) #li is now [1]
li.append(2) #li is now [1, 2]
li.append(4) #li is now [1, 2, 4]
li.append(3) #li is now [1, 2, 4, 3]
; You can also use this shorthand to create functions:
(def hello2 #(str "Hello " %1))
(hello2 "Fanny") ; => "Hello Fanny"
# Access a list like you would any array
li[0] #=> 1
# Looking out of bounds is an IndexError
li[4] # Raises an IndexError
; You can have multi-variadic functions, too
(defn hello3
([] "Hello World")
([name] (str "Hello " name)))
(hello3 "Jake") ; => "Hello Jake"
(hello3) ; => "Hello World"
# Remove elements from a list with del
del li[2] # li is now [1, 2, 3]
; Functions can pack extra arguments up in a seq for you
(defn count-args [& args]
(str "You passed " (count args) " args: " args))
(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
# You can add lists
li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li and other_li is left alone
; You can mix regular and packed arguments
(defn hello-count [name & args]
(str "Hello " name ", you passed " (count args) " extra args"))
(hello-count "Finn" 1 2 3)
; => "Hello Finn, you passed 3 extra args"
# Concatenate lists with extend
li.extend(other_li) # Now li is [1 ,2 ,3 ,4 ,5 ,6]
# Check for existence in a list with in
1 in li #=> True
; Hashmaps
;;;;;;;;;;
# Examine the length with len
len(li) #=> 6
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
# Tuples are like lists but are immutable
tup = (1, 2, 3)
tup[0] #=> 1
tup[0] = 3 # Raises a TypeError
; Keywords are like strings with some efficiency bonuses
(class :a) ; => clojure.lang.Keyword
; Maps can use any type as a key, but usually keywords are best
(def stringmap (hash-map "a" 1, "b" 2, "c" 3))
stringmap ; => {"a" 1, "b" 2, "c" 3}
# Dictionaries store mappings
empty_dict = {}
# Here is a prefilled dictionary
filled_dict = {"one": 1, "two": 2, "three": 3}
(def keymap (hash-map :a 1 :b 2 :c 3))
keymap ; => {:a 1, :c 3, :b 2} (order is not guaranteed)
# Look up values with []
filled_dict["one"] #=> 1
; By the way, commas are always treated as whitespace and do nothing.
# Get all keys as a list
filled_dict.keys()
; Retrieve a value from a map by calling it as a function
(stringmap "a") ; => 1
(keymap :a) ; => 1
# Get all values as a list
filled_dict.values()
; Keywords can be used to retrieve their value from a map, too!
(:b keymap) ; => 2
# Check for existence of keys in a dictionary with in
"one" in filled_dict #=> True
1 in filled_dict #=> False
; Don't try this with strings.
;("a" stringmap)
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
; Retrieving a non-present value returns nil
(stringmap "d") ; => nil
# Sets store ... well sets
empty_set = set()
# Initialize a set with a bunch of values
filled_set = set([1,2,2,3,4]) # filled_set is now set([1, 2, 3, 4])
; Use assoc to add new keys to hash-maps
(assoc keymap :d 4) ; => {:a 1, :b 2, :c 3, :d 4}
# Add more items to a set
filled_set.add(5) # filled_set is now set([1, 2, 3, 4, 5])
; But remember, clojure types are immutable!
keymap ; => {:a 1, :b 2, :c 3}
# Do set intersection with &
other_set = set([3, 4, 5 ,6])
filled_set & other_set #=> set([3, 4, 5])
; Use dissoc to remove keys
(dissoc keymap :a :b) ; => {:c 3}
# Do set union with |
filled_set | other_set #=> set([1, 2, 3, 4, 5, 6])
; Sets
;;;;;;
# Check for existence in a set with in
2 in filled_set #=> True
10 in filled_set #=> False
(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
; Add a member with conj
(conj #{1 2 3} 4) ; => #{1 2 3 4}
----------------------------------------------------
-- 3. Control Flow
----------------------------------------------------
; Remove one with disj
(disj #{1 2 3} 1) ; => #{2 3}
# Let's just make a variable
some_var = 5
; Test for existence by using the set as a function:
(#{1 2 3} 1) ; => 1
(#{1 2 3} 4) ; => nil
# Here is an if statement. INDENTATION IS SIGNIFICANT IN PYTHON!
if some_var > 10:
print "some_var is totally bigger than 10."
elif some_var < 10: # This elif clause is optional.
print "some_var is smaller than 10."
else: # This is optional too.
print "some_var is indeed 10."
; There are more functions in the clojure.sets namespace.
# For loops iterate over lists
for animal in ["dog", "cat", "mouse"]:
print "%s is a mammal" % animal # You can use % to interpolate formatted strings
; Useful forms
;;;;;;;;;;;;;;;;;
# While loops go until a condition is no longer met.
x = 0
while x < 10:
print x
x += 1 # Short hand for x = x + 1
; Logic constructs in clojure are just macros, and look like
; everything else
(if false "a" "b") ; => "b"
(if false "a") ; => nil
# Handle exceptions with a try/except block
try:
raise IndexError("This is an index error") # Use raise to raise an error
except IndexError as e:
pass # Pass is just a no-op. Usually you would do recovery here.
; Use let to create temporary bindings
(let [a 1 b 2]
(> a b)) ; => false
; Group statements together with do
(do
(print "Hello")
"World") ; => "World" (prints "Hello")
----------------------------------------------------
-- 4. Functions
----------------------------------------------------
; Functions have an implicit do
(defn print-and-say-hello [name]
(print "Saying hello to " name)
(str "Hello " name))
(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
# Use def to create new functions
def add(x, y):
print "x is %s and y is %s" % (x, y)
return x + y # Return values with a return statement
; So does let
(let [name "Urkel"]
(print "Saying hello to " name)
(str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
# Calling functions with parameters
add(5, 6) #=> 11 and prints out "x is 5 and y is 6"
# Another way to call functions is with keyword arguments
add(y=6, x=5) # Equivalent to above. Keyword arguments can arrive in any order.
; Modules
;;;;;;;;;;;;;;;
# You can define functions that take a variable number of positional arguments
def varargs(*args):
return args
; Use "use" to get all functions from the module
(use 'clojure.set)
varargs(1, 2, 3) #=> (1,2,3)
; Now we can use set operations
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
(difference #{1 2 3} #{2 3 4}) ; => #{1}
; You can choose a subset of functions to import, too
(use '[clojure.set :only [intersection]])
# You can define functions that take a variable number of keyword arguments
def keyword_args(**kwargs):
return kwargs
; Use require to import a module
(require 'clojure.string)
# Let's call it to see what happens
keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
; Use / to call functions from a module
(clojure.string/blank? "") ; => true
; You can give a module a shorter name on import
(require '[clojure.string :as str])
(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
; (#"" denotes a regular expression literal)
# Python has first class functions
def create_adder(x):
def adder(y):
return x + y
return adder
; You can use require (and use, but don't) from a namespace using :require.
; You don't need to quote your modules if you do it this way.
(ns test
(:require
[clojure.string :as str]
[clojure.set :as set]))
# Let's create a new function that always adds 10 to the argument
add_10 = create_adder(10):
add_10(3) #=> 13
; Java
;;;;;;;;;;;;;;;;;
# There are also anonymous functions
(lambda x: x > 2)(3) #=> True
; Java has a huge and useful standard library, so
; you'll want to learn how to get at it.
# There are built-in higher order functions
map(add_10, [1,2,3]) #=> [11, 12, 13]
filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
; Use import to load a java module
(import java.util.Date)
# We can use list comprehensions for nice maps and filters
[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
; You can import from an ns too.
(ns test
(:import java.util.Date
java.util.Calendar))
----------------------------------------------------
-- 5. Classes
----------------------------------------------------
; Use the class name with a "." at the end to make a new instance
(Date.) ; <a date object>
# We can define classes with the class statement
class Human(): # By convention CamelCase is used for classes.
pass
; Use . to call methods. Or, use the ".method" shortcut
(. (Date.) getTime) ; <a timestamp>
(.getTime (Date.)) ; exactly the same thing.
# We subclass from object to get a "new-style class". All your code should do this.
class Human(object):
; Use / to call static methods
(System/currentTimeMillis) ; <a timestamp> (system is always present)
# A class attribute. It is shared by all instances of this class
species = "H. sapiens"
; Use doto to make dealing with (mutable) classes more tolerable
(import java.util.Calendar)
(doto (Calendar/getInstance)
(.set 2000 1 1 0 0 0)
.getTime) ; => A Date. set to 2000-01-01 00:00:00
```
# Basic initializer
def __init__(self, name):
self.name = name # We are assigning the argument to the instance's name attribute
# A method. All methods take self as the first argument, including the initializer
def say(self, msg):
return "%s: %s" % (this.name, msg)
# A class method is shared among all instances
@classmethod
def get_species(cls):
return cls.species
# Static methods are called without a parameter reference to the class or instance
@staticmethod
def grunt(self):
return "*grunt*"
# Instantiate a class
h = Human(name="Harry")
print h.say("hi") # prints out "Harry: hi"
i = Human("Ian")
print i.say("hello") #prints out "Ian: hello"
# Call our class method
h.get_species() #=> "H. sapiens"
# Change the shared attribute
h.species = "H. neanderthalensis"
h.get_species() #=> "H. neanderthalensis"
i.get_species() #=> "H. neanderthalensis"
# Call the static method
Human.grunt() #=> "*grunt*"