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 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. 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.
```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)
; More basic examples: ```Python
# Single line comments start with a hash.
; str will create a string out of all its arguments """ Multiline comments can we written
(str "Hello" " " "World") ; => "Hello World" using three "'s
"""
; Math is straightforward ----------------------------------------------------
(+ 1 1) ; => 2 -- 1. Primitive Datatypes and Operators
(- 2 1) ; => 1 ----------------------------------------------------
(* 1 2) ; => 2
(/ 2 1) ; => 2
; Equality is = # You have numbers
(= 1 1) ; => true 3 #=> 3
(= 2 1) ; => false
; You need not for logic, too # Math is what you would expect
(not true) ; => false 1 + 1 #=> 2
8 - 1 #=> 9
; Nesting forms works as you expect 10 * 2 #=> 20
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2 35 / 5 #=> 7
; Types # Division is a bit tricky. It is integer division and floors the results automatically.
;;;;;;;;;;;;; 11 / 4 #=> 2
; 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
;;;;;;;;;;;;;;;;;;;
; Vectors and Lists are java classes too! # Enforce precedence with parentheses
(class [1 2 3]); => clojure.lang.PersistentVector (1 + 3) * 2 #=> 8
(class '(1 2 3)); => clojure.lang.PersistentList
; A list would be written as just (1 2 3), but we have to quote # Boolean values are primitives
; it to stop the reader thinking it's a function. True
; Also, (list 1 2 3) is the same as '(1 2 3) False
; Both lists and vectors are collections: # negate with not
(coll? '(1 2 3)) ; => true not True #=> False
(coll? [1 2 3]) ; => true 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. # Equality is ==
; "Lazy" means that a seq can define an infinite series, like so: 1 == 1 #=> True
(range 4) ; => (0 1 2 3) 2 == 1 #=> False
(range) ; => (0 1 2 3 4 ...) (an infinite series)
(take 4 (range)) ; (0 1 2 3)
; Use cons to add an item to the beginning of a list or vector # Strings are created with " or '
(cons 4 [1 2 3]) ; => (4 1 2 3) "This is a string."
(cons 4 '(1 2 3)) ; => (4 1 2 3) 'This is also a string.'
; Use conj to add an item to the beginning of a list, # Strings can be added too!
; or the end of a vector "Hello " + "world!" #=> "Hello world!"
(conj [1 2 3] 4) ; => [1 2 3 4]
(conj '(1 2 3) 4) ; => (4 1 2 3)
; Use concat to add lists or vectors together # A string can be treated like a list of characters
(concat [1 2] '(3 4)) ; => (1 2 3 4) "This is a string"[0] #=> 'H'
; Use filter, map to interact with collections # None is an object
(map inc [1 2 3]) ; => (2 3 4) None #=> None
(filter even? [1 2 3]) ; => (2)
; 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)) -- 2. Variables and Collections
; = (conj (conj (conj [] 3) 2) 1) ----------------------------------------------------
; => [3 2 1]
; 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) # No need to declare variables before assigning to them.
((fn [] "Hello World")) ; => "Hello World" some_var = 5 # Convention is to use lower_case_with_underscores for variables
some_var #=> 5
; You can create a var using def # Accessing a previously unassigned variable is an exception
(def x 1) some_other_var # Will raise a NameError
x ; => 1
; Assign a function to a var
(def hello-world (fn [] "Hello World"))
(hello-world) ; => "Hello World"
; You can shorten this process by using defn # Lists store sequences
(defn hello-world [] "Hello World") li = []
# You can start with a prefilled list
other_li = [4, 5, 6]
; The [] is the list of arguments for the function. # Add stuff to the end of a list with append
(defn hello [name] li.append(1) #li is now [1]
(str "Hello " name)) li.append(2) #li is now [1, 2]
(hello "Steve") ; => "Hello Steve" 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: # Access a list like you would any array
(def hello2 #(str "Hello " %1)) li[0] #=> 1
(hello2 "Fanny") ; => "Hello Fanny" # Looking out of bounds is an IndexError
li[4] # Raises an IndexError
; You can have multi-variadic functions, too # Remove elements from a list with del
(defn hello3 del li[2] # li is now [1, 2, 3]
([] "Hello World")
([name] (str "Hello " name)))
(hello3 "Jake") ; => "Hello Jake"
(hello3) ; => "Hello World"
; Functions can pack extra arguments up in a seq for you # You can add lists
(defn count-args [& args] li + other_li #=> [1, 2, 3, 4, 5, 6] - Note: li and other_li is left alone
(str "You passed " (count args) " args: " args))
(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
; You can mix regular and packed arguments # Concatenate lists with extend
(defn hello-count [name & args] li.extend(other_li) # Now li is [1 ,2 ,3 ,4 ,5 ,6]
(str "Hello " name ", you passed " (count args) " extra args"))
(hello-count "Finn" 1 2 3)
; => "Hello Finn, you passed 3 extra args"
# 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 # Dictionaries store mappings
(def stringmap (hash-map "a" 1, "b" 2, "c" 3)) empty_dict = {}
stringmap ; => {"a" 1, "b" 2, "c" 3} # Here is a prefilled dictionary
filled_dict = {"one": 1, "two": 2, "three": 3}
(def keymap (hash-map :a 1 :b 2 :c 3)) # Look up values with []
keymap ; => {:a 1, :c 3, :b 2} (order is not guaranteed) 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 # Get all values as a list
(stringmap "a") ; => 1 filled_dict.values()
(keymap :a) ; => 1
; Keywords can be used to retrieve their value from a map, too! # Check for existence of keys in a dictionary with in
(:b keymap) ; => 2 "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 # Sets store ... well sets
(stringmap "d") ; => nil 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 # Add more items to a set
(assoc keymap :d 4) ; => {:a 1, :b 2, :c 3, :d 4} filled_set.add(5) # filled_set is now set([1, 2, 3, 4, 5])
; But remember, clojure types are immutable! # Do set intersection with &
keymap ; => {:a 1, :b 2, :c 3} other_set = set([3, 4, 5 ,6])
filled_set & other_set #=> set([3, 4, 5])
; Use dissoc to remove keys # Do set union with |
(dissoc keymap :a :b) ; => {:c 3} 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 # Let's just make a variable
(disj #{1 2 3} 1) ; => #{2 3} some_var = 5
; Test for existence by using the set as a function: # Here is an if statement. INDENTATION IS SIGNIFICANT IN PYTHON!
(#{1 2 3} 1) ; => 1 if some_var > 10:
(#{1 2 3} 4) ; => nil 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 # Handle exceptions with a try/except block
; everything else try:
(if false "a" "b") ; => "b" raise IndexError("This is an index error") # Use raise to raise an error
(if false "a") ; => nil 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 -- 4. Functions
(print "Hello") ----------------------------------------------------
"World") ; => "World" (prints "Hello")
; Functions have an implicit do # Use def to create new functions
(defn print-and-say-hello [name] def add(x, y):
(print "Saying hello to " name) print "x is %s and y is %s" % (x, y)
(str "Hello " name)) return x + y # Return values with a return statement
(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
; So does let # Calling functions with parameters
(let [name "Urkel"] add(5, 6) #=> 11 and prints out "x is 5 and y is 6"
(print "Saying hello to " name) # Another way to call functions is with keyword arguments
(str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") 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 varargs(1, 2, 3) #=> (1,2,3)
(use 'clojure.set)
; 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 # You can define functions that take a variable number of keyword arguments
(use '[clojure.set :only [intersection]]) def keyword_args(**kwargs):
return kwargs
; Use require to import a module # Let's call it to see what happens
(require 'clojure.string) 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 # Python has first class functions
(require '[clojure.string :as str]) def create_adder(x):
(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst." def adder(y):
; (#"" denotes a regular expression literal) return x + y
return adder
; You can use require (and use, but don't) from a namespace using :require. # Let's create a new function that always adds 10 to the argument
; You don't need to quote your modules if you do it this way. add_10 = create_adder(10):
(ns test add_10(3) #=> 13
(:require
[clojure.string :as str]
[clojure.set :as set]))
; Java # There are also anonymous functions
;;;;;;;;;;;;;;;;; (lambda x: x > 2)(3) #=> True
; Java has a huge and useful standard library, so # There are built-in higher order functions
; you'll want to learn how to get at it. 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 # We can use list comprehensions for nice maps and filters
(import java.util.Date) [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 -- 5. Classes
(:import java.util.Date ----------------------------------------------------
java.util.Calendar))
; Use the class name with a "." at the end to make a new instance # We can define classes with the class statement
(Date.) ; <a date object> class Human(): # By convention CamelCase is used for classes.
pass
; Use . to call methods. Or, use the ".method" shortcut # We subclass from object to get a "new-style class". All your code should do this.
(. (Date.) getTime) ; <a timestamp> class Human(object):
(.getTime (Date.)) ; exactly the same thing.
; Use / to call static methods # A class attribute. It is shared by all instances of this class
(System/currentTimeMillis) ; <a timestamp> (system is always present) species = "H. sapiens"
; Use doto to make dealing with (mutable) classes more tolerable # Basic initializer
(import java.util.Calendar) def __init__(self, name):
(doto (Calendar/getInstance) self.name = name # We are assigning the argument to the instance's name attribute
(.set 2000 1 1 0 0 0)
.getTime) ; => A Date. set to 2000-01-01 00:00:00 # 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*"