Welcome to Junxian’s Documentation!

[Overview]

Documents for study, collections, todos

See also other basics:

[Contents]

Python Phthonic

Overview

Pythonic means code that doesn’t just get the syntax right but that follows the conventions of the python community and uses the lanuage in the way it’s intended to be used.

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren’t special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one– and preferably only one –obvious way to do it. Although that way may not be obvious at first unless you’re Dutch. Now is better than never. Although never is often better than right now. If the implementation is hard to explain, it’s a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea – let’s do more of those!

PEP8 first

Python Built-in Functions

https://docs.python.org/2.7/library/functions.html

>>>print dir(__builtins__)  # Or: print dir(sys.modules['__builtin__'])
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']

math

abs(x)
divmod(a, b)
max()
min()
pow(x, y)
range([start,] stop [,step])   # return list
xrange([start,] stop [,step])  # iterable
round(x, [,n])
sum([item])

logical

all(s)                  # True if all is True
any(s)                  # True if any is True
cmp(x, y)
isinstance(obj, class)  # Trure if obj is a isinstance of class
sorted()
reversed(sequence)

conversion

repr(o)
ascii(x) #python 3
str()
bin()
float()
hex()
int()    # equal to math.floor()
long()
ord(c)
chr(i)
set([item])

I/O

input()
raw_input()
print()

iteration

enumerate(iterable)

>>> for i, c in enumerate("Like"):
...     print "S[%d]=%c" %(i, c)
...
S[0]=L
S[1]=i
S[2]=k
S[3]=e

s = 'I like Python'
>>> reversed(s)
<reversed object at 0x7f2383001850>
>>> list(reversed(s))
['n', 'o', 'h', 't', 'y', 'P', ' ', 'e', 'k', 'i', 'l', ' ', 'I']
>>> list(sorted(s))
[' ', ' ', 'I', 'P', 'e', 'h', 'i', 'k', 'l', 'n', 'o', 't', 'y']

others

map(function, sequence, ...)   # list that one to one return after map
filter(function, sequence)     # list that all ture values
reduce(function, sequence[, initial])   # final one result after function(lastreturn/initial, next)

zip(a, b)
>>> names = ["Alex", "John", "Mike"]
>>> ages = [15, 36, 42]
>>> zip(names, ages)
[('Alex', 15), ('John', 36), ('Mike', 42)]

unzip()
>>> zip(*c)   #c=[(1, 4), (2, 5), (3, 6)]
[(1, 2, 3), (4, 5, 6)]

Python Data Modules

Introduction

Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects.

Data Modules:
number, string, sequence, mapping(dictionary), set/frozenset
Build-in Sequences:
list, tuple, string, unicode, buffer, xrange

The start index for all Sequences is 0, and -1 is means the last one.

Immutable sequences: string, unicode, tuple Mutable sequences: list, byte array

(1, ) # If there is only one item in the tuple

The key of dictionary must can not be changed, for example: int, float, string, tuple, frozenset. But the value of dictionary can be any data type.

Note

  • The differences between reference and copy
  • See also pickle module

Other operation supported by sequences

https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range

Slicing:

>>> i=3
>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers[i]      # numbers[3] = 3
3
>>> numbers[-3]     # numbers[10-3] = numbers[7]
7
>>> numbers[3:6]    # from 3 to 6, but not include 6
[3, 4, 5]
>>> numbers[-3:-1]  # from -3 to -1, the same as numbers[7:9]
[7, 8]
>>> numbers[3:]     # from 3 to the end
[3, 4, 5, 6, 7, 8, 9]
>>> numbers[:3]     # from the beginning to 3, doesn't include 3
[0, 1, 2]
>>> numbers[-3:]    # the last 3 items
[7, 8, 9]
>>> numbers[:-3]    # from the beginning to the last third one
[0, 1, 2, 3, 4, 5, 6]
>>> numbers[::2]    # step is 2
[0, 2, 4, 6, 8]
>>> numbers[::-1]   # step is -1, which means reverse the sequence
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> numbers[-1:-10:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> numbers[9:0:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers[-2:] = [-2, -1]   # change value
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, -2, -1]

>>> numbers[2:2] = [20, 21]   # insert
>>> numbers
[0, 1, 20, 21, 2, 3, 4, 5, 6, 7, -2, -1]

>>> numbers[-2:] = [-3, -2, -1]   # change value and append
>>> numbers
[0, 1, 20, 21, 2, 3, 4, 5, 6, 7, -3, -2, -1]

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers[0:9:2] = [10, 12, 14, 16, 18]   # change value in specified step
>>> numbers
[10, 1, 12, 3, 14, 5, 16, 7, 18, 9]

Append:

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers + numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Times:

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers * 2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Change value:

>>> numbers[0] = 10
>>> numbers
[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Check item existence:

>>> 2 in numbers
True
>>> 'P' in "Python"
True

Build in functions:

>>> max("Python")
'y'
>>> max(numbers)
9
>>> min(numbers)
0
>>> len(numbers)
10

Delete:

>>> del numbers[0]
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Operations supported by string

String is a special kind of sequence, so most of the above sequence operations are valid to string, such as slicing, ‘+’, ‘*’, and build-in functions ‘len’, ‘cmp’, for example:

s[::-1]  # reverse the string

str="This is a string"" and some others together"

str1 = 'strcat'
str2 = 'append'
str1 += str2

# basestring is the base calse of all string and unicode type:
# The following way can check whether the it's a string.
isinstance(myobj, basesring)

Format a string

Usage: format_string % tuple/dictionary https://docs.python.org/2/library/stdtypes.html#string-formatting

Format string: %[[+/-]width][.precision]type

Examples:

%s,  %8d, %-16s, %10.2f, %010.2f,  %+5d

print "My name is %s, age is %d\n" % (name, age)

d = {'name': 'Alex', 'age': 42}
print "Name is %(name)s, age is %d" % d

Usage: Template() https://docs.python.org/2/library/string.html#template-strings

Examples:

>>> s = Template("My name is $name, age is $age")
>>> s.substitute(name="John", age=18)  #使用变量赋值
'My name is John, age is 18'
>>> d = {'name':'John', 'age':18}
>>> s.substitute(d)     #使用字典赋值
'My name is John, age is 18'

Usage: format() https://docs.python.org/2/library/string.html#custom-string-format_string

Examples::
>>> '{}, {}, {}'.format('arg0', 'arg1', 'arg2')
'arg0, arg1, arg2'
>>> '{0}, {1}, {2}'.format('arg0', 'arg1', 'arg2')
'arg0, arg1, arg2'
>>> '{2}, {1}, {1}'.format('arg0', 'arg1', 'arg2')
'arg2, arg1, arg1'
>>> '{0}, {arg1}, {arg2}'.format('arg0', arg1='arg1', arg2='arg2')
'arg0, arg1, arg2'
>>> '{arg0}, {0}, {arg2}'.format('arg1', arg0='arg0', arg2='arg2')  # named arguments must be at last.
'arg0, arg1, arg2'
>>> config['conf0':'arg0', 'conf1':'arg1']
>>> '{0[conf0]}, {0[conf1]}, {1}'.format(config, 'arg2')
'arg0, arg1, arg2'
>>> '|{0[conf0]:>10}|{0[conf1]:<10}|{1:^10}|'.format(config, 'arg2')  # alignment
'|      arg0|arg1      |   arg2   |'
>>> '{0:.{1}f}'.format(1/3.0, 4)
'0.3333'

Build-in functions for string

https://docs.python.org/2/library/string.html#string-functions

Note

As string is not changable, so all the return value is the new copy.

>>> dir(string)
>>> dir(s)

Build-in Functions:

S.find(substr, [start, [end]])
S.rfind(substr, [start, [end]])
S.index(substr, [start, [end]]) # similar to find, but maybe index exception.
S.rindex(substr, [start, [end]])
S.count(substr, [start, [end]])


S.replace(oldstr, newstr, [count])
S.strip([chars])
S.lstrip([chars])
S.rstrip([chars])
S.expandtabs([tabsize])

S.lower()
S.upper()
S.swapcase()
S.capitalize()
S.title()

S.partition(substr)
S.rpartition(substr)
S.split([sep, [maxsplit]])
S.rsplit([sep, [maxsplit]])
S.splitlines([keepends])
S.join(sequence)

S.isalnum()
S.isalpha()
S.isdigit()
S.islower()
S.isupper()
S.isspace()
S.istitle()
S.startswith(prefix [, start, end])
S.endswith(suffix [, start, end])

S.center(width[, fillchar])
S.ljust(width[, fillchar])
S.rjust(width[, fillchar])
S.zfill(width)

S.translate(table[,deletechars])

S.encode([encoding,[errors]])
S.decode([encoding,[errors]])

string.atoi(s[,base])
string.atol(s[,base])
string.atof(s[,base])

Examples:

>>> st = string.maketrans("0123456789", "abcdefghij")
>>> "001".translate(st)
'aab'

allchars = string.maketrans('', '')   # nothing is changed
keep = 'abcde'
alldel = allchars.translate(allchars, keep)   # all execpt characters in keep
s.translater(allchars , alldel)   # all in keep

>>> se = "007".encode('base64')
>>> se.decode('base64')
'007'

re library

https://docs.python.org/2/library/re.html

re.search(pattern, string, flags=0)
re.match(pattern, string, flags=0)
re.fullmatch(pattern, string, flags=0)
re.split(pattern, string, maxsplit=0, flags=0)
re.findall(pattern, string, flags=0)
re.finditer(pattern, string, flags=0)
re.sub(pattern, repl, string, count=0, flags=0)
re.escape(string)

textwrap module

https://docs.python.org/3/library/textwrap.html

textwrap.wrap(text, width=70, **kwargs)
textwrap.fill(text, width=70, **kwargs)
textwrap.shorten(text, width, **kwargs)
textwrap.dedent(text)
textwrap.indent
class textwrap.TextWrapper(**kwargs)

Sequences type cast

Integer to Binary string:

# Use built-in function bin()
bin(n)[2:]

Sting to list:

>>> list("Python")
['P', 'y', 't', 'h', 'o', 'n']

String to tuple:

>>> tuple("Python")
('P', 'y', 't', 'h', 'o', 'n')

List to string:

# Items for join function must be strings or characers
>>> ''.join(['P', 'y', 't', 'h', 'o', 'n'])
'Python'

List to set:

# unique the list after from list to set and back to list
list(set(l))

Dictionary to set:

>>> print set({'Hacker' : 'DOSHI', 'Rank' : 616 })
set(['Hacker', 'Rank'])

Map to set:

s = set(map(int, input().strip().split()))

List enumerate:

for idx, value in enumerate(['Spring', 'Summer', 'Fall', 'Winter'])

List build-in functions

append:

>>> numbers.append(10)
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

count:

>>> numbers[10]=9
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9]
>>> numbers.count(9)   # count the number of value '9'
2

extend:

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers.extend([10, 11, 12, 13])   # similar to a = a + b
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Note

a + b will not change a,but a.extend(b) will change a

index:

>>> numbers=[0,1,2,3,4,5,6,7,8,9]
>>> numbers.index(4)   # find the first one and return the index
4

insert:

>>> numbers.insert(4, 41)
>>> numbers
[0, 1, 2, 3, 41, 4, 5, 6, 7, 8, 9]

remove:

>>> numbers.remove(41)   # remove the first one which is found
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

pop:

#pop(n) remove and return the Nth item, default is '-1'
>>> numbers.pop()
9
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8]

reverse:

>>> numbers.reverse()
>>> numbers
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

sort:

>>> numbers.sort()    # no return value, just change the list.
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> name=["John", "Stephanie", "Hasan"]
>>> name.sort(cmp)    # use build-in function 'cmp' as compare function
>>> name
['Hasan', 'John', 'Stephanie']

>>> name.sort(key=len)   # compare the len
>>> name
['John', 'Hasan', 'Stephanie']

>>> name.sort(key=len, reverse=True)  # sort and also reverse the result
>>> name
['Stephanie', 'Hasan', 'John']

Operations supported by dictionary

https://docs.python.org/3/library/stdtypes.html#mapping-types-dict

Create:

d = {'name': 'Alex', 'age': 42}
d = dict(name='Alex', age=42)
items = [('name', 'Alex'), ('age', 42)]
d = dict(items)

Add/Set:

d['name'] = 'Alisa'
d['interest'] = 'reading'

Delete:

del d['interest']

Length:

len(d)

Member check:

‘name’  in d    #true

Dictionary to Sting:

>>> str(d)
"{'age': 42, 'name': 'Alex'}"

Format by key-value paring in dictionary:

>>> print "Name is %(name)s, age is %(age)s" % d
Name is Alex, age is 42

Dictionary build-in functions

>>> dir(d)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__',
'__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items',
'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault',
'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']

clear:

d.clear()  # clear all key-value, no return value

copy:

>>> d['interest'] = ["reading", "chese", "movie"]
>>> d
{'age': 42, 'name': 'Alex', 'interest': ['reading', 'chese', 'movie']}
>>> d1 = d.copy()    # just add the reference
>>> d1['name'] = 'John'
>>> d1['interest'].remove('movie')
>>> d
{'age': 42, 'name': 'Alex', 'interest': ['reading', 'chese']}
>>> d1
{'age': 42, 'name': 'John', 'interest': ['reading', 'chese']}

deepcopy:

>>> from copy import deepcopy
>>> d2 = deepcopy(d) # deepcopy from the copy module
>>> d2['interest'].append('movie')
>>> d
{'age': 42, 'name': 'Alex', 'interest': ['reading', 'chese']}
>>> d2
{'age': 42, 'name': 'Alex', 'interest': ['reading', 'chese', 'movie']}

fromkeys:

>>> d1 = d.fromkeys(['name', 'age'], 'Unknown')
>>> d1
{'age': 'Unknown', 'name': 'Unknown'}

#fromkeys is a dict class static method
>>> d1 = dict.fromkeys(['name', 'age'], 'Unknown')
>>> d1
{'age': 'Unknown', 'name': 'Unknown'}

get:

>>> print d.get('name')
Alex
>>> print d.get('country')   # return None instead of exception if doesn't exist.
None
>>> print d['country']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'country'

>>> print d.get('country', 'Unkown')  # provide a default value
Unkown

setdefault:

# It's to get value, but if key doesn't exist, return the default value.
# Will also add the key and the default value as new key-value paring.
>>> d.setdefault('interest', ['reading', 'chese'])
['reading', 'chese']

has_key:

>>> d.has_key('name')
True

items:

>>> d.items()   # return the list of all the key-value tuple
[('age', 42), ('name', 'Alex'), ('interest', ['reading', 'chese'])]

>>> for key, value in d.items():
...    print "[%s]:%s" %(key, value)
...
[age]:42
[name]:Alex
[interest]:['reading', 'chese']

iteritems:

>>> it = d.iteritems()   # return the iterable items
>>> it
<dictionary-itemiterator object at 0x7f2382fae2b8>
>>> list(it)
[('age', 42), ('name', 'Alex'), ('interest', ['reading', 'chese'])]

keys:

>>> d.keys()   # return the list of all the keys only
['age', 'name', 'interest']

iterkeys:

>>> d.iterkeys()  # return a iterable keys
<dictionary-keyiterator object at 0x7f2382fae310>

values:

>>> d.values()  # return the list of all the values only
[42, 'Alex', ['reading', 'chese']]

itervalues:

>>> d.itervalues() # return the iterable values
<dictionary-valueiterator object at 0x7f2382fae310>

pop:

# Remove the key-value specified by this key in the dictionary.
# And return the value of this key
>>> d.pop('interest')
['reading', 'chese']
>>> d
{'age': 42, 'name': 'Alex'}

# provide default return value if key doesn't exist
>>> d.pop('interest', 'No this key')
'No this key'

popitem:

# The same as pop, but using a random key instead of specified one
# Also return the value of this randome key-value paring.
>>>d.popitem()

update:

# Update if the same key exist, add new key-value paring if not.
>>> d1 = {'name': 'John', 'country': 'USA'}
>>> d.update(d1)
>>> d
{'country': 'USA', 'age': 42, 'name': 'John', 'interest': ['reading', 'chese']}

Operations supported by set

https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset

>>> x = set('python')
>>> y = {'p', 'o', 'i', 'n', 't'}

>>> x & y   # x.intersection(y),  in both x and y
set(['p', 't', 'o', 'n'])

>>> x | y   # x.union(y),  in x or y
set(['i', 'h', 'o', 'n', 'p', 't', 'y'])

>>> x - y   # or x.difference(y),  in x but ont in y
set(['y', 'h'])

>>> x ^ y   #x.symmetric_difference(y),  in x or y but not both
set(['i', 'h', 'y'])

>>> s = set()
>>> s.add('test')      # add 'test' into set
>>> s.update('test')   # add 't', 'e', 's', 't' into test

>>> s.update({1, 6}, [5, 3]) # add 1, 6, 5 ,3 into set

>>> s.discard(1)   # remove 1 from set if exits.
>>> s.remove(1)    # remove 1 from set and raise KeyError if doesn't exit.

Define and use of Enum

enum is standard after python 3.4, for older version, please try “pip install enum”.

from enum import Enum, IntEnum, unique
try:
    @unique
    class WEEKDAY(Enum):
        MON = 1
        TUS = 2
        WEN = 3
        THU = 4
        FRI = 1
except ValueError as e:
    print(e)

duplicate values found in <enum 'WEEKDAY'>: FRI -> MON

try:
    class Color(IntEnum):
        RED = 0
        GREEN = 1
        BLUE = 'b'
except ValueError as e:
    print(e)

invalid literal for int() with base 10: 'b'

red = class(0)
print(red is Color.R)       # True
print(red == 0)             # False

Container datatypes

collections module: https://docs.python.org/3/library/collections.html

This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict, list, set, and tuple.

For example:

  • namedtuple() factory function for creating tuple subclasses with named fields
  • deque list-like container with fast appends and pops on either end
  • ChainMap dict-like class for creating a single view of multiple mappings
  • Counter dict subclass for counting hashable objects
  • OrderedDict dict subclass that remembers the order entries were added
  • defaultdict dict subclass that calls a factory function to supply missing values
  • UserDict wrapper around dictionary objects for easier dict subclassing
  • UserList wrapper around list objects for easier list subclassing
  • UserString wrapper around string objects for easier string subclassing

Examples:

from collections import Counter, OrderedDict

class OrderedCounter(Counter, OrderedDict):
    pass

[print(*c) for c in OrderedCounter(sorted('bbbaaccde').most_common(3)]

# output: (top 3 occurrence count and sorted when with the same count)
b 3
a 2
c 2

Python Expressions and Operators

https://docs.python.org/3/reference/expressions.html

http://www.runoob.com/python/python-operators.html

Overview

Arithmetic conversions:

  • If either argument is a complex number, the other is converted to complex;
  • otherwise, if either argument is a floating point number, the other is converted to floating point;
  • otherwise, both must be integers and no conversion is necessary.

The power operator Unary arithmetic and bitwise operations Binary arithmetic operations Shifting operations Binary bitwise operations Comparisons Boolean operations Conditional expressions Lambdas Expression lists Evaluation order Operator precedence

Logical expressions

False:

False None 0 "" () [] {}

Examples:

name = input("Please enter your name: ")  or 'Unknown'
x = A or B or C or default

x = 1 if 5<6 else 0

List Comprehensions

Examples:

[line.rstrip().replace(' ', '#') for line in open('testfile')]

>>> [a**2 + b**2 for (a, b) in zip(range(1,5),range(1,5))]
[2, 8, 18, 32]

[x[0]**2 + x[1]**2 for x in zip(range(1,5),range(1,5))]  # zip两个序列
[2, 8, 18, 32]

[i**2 for i in range(0,5) if i > 2]    # 附带条件判断的

[a**2 + b**2 for a in range(1,5) for b in range(1,5)]  # 两个序列的全排列组合
[2, 5, 10, 17, 5, 8, 13, 20, 10, 13, 18, 25, 17, 20, 25, 32]

l = [(1,2,3), (4,5,6)]
[i for t in l for i in t]

Dictionary Comprehensions

# dict([(str(i), i**2) for i in range(0,5)]) >>> {str(i):i**2 for i in range(0,5)} {‘3’: 9, ‘4’: 16, ‘0’: 0, ‘2’: 4, ‘1’: 1}

Generator Expression

Examples:

total = sum(num * num for num in xrange(1, 101))

month_codes = dict((fn(i+1), code)
                    for i, code in enumerate('FGHJKMNQUVXZ')
                    for fn in (int, str))

Python Statements

https://docs.python.org/3/reference/simple_stmts.html

https://docs.python.org/3/reference/compound_stmts.html

Overview

Simple statements:

  • Expression statements
  • Assignment statements
  • The assert statement
  • The pass statement
  • The del statement
  • The return statement
  • The yield statement
  • The raise statement
  • The break statement
  • The continue statement
  • The import statement
  • The global statement
  • The nonlocal statement

Compound statements:

  • The if statement
  • The while statement
  • The for statement
  • The try statement
  • The with statement
  • Function definitions
  • Class definitions
  • Coroutines

Assignment statement

All assignment expression will not return value like C language. There is syntax error in this expression: 5 == (x = 5).

All assignment are reference copy, but not real deep copy. For example:

>>> L1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L2 = L1[::2]    # L2 = [0, 2, 4, 6, 8]
>>> L1[2] = 20      # L1[2] point to reference of int '20', L2 is still not changed.
>>> L2
[0, 2, 4, 6, 8]     # L2[1] is still point to int '2'

>>> L1[2] = [1, 2]
>>> L2 = L1[::2]    # Both L1[2] and L2[1] point to the refrence of list [1, 2]
>>> L1[2][0] = 10   # The first value of list [1, 2] is changed to 10
>>> L1
[0, 1, [10, 2], 3, 4, 5, 6, 7, 8, 9]
>>> L2
[0, [10, 2], 4, 6, 8]  # So both the value in L1 and L2 are changed, because of the same one reference.

Special assignment examples:

x, y, z = (1, 2, 3)
a,b,c,d = 'test'
a, b = ['111', '222']
a,b = c, d

[a, b] = [c, d]
for (a, b, c) in [(1,2,3), (4,5,6)]: pass

x = y = z = 1

while statement

Syntax:

while something:
    ...
else:
    ...

if statement

Examples:

if 0<age<10: pass

for statement

Examples:

for x in List/Tuple/String: ... else: pass
for k in Dict: pass

for  (a, b) in [(1, 2), (3, 4), (5, 6)]: pass

for line in open('test.txt'): pass    # read one line each time
for line in open('test.txt').readlines(): pass    # read all into list
for line in os.popen('ls -1 /'): pass

for i in range(0,10, 2):  print L[i]
for l in L[::2]:  print l       # will copy L[::2] as new list, use more memory than above case.

Note

All object with __next__() method is iteriable, next(o) is equal to o.__next()

with statement

Syntax:

with A() as a:
with A() as a , B() as b:  # Support this after python 3.1

# will close file automatically
with open(r'/home/test/test.txt') as myfile:
     for line in myfile:
        print(line)

Any class with __enter__(), __exit__() method can use with/as statement:

  • with will call__enter__(), and return to variable behind as.
  • __exit() will always be called at the end of the with/as statement.

Example:

class TraceBlock:
    def message(self, arg):
        print('running %s' %arg)
    def __enter__(self):
        print('starting trace block')
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        if exc_type is None:
            print('exit normal')
        else:
            print('exit with execption %s' % exc_type)
        return False

with TraceBlock() as action:
    action.message('test1')
    print('reached')

with TraceBlock() as action:
    action.message('test2')
    raise TypeError
    print('not reached')

Python Exception and Errors

Exception Overview

  • Some exceptions are not error, such as EOFError, KeyboardInterrupt.
  • Catch the exception as exact as possible.

try/except/else/finally Syntax:

try:
    ...
except <ExceptionName1>:
    ...
except <ExceptionName2>:
    ...
else:
    ...
finally:
    ...

try/except/else/finally Example:

try:
    a = int(raw_input("enter number"))
    break
except (NameError, TypeError, RuntimeError):
    print "err"
except:     # equal to "except Exception:", base Exception is the base class of all exception.
    pass
print "test"

raise <instance of class>:

raise IndexError('name')

assert <test>, <data>:

def f(x):
    assert x<0, 'x must be negative'

Define New Exception

Examples:

import sys
class FormatError(Execption):
    def __init__(self, line, file):
        self.line = line
        self.file = file

try:
    raise FormatError(sys._getframe().f_lineno, __file__)
except FormatError as e:
    print('Format error at: %s line %d' % (e.file, e.line))

Module: errno

Error Code to String:

import errno
import os
os.strerror(errno.E2BIG)   # Convert error code E2BIG to string: 'Argument list too long'

print errno.errorcode  # see also: linux/include/errno.h
{1: 'EPERM', 2: 'ENOENT', 3: 'ESRCH', 4: 'EINTR', 5: 'EIO', 6: 'ENXIO', 7: 'E2BIG', 8: 'ENOEXEC',
 ... }

POSIX Error Number:

e2big - argument list too long
eacces - permission denied
eaddrinuse - address already in use
eaddrnotavail - cannot assign requested address
eadv - advertise error
eafnosupport - address family not supported by protocol family
eagain - resource temporarily unavailable
ealign - EALIGN
ealready - operation already in progress
ebade - bad exchange descriptor
ebadf - bad file number
ebadfd - file descriptor in bad state
ebadmsg - not a data message
ebadr - bad request descriptor
ebadrpc - RPC structure is bad
ebadrqc - bad request code
ebadslt - invalid slot
ebfont - bad font file format
ebusy - file busy
echild - no children
echrng - channel number out of range
ecomm - communication error on send
econnaborted - software caused connection abort
econnrefused - connection refused
econnreset - connection reset by peer
edeadlk - resource deadlock avoided
edeadlock - resource deadlock avoided
edestaddrreq - destination address required
edirty - mounting a dirty fs w/o force
edom - math argument out of range
edotdot - cross mount point
edquot - disk quota exceeded
eduppkg - duplicate package name
eexist - file already exists
efault - bad address in system call argument
efbig - file too large
ehostdown - host is down
ehostunreach - host is unreachable
eidrm - identifier removed
einit - initialization error
einprogress - operation now in progress
eintr - interrupted system call
einval - invalid argument
eio - I/O error
eisconn - socket is already connected
eisdir - illegal operation on a directory
eisnam - is a named file
el2hlt - level 2 halted
el2nsync - level 2 not synchronized
el3hlt - level 3 halted
el3rst - level 3 reset
elbin - ELBIN
elibacc - cannot access a needed shared library
elibbad - accessing a corrupted shared library
elibexec - cannot exec a shared library directly
elibmax - attempting to link in more shared libraries than system limit
elibscn - .lib section in a.out corrupted
elnrng - link number out of range
eloop - too many levels of symbolic links
emfile - too many open files
emlink - too many links
emsgsize - message too long
emultihop - multihop attempted
enametoolong - file name too long
enavail - not available
enet - ENET
enetdown - network is down
enetreset - network dropped connection on reset
enetunreach - network is unreachable
enfile - file table overflow
enoano - anode table overflow
enobufs - no buffer space available
enocsi - no CSI structure available
enodata - no data available
enodev - no such device
enoent - no such file or directory
enoexec - exec format error
enolck - no locks available
enolink - link has be severed
enomem - not enough memory
enomsg - no message of desired type
enonet - machine is not on the network
enopkg - package not installed
enoprotoopt - bad proocol option
enospc - no space left on device
enosr - out of stream resources or not a stream device
enosym - unresolved symbol name
enosys - function not implemented
enotblk - block device required
enotconn - socket is not connected
enotdir - not a directory
enotempty - directory not empty
enotnam - not a named file
enotsock - socket operation on non-socket
enotsup - operation not supported
enotty - inappropriate device for ioctl
enotuniq - name not unique on network
enxio - no such device or address
eopnotsupp - operation not supported on socket
eperm - not owner
epfnosupport - protocol family not supported
epipe - broken pipe
eproclim - too many processes
eprocunavail - bad procedure for program
eprogmismatch - program version wrong
eprogunavail - RPC program not available
eproto - protocol error
eprotonosupport - protocol not supported
eprototype - protocol wrong type for socket
erange - math result unrepresentable
erefused - EREFUSED
eremchg - remote address changed
eremdev - remote device
eremote - pathname hit remote file system
eremoteio - remote i/o error
eremoterelease - EREMOTERELEASE
erofs - read-only file system
erpcmismatch - RPC version is wrong
erremote - object is remote
eshutdown - cannot send after socket shutdown
esocktnosupport - socket type not supported
espipe - invalid seek
esrch - no such process
esrmnt - srmount error
estale - stale remote file handle
esuccess - Error 0
etime - timer expired
etimedout - connection timed out
etoomanyrefs - too many references
etxtbsy - text file or pseudo-device busy
euclean - structure needs cleaning
eunatch - protocol driver not attached
eusers - too many users
eversion - version mismatch
ewouldblock - operation would block
exdev - cross-domain link
exfull - message tables full
nxdomain - the hostname or domain name could not be found

Python Functions

Overview

def is a statement, and function itself is a object, for examples:

if test-some-thing:
    def func();
        pass

func1 = lambda x:x+10

fun_name = func1
fun_name(args)

Return None by default if there is no return.

LEGB search variable: local def => parent def … => Global => Build in

Parameters

def func(arg, named_arg=None, *args, **kargs): pass
func(arg1_value, arg2_value, named_arg1=value1, named_arg2=value2)

# => arg=arg1_value, named_arg=value1, *args=(arg2_value,),  kargs={named_arg2=value2}

Arguments

def test(a, b):
    print a + ' ' + b

test(a="test", b="function")

param = ("Hello", "world")
test(*param)

dparam = {'a':"Very", 'b':"happy"}
test(**dparam)

test(*['hello', 'world'])  # directly without via a variable

Similar to print function:

>>> print(*{"a":1, 'b':2, "c":3})  # '*' mean keys only
b c a
>>> print(*[1,2,3])
1 2 3
>>> print(*{1,2,3})
1 2 3
>>> print(*(1,2,3), sep='')
123

lambda expression

func = lambda: arg1, arg2 ... argN: expression using arguments 1~N

Decorator Function

func = decorator_func(func) cls = decorator_func(cls) func = decorator_cls().__call__(func) cls = decorator_cls().__call__(cls) func = decorator_func(args)(func) # decorator(args) will return sub decorator_func(func)

Function decorator:

import time
import functools

def timeit(func):
    @functools.wraps(func)
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'used:', end - start
        return wrapper

@timeit
def foo():
    print 'in foo()'

Class decorator:

class HTML(object):
"""Baking HTML Tags!"""

    def __init__(self, tag="p"):
        print("LOG: Baking Tag <{}>!".format(tag))
        self.tag = tag

    def __call__(self, func):
        return lambda: "<{0}>{1}</{0}>".format(self.tag, func(), self.tag)

@HTML("div")
@HTML("p")
def body():
    return "Hello"

print(body())       # HTML("div")__call__((HTML("div")__call__(body)))

LOG: Baking Tag <div>!
LOG: Baking Tag <p>!
<div><p>Hello</p></div>

Python Functional Programming

Built-in Functions

map/filter/reduce

Note

reduce() is in functools library but not a built-in function in python3.

Example:

>>> import operator, functools
>>> functools.reduce(operator.add, [1,2,3,4], 0)
10

Higher-Order Functions

Example:

def compose(*funcs):
    """Return a new function s.t. compose(f,g,...)(x) == f(g(...(x)))"""
    def inner(data, funcs=funcs):
        result = data
        for f in reversed(funcs):
            result = f(result)
        return result
    return inner

# >>> times2 = lambda x: x*2
# >>> minus3 = lambda x: x-3
# >>> mod6 = lambda x: x%6
# >>> f = compose(mod6, times2, minus3)
# >>> all(f(i)==((i-3)*2)%6 for i in range(1000000))
# True

Module: itertools

Infinite iterators:

Iterator Arguments Example
count() start, [step] count(10) –> 10 11 12 13 14 …
cycle() p cycle(‘ABCD’) –> A B C D A B C D …
repeat() elem [,n] repeat(10, 3) –> 10 10 10

Iterators terminating on the shortest input sequence:

Iterator Arguments Example
accumulate() p [,func] accumulate([1,2,3,4,5]) –> 1 3 6 10 15
chain() p, q, … chain(‘ABC’, [1,2,3]) –> A B C 1 2 3
compress() data, selectors compress(‘ABCDEF’, [1,0,1,0,1,1]) –> A C E F
takewhile() pred, seq takewhile(lambda x: x<5, [1,4,6,4,1]) –> 1 4
dropwhile() pred, seq dropwhile(lambda x: x<5, [1,4,6,4,1]) –> 6 4 1
filterfalse() pred, seq filterfalse(lambda x: x%2, range(10)) –> 0 2 4 6 8
groupby() iterable[,func] sub-iterators grouped by value of keyfunc(v)
islice() seq, … islice(‘ABCDEFG’, 2, None) –> C D E F G
starmap() func, seq starmap(pow, [(2,5), (3,2), (10,3)]) –> 32 9 1000
tee() it, n it1, it2, … itn splits one iterator into n
zip_longest() p, q, … zip_longest(‘ABCD’, ‘xy’, fillvalue=’-‘) –> Ax By C- D-

Combinatoric generators:

Iterator Arguments Example
product() p,…[repeat=1] product(“ABC”, “123”) =>(A,1),(A,2),(A,3),(B,1),..(C,2),(C,3)
permutations() p[, r] permutations([1,2,3], 3)=>(1,2,3),(1,3,2),(2,1,3),(2,3,1),…
combinations() p, r combinations([1,2,3], 2)=>(1,2),(1,3),(2,3)

Example:

>>> list(itertools.tee([1,2,3,4], 2))
[<itertools.tee object at 0x7feff9d40128>, <itertools.tee object at 0x7feff9d40170>]
>>> list(itertools.tee([1,2,3,4], 2)[0])
[1, 2, 3, 4]
>>> list(itertools.tee([1,2,3,4], 2)[1])
[1, 2, 3, 4]

#----------------------------------------------------------------------

city_list = [('Decatur', 'AL'), ('Huntsville', 'AL'), ('Selma', 'AL'),
             ('Anchorage', 'AK'), ('Nome', 'AK'),
             ('Flagstaff', 'AZ'), ('Phoenix', 'AZ'), ('Tucson', 'AZ')]

def get_state(city_state):
    return city_state[1]

itertools.groupby(city_list, get_state) =>
 ('AL', iterator-1),
 ('AK', iterator-2),
 ('AZ', iterator-3), ...

 where
 iterator-1 => ('Decatur', 'AL'), ('Huntsville', 'AL'), ('Selma', 'AL')
 iterator-2 => ('Anchorage', 'AK'), ('Nome', 'AK')
 iterator-3 => ('Flagstaff', 'AZ'), ('Phoenix', 'AZ'), ('Tucson', 'AZ')

#----------------------------------------------------------------------

>>> print(*[(k, list(g)) for k, g in groupby('1222233')], sep=' ')
('1', ['1']) ('2', ['2', '2', '2', '2']) ('3', ['3', '3'])

>>> list(itertools.combinations_with_replacement([1,2,3], 2))
[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]

>>> list(itertools.product("01",repeat=3))
[('0', '0', '0'), ('0', '0', '1'), ('0', '1', '0'), ('0', '1', '1'),
('1', '0', '0'), ('1', '0', '1'), ('1', '1', '0'), ('1', '1', '1')]

Module: functools

@functools.lru_cache(maxsize=128, typed=False):

Decorator to wrap a function with a memoizing callable that saves up to the maxsize most recent calls.

@functools.total_ordering:

Decorator to wrap a class, provide at least __eq__() and one of __lt__(), __le__(), __gt__(), or __ge__(). The others will be included automatically based on above eq and at least one of others.

functools.partial(func, *args, **keywords): functools.partialmethod(func, *args, **keywords):

Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.

@functools.singledispatch:

See also multipledispatch module

@functools.wraps(func):

Decorator to wrap the internal function of a decorator.

Example:

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')  # => 18

Module: operator

operators in module operator:

Syntax                  Function
a + b                   add(a, b)
seq1 + seq2             concat(seq1, seq2)
obj in seq              contains(seq, obj)
a / b                   truediv(a, b)
a // b                  floordiv(a, b)
a & b                   and_(a, b)
a ^ b                   xor(a, b)
~a                      invert(a)
a | b                   or(a, b)
a ** b                  pow(a, b)
a is b                  is(a, b)
a is not b              is_not(a, b)
obj[k] = v              setitem(obj, k, v)
del obj[k]              delitem(obj, k)
obj[k]                  getitem(obj, k)
a << b                  lshift(a, b)
a % b                   mod(a, b)
a * b                   mul(a, b)
a @ b                   matmul(a, b)
-a                      neg(a)
not a                   not_(a)
+a                      pos(a)
a >> b                  rshift(a, b)
seq[i:j] = values       setitem(seq, slice(i, j), values)
del seq[i:j]            delitem(seq, slice(i, j))
seq[i:j]                getitem(seq, slice(i, j))
s % obj                 mod(s, obj)
a - b                   sub(a, b)
obj                     truth(obj)
a < b                   lt(a, b)
a <= b                  le(a, b)
a == b                  eq(a, b)
a != b                  ne(a, b)
a >= b                  ge(a, b)
a > b                   gt(a, b)
a += b                  a = iadd(a, b)
a &= b                  a = iand(a, b)
ListA += listB          ListA = iconcat(ListA, listB)
a //= b                 a = ifloordiv(a, b)
a <<= b                 a = ilshift(a, b)
a %= b                  a = imod(a, b)
a *= b                  a = imul(a, b)
a @= b                  a = imatmul(a, b)
a |= b                  a = ior(a, b)
a **= b                 a = ipow(a, b)
a >>= b                 a = irshift(a, b)
a -= b                  a = isub(a, b)
a /= b                  a = itruediv(a, b)
a ^= b                  a = ixor(a, b)

Module: multipledispatch

Example:

from multipledispatch import dispatch

@dispatch(Rock, Rock)
def beats3(x, y): return None

@dispatch(Rock, Paper)
def beats3(x, y): return y

@dispatch(Rock, Scissors)
def beats3(x, y): return x

@dispatch(Paper, Rock)
def beats3(x, y): return x

@dispatch(Paper, Paper)
def beats3(x, y): return None

@dispatch(Paper, Scissors)
def beats3(x, y): return x

@dispatch(Scissors, Rock)
def beats3(x, y): return y

@dispatch(Scissors, Paper)
def beats3(x, y): return x

@dispatch(Scissors, Scissors)
def beats3(x, y): return None

@dispatch(object, object)
def beats3(x, y):
    if not isinstance(x, (Rock, Paper, Scissors)):
        raise TypeError("Unknown first thing")
    else:
        raise TypeError("Unknown second thing")

# >>> beats3(rock, paper)
# <__main__.DuckPaper at 0x103b894a8>
# >>> beats3(rock, 3)
# TypeError: Unknown second thing

Module: predicative_dispatch

Example:

from predicative_dispatch import predicate

@predicate(lambda x: x < 0, lambda y: True)
def sign(x, y):
    print("x is negative; y is", y)

@predicate(lambda x: x == 0, lambda y: True)
def sign(x, y):
    print("x is zero; y is", y)

@predicate(lambda x: x > 0, lambda y: True)
def sign(x, y):
    print("x is positive; y is", y)

Python Class

Overview

In python, class can be used to create a instance, But still, it’s an object and therefore:

  • you can assign it to a variable
  • you can copy it
  • you can add attributes to it
  • you can pass it as a function parameter

Examples:

>>> class myClass(object):
...     pass
...
>>> type(myClass)
<type 'type'>
>>> type(myClass())
<class '__main__.myClass'>

>>> print myClass
<class '__main__.myClass'>
>>> print myClass()
<__main__.myClass object at 0x7f5cdbfca210>

>>> new_class = myClass
>>> print new_class
<class '__main__.myClass'>

Create Class via type()

Besides define the class by “class” keyword, you can also use type() function:

var = type(classname, tuple of parent classes, dictionary containing attributes)

For example:

new_class = type('myClass', (object,), {'test': True})
>>> type(new_class)
<type 'type'>
>>> type(new_class())
<class '__main__.myClass'>
>>> print new_class.test
True

>>> type(myClass)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  NameError: name 'myClass' is not defined

Note

This is also what python do in the background when you define a class by “class” keyword.

What’s metaclasses

http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

We learned that Python classes are objects. Well, metaclasses are what create these objects. They are the classes’ classes, you can picture them this way:

myClass = metaClass()
myObject = myClass()

As you know, ‘int’ is a normal class to create integers, ‘str’ is a normal class to create strings. The above “type” is also a class, which is used to create other classes, so, we call it metaclass.

Example for how to define a metaclass (normally, it overwrite __new__ to do some special things):

class UpperAttrMetaclass(type):
    def __new__(cls, clsname, bases, dct):
        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val
        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)


class myClass(object):
    __metaclass__ = UpperAttrMetaclass  # Use this metaclass instead of default 'type'
    class_attr = "Yes"

def __init__(self):
    self.inst_attr = "right"
    super(myClass, self).__init__()

if __name__ == '__main__':
    c = myClass()
    print(c.CLASS_ATTR)      # The class attribute name is changed when call __new__
    print(c.inst_attr)       # instance attribute is not changed because __init__ is called after __new__.

How to search the metaclass:

  • If there is __metaclass__ attribute in current class, use it
  • Find the first __metaclass__ attribute in parent classes, use it.
  • If there is the definiation of __metaclass__ variable in current or imported module(file), use it.
  • Otherwise, use type by default.

Please note that __metaclass__ can also be a function, for example:

def upper_attr(future_class_name, future_class_parents, future_class_attr):
    attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))

__metaclass__ = upper_attr  # For all classes in this module which has no their own metaclass.

Most of the time, you don’t need metaclass. Instead of metaclass, you can also use “monkey patching” or “class decorators”

Monkey Patching

Monkey patching is used to:

  • Replace methods/attributes/functions at runtime, e.g. to stub out a function during testing;
  • Modify/extend behaviour of a third-party product without maintaining a private copy of the source code;
  • Apply a patch at runtime to the objects in memory, instead of the source code on disk;
  • Distribute security or behavioural fixes that live alongside the original source code.

Carelessly written or poorly documented monkey patches can lead to problems:

  • They can lead to upgrade problems when the patch makes assumptions about the patched object that are no longer true; if the product you have changed changes with a new release it may very well break your patch. For this reason monkey patches are often made conditional, and only applied if appropriate.[4]
  • If two modules attempt to monkey patch the same method, one of them (whichever one runs last) “wins” and the other patch has no effect, unless monkey patches are written with a pattern like alias_method_chain.
  • They create a discrepancy between the original source code on disk and the observed behaviour that can be very confusing to anyone unaware of the patches’ existence.

The following Python example monkey patches the value of Pi from the standard math library:

>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3

Class decorators

For example:

class classDecorator(object):
    def __init__(self, func):
        super(classDecorator, self).__init__()
        self.func = func

    def __call__(self, msg):
        print("class decorator ...")
        return self.func(msg)

# echo = classDecorator(echo)
@classDecorator
def echo(msg):
    print(msg)

print(echo)     # echo is a instance of classDecorator now.
echo('hello')   # equal to classDecorator(echo).__call__('hello')

There is three built-in decorators for class

  • @staticmethod
  • @classmethod
  • @property

Example for @property:

class Student(object):
    def __init__(self):
        super(Student, self).__init__()
        self._score = 0

    @property               # this define a getter, and also define @score.setter
    def score(self):
        return self._score

    @score.setter           # Optional, proerty will be readonly without this setter.
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

s = Student()
print s.score       # ==> 0
s.score = 98
print s.score       # ==> 98

Please see also @abstractmethod in abc(Abstract Base Classes) module.

Python Modules

The Paths for Import

Specified by sys.path, the default path in order:

  1. Current directory
  2. PYTHONPATH (path1:path2…)
  3. Standard installation directories
  4. Specified by xxx.pth file (one line for each path)

Of course, we can append path in to sys.path like this:

sys.path.append('Path-for-mymoudule')
import mymodule

How to Import Modules

import xxx:
import xxx, yyy:
import <package-name>.<module-name>:

Compile and execute all the code in the module, and import itself like a object into current name space.

import xxx as yyy:

Same as import, but also rename the module object in current name space.

from xxx import yyy:

Compile and execute all the code in the module, and only import yyy into current name space.

from xxx import *:

Compile and execute all the code in the module, and import each in it into current name space.

from xxx import yyy as zzz:

Same as “from xxx import yyy”, but also rename it to “zzz”.

from .xxx improt yyy:
from ..xxx improt yyy:
from . improt yyy:
from .. import yyy:

Require the current module and the “xxx” module are in the same package.

Note

variables/functions start with _X will not be imported by from xxx import *

When call the properties from outside of class, need to add class name like this ‘_className__x’.

Note

import requires using module name later, but from import the name directly, must be careful.

Note

import、from can also import pyc, package directory, c module, zip archive.

__init__.py

All code in __init__.py will be execute when first import the package.

List __all__ in __init__.py defines the module which will be imported when from xxx import *. Otherwise, you must use ‘import’ to import the sub modules one by one manually.

Local Import

As the same as def, import and from also are statements, and can be used any where, such as in if/else, or inside of a function:

def square_root(a):
    # This import is into the square_root functions local scope
    import math
    return math.sqrt(a)

Optional Import

try:
    # Python 2.x
    from urlparse import urljoin
    from urllib2 import urlopen
except ImportError:
    # Python 3.x
    from urllib.parse import urljoin
    from urllib.request import urlopen

Python Design Patterns

Creational Patterns:

Pattern Description
abstract_factory use a generic function with specific factories
borg a singleton with shared-state among instances
builder instead of using multiple constructors, builder object receives parameters and returns constructed objects
factory_method delegate a specialized function/method to create instances
lazy_evaluation lazily-evaluated property pattern in Python
pool preinstantiate and maintain a group of instances of the same type
prototype use a factory and clones of a prototype for new instances (if instantiation is expensive)

Structural Patterns:

Pattern Description
3-tier data<->business logic<->presentation separation (strict relationships)
adapter adapt one interface to another using a white-list
bridge a client-provider middleman to soften interface changes
composite encapsulate and provide access to a number of different objects
decorator wrap functionality with other functionality in order to affect outputs
facade use one class as an API to a number of others
flyweight transparently reuse existing instances of objects with similar/identical state
front_controller single handler requests coming to the application
mvc model<->view<->controller (non-strict relationships)
proxy an object funnels operations to something else

Behavioral Patterns:

Pattern Description
chain apply a chain of successive handlers to try and process the data
catalog general methods will call different specialized methods based on construction parameter
chaining_method continue callback next object method
command bundle a command and arguments to call later
mediator an object that knows how to connect other objects and act as a proxy
memento generate an opaque token that can be used to go back to a previous state
observer provide a callback for notification of events/changes to data
publish_subscribe a source syndicates events/data to 0+ registered listeners
registry keep track of all subclasses of a given class
specification business rules can be recombined by chaining the business rules together using boolean logic
state logic is organized into a discrete number of potential states and the next state that can be transitioned to
strategy selectable operations over the same data
template an object imposes a structure but takes pluggable components
visitor invoke a callback for all items of a collection

Singleton

Examples:

# Method 1: only __new__() once
class Singleton(object):
    def __new__(cls,*args,**kwargs):
        if not hasattr(cls,'_inst'):
            cls._inst=super(Singleton,cls).__new__(cls,*args,**kwargs)
        return cls._inst

# Method 2: share the __dict__
class Borg(object):
    _shared_state={}
    def __new__(cls,*args,**kwargs):
        obj=super(Borg,cls).__new__(cls,*args,**kwargs)
        obj.__dict__=cls._shared_state
        return obj

Note

The pythonic way is to define a module if you want to use singleton class.

Python Project

Typical Structure

foobar
|__docs
|         |__conf.py
|         |__quickstart.rst
|         |__index.rst
|__foobar
|          |__ __init__.py
|          |__xxx.py
|          |__tests
|                   |__ __init__.py
|                   |__ test_xxx.py
|__tools
|__data
|__setup.py
|__ReadMe.rst
|__requirements.txt   # the dependencies

virtualenv

virtualenv + virtualenvwrapper:

sudo pip install virtualenv
sudo pip install virtualenvwrapper

[MAC OS] pyenv + pyenv-virtualenv:

brew install pyenv
brew install pyenvbrew install pyenv

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi

pyenv install -l
pyenv install 3.5.2
pyenv rehash

在任意目录, 如果想在这个目录及其子目录中使用不同的python版本
pyenv local 3.5.2
python --version  #should be 3.5.2
pyenv virtualenv 3.5.2 venv3
pyenv shell venv3
pyenv activate venv3

pyenv virtualenv-delete venv3       # delete the virtualenv
pyenv <tab>                         # to show all sub commands

不建议使用 pyenv global, 可能对全局其他程序有影响。

pyenv:  安装切换不同的python版本,但是同一个版本还是共用一个python环境
virtualenv:   创建不同的python环境 (--python指定基于哪一个python版本,要求系统中先装好了对应版本)
virtualenvwrapper: 更加方便地创建和管理不同的virtualenv。
pyenv-virtualenv: 把virtualenv集成到pyenv中, 同时自带virtualenvwrapper 和autoenv 类似高阶管理功能。

如果系统已经自带多个python版本, 比如ubuntu16.04 自带python2 和python3,
或许virtualenv + virtualenvwrapper 足够。
如果还需要自己安装管理多个python版本,python环境, 比如 MacbootPro 2015上面,
那么 pyenv+pyenv-virtualenv 可能更适合。

Coding Style

PEP8 online: http://www.pep8online.com/

pylint:

https://www.pylint.org/

https://pylint.readthedocs.io/en/latest/

sudo apt-get install pylint

There are 5 kind of message types : * (C) convention, for programming standard violation * (R) refactor, for bad code smell * (W) warning, for python specific problems * (E) error, for much probably bugs in the code * (F) fatal, if an error occurred which prevented pylint from doing

Examples:

pylint --generate-rcfile >pylint.conf
pylint --rcfile=pylint.conf  xxx.py
pylint --reports=n xxx.py

pep8(pycodestyle):

https://pypi.python.org/pypi/pep8

sudo pip install pep8, and run it like this: pep8 <source-file>.

Note

There is a pyflakes vim plugin: https://github.com/vim-scripts/pyflakes

flake8:

https://pypi.python.org/pypi/flake8

豆瓣内部要求使用这个, Include Pyflakes + Pycodestyle + McCabe … + other plugins。

Code complexity:

flake8 --max-complexity 10 app.py  (#It's better not greater than 10)

PEP8 Auto-convert tool:

Configuration

  1. Use a config.py file or the config module
  2. Module “configparser” for ini configuration file
  3. Module “json” for json configuration file
  4. Module “csv” for csv configuration file
  5. Module “xml.etree.ElementTree ” for xml configuration file

Examples for json:

with open('comments.json', 'r') as f: # see also json.load()
    comments = json.loads(f.read())

with open('comments.json', 'w') as f: # see also json.dump()
    f.write(json.dumps(comments, indent=4, separators=(',', ': ')))

Unittest

Module “unittest” for unit tests.

See also nose: - http://nose.readthedocs.org/en/latest/ - http://pythontesting.net/framework/nose/nose-introduction/

Documentation

Tips:

  1. Use some formal template of document
  2. Simple sentences
  3. One topic for each paragraph
  4. More use of present tenses
  5. Use real codes as the examples.
  6. Good code is always better than many documents.

HowTO:

  1. Document project: sphinx + reStructuredText
  2. doctest: https://docs.python.org/2/library/doctest.html
  3. pydoc: https://docs.python.org/2/library/pydoc.html
  4. epydoc tool: http://epydoc.sourceforge.net/

Epydoc is a tool for generating API documentation for Python modules, based on their docstrings. For an example of epydoc’s output, see the API documentation for epydoc itself.

A lightweight markup language called epytext can be used to format docstrings, and to add information about specific fields, such as parameters and instance variables. Epydoc also understands docstrings

License

The lice tool: https://github.com/licenses/lice

lice [opts ...]  ('afl3', 'agpl3', 'apache', 'bsd2', 'bsd3', 'cc0',
'cc_by', 'cc_by_nc', 'cc_by_nc_nd', 'cc_by_nc_sa', 'cc_by_nd',
'cc_by_sa', 'cddl', 'epl', 'gpl2', 'gpl3', 'isc', 'lgpl', 'mit',
'mpl', 'wtfpl', 'zlib')

Package

Module ‘setuptools’

Continuous Integration

buildbot

http://buildbot.net/

Quick start:

sudo pip install buildbot
sudo pip install buildbot-www
sudo pip install buildbot-waterfall_view
sudo pip install buildbot-console_view
sudo pip install buildbot-worker

buildbot create-master /tmp/experimental_buildmaster
cp /tmp/experimental_buildmaster/master.cfg.sample /tmp/experimental_buildmaster/master.cfg
buildbot upgrade-master /tmp/experimental_buildmaster   # each time when change the conf file

# Check the worker name and password from master.cfg
buildbot-worker create-worker /tmp/experimental_buildslave localhost:9989 example-worker pass
buildbot-worker start /tmp/experimental_buildslave

firefox http://localhost:8010/ &
Builds => runtests => force => Input "Your name"(email) and click "Start Build"

Project Template

https://github.com/audreyr/cookiecutter

Create new project base on a template:

pip install cookiecutter
cookiecutter https://github.com/sloria/cookiecutter-flask.git

All templates here: https://github.com/audreyr/cookiecutter#a-pantry-full-of-cookiecutters

Other code check tool

https://wiki.python.org/moin/PythonTestingToolsTaxonomy

pychecker:

http://pychecker.sourceforge.net/

Install: sudo apt-get install pychecker

clonedigger:

Clone Digger aimed to detect similar code in Python and Java programs. The synonyms for the term “similar code” are “clone” and “duplicate code”.

http://clonedigger.sourceforge.net/

Install: sudo pip install clonedigger

Examples:

clonedigger source_file_1 source_file_2 ...
clonedigger path_to_source_tree

coverage:

Install: sudo pip install coverage

Examples:

/usr/local/bin/coverage run test.py  # the output is in file "./.coverage" by default
/usr/local/bin/coverage report -m    # line range show the code which is not covered.
/usr/local/bin/coverage html         # the outputs are in folder "./htmlcov" by default
firefox htmlcov/index.html

profile:

https://docs.python.org/3/library/profile.html

Examples:

python -m cProfile test.py

pymetrics: The complexity test tool

http://www.traceback.org/2008/03/31/measuring-cyclomatic-complexity-of-python-code/

/tmp/pymetrics-0.8.1/pymetrics ./send-pull-request

Python PEP8 in Chinese

代码编排

  1. 缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。
  2. 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。
  3. 类和top-level函数定义之间空两行;类中的方法定义之间空一行 函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。

文档编排

  1. 模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。 其中import部分,又按标准、三方和自己编写顺序依次排放,之间空一行。
  2. 不要在一句import中多个库,比如import os, sys不推荐。
  3. 如果采用from XX import XX引用库,可以省略‘module.’,都是可能出现命名冲突,这时就要采用import XX。

空格的使用

总体原则,避免不必要的空格。

  1. 各种右括号前不要加空格。
  2. 逗号、冒号、分号前不要加空格。
  3. 函数的左括号前不要加空格。如Func(1)。
  4. 序列的左括号前不要加空格。如list[2]。
  5. 操作符左右各加一个空格,不要为了对齐增加空格。
  6. 函数默认参数使用的赋值符左右省略空格。
  7. 不要将多句语句写在同一行,尽管使用‘;’允许。
  8. if/for/while语句中,即使执行语句只有一句,也必须另起一行。

注释

总体原则:

  1. 避免无谓的注释。
  2. 错误的注释不如没有注释。所以当一段代码发生变化时,第一件事就是要修改注释!

注释必须使用英文,最好是完整的句子,首字母大写,句后要有结束符。 如果是短语,可以省略结束符。

  1. 块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:

    # Description : Module config.
    #
    # Input : None
    #
    # Output : None
    
  2. 行注释,在一句代码后加注释,这种方式尽量少使用。比如: x = x + 1 # Increment x

文档描述

  1. 为所有的共有模块、函数、类、方法写docstrings;非共有的没有必要,但是可以写注释(在def的下一行)。

  2. 如果docstring要换行,参考如下例子,详见PEP 257:

    """Return a foobang
    Optional plotz says to frobnicate the bizbaz first.
    """
    

命名规范

总体原则,新编代码必须按下面命名风格进行,现有库的编码尽量保持风格。

  1. 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母。
  2. 模块命名尽量短小,使用全部小写的方式,可以使用下划线。
  3. 包命名尽量短小,使用全部小写的方式,不可以使用下划线。
  4. 类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。
  5. 异常命名使用CapWords+Error后缀的方式。
  6. 全局变量尽量只在模块内有效,类似C语言中的static。实现方法有两种,一是__all__机制;二是前缀一个下划线。
  7. 函数命名使用全部小写的方式,可以使用下划线。
  8. 常量命名使用全部大写的方式,可以使用下划线。
  9. 类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。
  10. 类的私有属性(方法和变量)以一条下划线作为前缀。
  11. 类的属性若与关键字名字冲突,后缀一下划线,尽量不要使用缩略等其他方式。
  12. 为避免与子类属性命名冲突,在类的一些属性前,前缀两条下划线。 比如:类Foo中声明__a,访问时,只能通过Foo._Foo__a,避免歧义。如果子类也叫Foo,那就无能为力了。
  13. 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls。

编码建议

  1. 编码中考虑到其他python实现的效率等问题,比如运算符‘+’在CPython(Python)中效率很高 都是Jython中却非常低,所以应该采用.join()的方式。

  2. 尽可能使用‘is’‘is not’取代‘==’,比如if x is not None 要优于if x。

  3. 使用基于类的异常,每个模块或包都有自己的异常类,此异常类继承自Exception。

  4. 异常中不要使用裸露的except,except后跟具体的exceptions。

  5. 异常中try的代码尽可能少。比如:

    try:
        value = collection[key]
    except KeyError:
        return key_not_found(key)
    else:
        return handle_value(value)
    
    优于
    try:
        return handle_value(collection[key])
    except KeyError:
        # Will also catch KeyError raised by handle_value()
        return key_not_found(key)
    
  6. 使用startswith() and endswith()代替切片进行序列前缀或后缀的检查。比如:

    if foo.startswith('bar'):
    优于
    if foo[:3] == 'bar':
    
  7. 使用isinstance()比较对象的类型。比如:

    if isinstance(obj, int):
    优于
    if type(obj) is type(1):
    
  8. 判断序列空或不空,有如下规则:

    if not seq:
    if seq:
    优于
    if len(seq)
    if not len(seq)
    
  9. 字符串不要以空格收尾。

  10. 二进制数据判断使用 if boolvalue的方式。

  11. 超长行字符串定义:

    "this is line one, and then"
    "this is line two to avoid long line"
    

unittest Quickstart

pytest is better than the unittest standard library.

https://docs.python.org/2.7/library/unittest.html

All test case methods must begin with test, and run in the order of name.

Example(test.py):

#!/usr/bin/python
# -*- coding:utf-8 -*-

import unittest

class TestStringMethods(unittest.TestCase):  #must based on unitest.TestCase
    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    #unittest.main()    # run all test cases by default

    #suite =  unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)
    suite = unittest.TestSuite()    # create test suite to test part of the cases
    suite.addTest(TestStringMethods('test_upper'))
    suite.addTest(TestStringMethods('test_isupper'))

    unittest.TextTestRunner(verbosity=2).run(suite)

Run the test case:

./test.py
python -m unittest -v test                     # Run special test module
python -m unittest -v test.TestStringMethods   # Run special test class in the module
python -m unittest -v test.TestStringMethods.test_split  #run special test case
python -m unittest discover ./ "test*.py"      # Discover all test cases.

Important concepts

test fixture:
A test fixture represents the preparation needed to perform one or more tests, and any associate cleanup actions. This may involve, for example, creating temporary or proxy databases, directories, or starting a server process.
test case:
A test case is the smallest unit of testing. It checks for a specific response to a particular set of inputs. unittest provides a base class, TestCase, which may be used to create new test cases.
test suite:
A test suite is a collection of test cases, test suites, or both. It is used to aggregate tests that should be executed together.
test runner:
A test runner is a component which orchestrates the execution of tests and provides the outcome to the user. The runner may use a graphical interface, a textual interface, or return a special value to indicate the results of executing the tests.

Fixtures

setUp/tearDown() for test case level setUpClass()/tearDownClass for class level, need the @classmethod decorator. setUpModule()/tearDownModule() for module level

Skip/ExpectFaiure

The following decorators implement test skipping and expected failures:

@unittest.skip(reason): Unconditionally skip the decorated test. reason should describe why the test is being skipped.

@unittest.skipIf(condition, reason): Skip the decorated test if condition is true.

@unittest.skipUnless(condition, reason): Skip the decorated test unless condition is true.

@unittest.expectedFailure(): Mark the test as an expected failure. If the test fails when run, the test is not counted as a failure.

Skipped tests will not have setUp() or tearDown() run around them. Skipped classes will not have setUpClass() or tearDownClass() run.

Asserts

Method Checks that
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b
assertGreaterEqual(a, b) a >= b
assertLess(a, b) a < b
assertLessEqual(a, b) a <= b
assertRegexpMatches(s, r) r.search(s)
assertNotRegexpMatches(s, r) not r.search(s)
assertItemsEqual(a, b) sorted(a) == sorted(b)
assertDictContainsSubset(a, b) all the key/value pairs in a exist in b

Python Interview

Python Shell

sh

sh (previously pbs) is a full-fledged subprocess interface for Python that allows you to call any program as if it were a function:

from sh import ifconfig
print ifconfig("eth0")

They may be executed on the sh namespace, or imported directly from sh:

import sh
print(sh.ifconfig("eth0"))

For commands that have dashes in their names, for example /usr/bin/google-chrome, substitute the dash for an underscore:

import sh
sh.google_chrome("http://google.com")

For commands that take multiple arguments, need to be invoked using separate string for each argument rather than single string for all:

from sh import ls
ls("-l", "./")  # ls("-l ./") will not work

For commands with more exotic characters in their names, like ., or if you just don’t like the “magic”-ness of dynamic lookups, you may use sh’s Command wrapper and pass in the command name or the absolute path of the executable:

import sh
run = sh.Command("/home/amoffat/run.sh") # Absolute path
run()
lscmd = sh.Command("ls")  # Absolute path not needed
lscmd()
lscmd('./')

Note

Similarly, sh.Command(“ls ./”) will not work! Must wrap command only and pass parameters later one by one.

Commands support short-form -a and long-form –arg arguments as keyword arguments:

# resolves to "curl http://duckduckgo.com/ -o page.html --silent"
curl("http://duckduckgo.com/", o="page.html", silent=True)

# or if you prefer not to use keyword arguments, this does the same thing:
curl("http://duckduckgo.com/", "-o", "page.html", "--silent")

# resolves to "adduser amoffat --system --shell=/bin/bash --no-create-home"
adduser("amoffat", system=True, shell="/bin/bash", no_create_home=True)

# or
adduser("amoffat", "--system", "--shell", "/bin/bash", "--no-create-home")

Shell style piping is performed using function composition. Just pass one command as the input to another, and sh will create a pipe between the two:

# sort this directory by biggest file
print(sort(du(glob("*"), "-sb"), "-rn"))

# print(the number of folders and files in /etc
print(wc(ls("/etc", "-1"), "-l"))

You can redirect the stdin, stdout and stderr streams of a process to a file or file-like object by the special _in, _out and _err keyword argument:

ls(_out="files.list")
ls("nonexistent", _err="error.txt")
print(tr("[:lower:]", "[:upper:]", _in="sh is awesome")) # SH IS AWESOME

The exit code can be seen through a command’s exit_code property:

output = ls("/")
print(output.exit_code) # should be 0

For other more advance features, please refer to: http://amoffat.github.io/sh/

os.system()

Return 0 for success and others for failure.

test.py:

import os

retcode = os.system("cp ./test.py ./test1.py")
print("retcode is: %d" % retcode);

retcode = os.system("cp ./not_exist_file.py ./test1.py")
print("retcode is: %d" % retcode);

$ python ./test.py:

retcode is: 0
cp: cannot stat ‘./not_exist_file.py’: No such file or directory
retcode is: 256

os.popen()

# get the result only
fouput = os.popen("ls /home/test")
print fouput.readlines()

# or use the input only
finput = os.popen("python TestInput.py", "w")
finput.write("how are you\n")

subprocess

It’s better to use subprocess instead of os.popen() and os.system()

Python SSH

pxssh

https://pexpect.readthedocs.org/en/stable/api/pxssh.html

Example:

import pxssh
import getpass
try:
    s = pxssh.pxssh()
    hostname = raw_input('hostname: ')
    username = raw_input('username: ')
    password = getpass.getpass('password: ')

    s.login (hostname, username, password, original_prompt='[$#>]')

    s.sendline ('uptime')
    s.prompt()
    print s.before

    s.sendline ('ls -l')
    s.prompt()
    print s.before

    s.logout()

except pxssh.ExceptionPxssh, e:
    print "pxssh failed on login."
    print str(e)

parmmiko

http://www.paramiko.org/

Installation:

sudo pip install pycrypto
sudo pip install paramiko

Example:

import paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, 22, user, passwd, timeout=7200)
stdin, stdout, stderr = ssh.exec_command("uptime")
print(stdout.readlines())
stdin, stdout, stderr = ssh.exec_command("uname -a")
print(stdout.readlines())
ssh.close()

Python Web Scraping

beautifulsoup

lxml

The lxml XML toolkit is a Pythonic binding for the C libraries libxml2 and libxslt. The speed is more fast than beautifulsoup. Maybe some problem in multi-thread, so it’s better to use the multi-process.

sudo apt-get install python-lxml sudo pip install cssselect

Example:

from lxml.etree import HTML
import requests

url = 'https://segmentfault.com/'
res = requests.get(url)
page = HTML(res.text)
for title in page.cssselect('.title>a'):
    #print(title.text.encode('UTF-8')) # For python2.7
    print title.text                   # For python3.x

urllib

Selenium

pip3 install selenium

Example:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from time import sleep
from selenium import webdriver

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")

driver.find_element_by_id("kw").send_keys("Selenium2")
driver.find_element_by_id("su").click()                     # search "Selenium2"

sleep(1)
driver.get_screenshot_as_file('./search_result.png')

driver.implicitly_wait(10)
driver.find_element_by_xpath(".//*[@id='1']/h3/a").click()  # goto the first result

sleep(3)
driver.quit()

Note

Fix issue that firefox 47.0 in ubuntu 16.04 is not supported yet.
If you have also some problems when run above example, please have try:
$ sudo apt-get purge firefox # remove current firefox 47.0
$ sudo apt-cache show firefox | grep Version # checke valid versions
$ sudo apt-get install firefox=45.0.2+build1-0ubuntu1 # install this 45.0 version
$ sudo apt-mark hold firefox # mark that will not update firefox
If you want to update firefox later:
$ sudo apt-mark unhold firefox
$ sudo apt-get upgrade

Scrapy

Python Email

Example:

import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from .config import Config
from .utils import Logger
from .git import Git

class RREmail(object):
    def __init__(self, user=None, from_email=None, to_email=None, cc_email=None):
        super(RREmail, self).__init__()
        self.from_email = from_email or Git.get_user_email()
        self.to_email = to_email or Config.GateKeeper
        self.cc_email = cc_email or Config.CHECK_IN_CC
        self.user = user or Config.EMAIL_USER
        self.server = Config.EMAIL_SMTP_SERVER
        self.port = Config.EMAIL_PORT
        self.sm = smtplib.SMTP(self.server, self.port, timeout=20)

    # Not neccessary
    def login(self, user='', password=''):
        #self.sm.set_debuglevel(1)
        #self.sm.ehlo()
        #self.sm.starttls()
        #self.sm.ehlo()
        self.sm.login(user or self.user,
                      password or raw_input('Please input the email password: ').strip())

    def send(self, subject, body, body_html=None, attachments=None, in_reply_to=None):
        message = MIMEMultipart('related')
        message['Subject'] = subject
        message['From'] = self.from_email
        message['To'] = self.to_email
        if self.cc_email.strip():
            message['CC'] = self.cc_email
        if in_reply_to is not None:
            message['In-Reply-To'] = in_reply_to

        msg_body = MIMEMultipart('alternative')
        message.attach(msg_body)

        body_plain = MIMEText(body, 'plain')
        msg_body.attach(body_plain)

        if body_html is not None:
            body_html = MIMEText(body_html, 'html', 'utf-8')
            msg_body.attach(body_html)

        if attachments is not None:
            for patch in attachments:
                f = open(patch)
                att = MIMEText(f.read(), 'plain', 'utf-8')
                att["Content-Type"] = 'text/plain'
                att["Content-Disposition"] = 'attachment;filename="%s"' % os.path.basename(patch)
                message.attach(att)
                f.close()

        return self.sm.sendmail(self.from_email,
                                self.to_email,
                                message.as_string())

    def quit(self):
        self.sm.quit()

References:

Python Excel

Overview

http://www.python-excel.org/

openpyxl The recommended package for reading and writing Excel 2010 files (ie: .xlsx)

https://openpyxl.readthedocs.io/en/default/

xlwd This package is for reading data and formatting information from older Excel files (ie: .xls)

http://xlrd.readthedocs.io/en/latest/

xlwt This package is for writing data and formatting information to older Excel files (ie: .xls)

http://xlwt.readthedocs.io/en/latest/

openpyxl

Install: sudo pip install openpyxl

Workboot in Memory

Create new workbook:

from openpyxl import Workbook
wb = Workbook()

# Write-only mode
wb = Workbook(write_only=True)

Get the worksheet:

ws = wb.active  # Get the active sheet (The first by default)
ws = wb['Mysheet']  # Get the sheet by name

Change the worksheet name:

ws.title = "New Title"  #

Get all the sheet names:

print(wb.sheetnames)  # or

for sheet in wb:
    print(sheet.title)

Get the column letter:

from openpyxl.utils import get_column_letter
get_column_letter(1)  # 'A' for column 1

Create new worksheet:

ws1 = wb.create_sheet("Mysheet") # insert at the end (default)
ws2 = wb.create_sheet("Mysheet", 0) # insert at first position

Copy sheet within a single workbook:

source = wb.active
target = wb.copy_worksheet(source)

The background color of the tab holding this title is white by default. You can change this via the sheet_properties.tabColor property:

ws.sheet_properties.tabColor = "1072BA"  # RRGGBB

Access one cell:

c = ws['A1']
ws['A1'] = 'Name'
d = ws.cell(row=4, column=2)  # return cell, d.value contains the value
d = ws.cell(row=4, column=2, value=10)   # change/assign to new value

cell_range = ws['A1':'C2']  # cells from A1 to C2
colC = ws['C']              # The whole column
ow10 = ws[10]               # The whole row
col_range = ws['C:D']       # Two columns
row_range = ws[5:10]        # Two rows

# Cells in each rows
>>> for row in ws.iter_rows(min_row=1, max_col=3, max_row=2):
...    for cell in row:
...        print(cell)
<Cell Sheet1.A1>
<Cell Sheet1.B1>
<Cell Sheet1.C1>
<Cell Sheet1.A2>
<Cell Sheet1.B2>
<Cell Sheet1.C2>

# Cells in each columns
>>> for col in ws.iter_cols(min_row=1, max_col=3, max_row=2):
...     for cell in col:
...         print(cell)
<Cell Sheet1.A1>
<Cell Sheet1.A2>
<Cell Sheet1.B1>
<Cell Sheet1.B2>
<Cell Sheet1.C1>
<Cell Sheet1.C2>

# all cells in row
>>> tuple(ws.rows)
((<Cell Sheet.A1>, <Cell Sheet.B1>, <Cell Sheet.C1>),
(<Cell Sheet.A2>, <Cell Sheet.B2>, <Cell Sheet.C2>),
...)

>>> tuple(ws.columns)
((<Cell Sheet.A1>, <Cell Sheet.A2>, ...),
(<Cell Sheet.B1>, <Cell Sheet.B2>, ...),
(<Cell Sheet.C1>, <Cell Sheet.C2>, ...))

ws['A1'].row            # 1
ws['A1'].column         # 'A'
ws['A1'].coordinate     # 'A1'

Write-only cell:

from openpyxl.writer.write_only import WriteOnlyCell
from openpyxl.styles import Font
cell = WriteOnlyCell(ws, value="hello world")
cell.comment = Comment(text="A comment", author="Author's Name")
cell.font = Font(name='Courier', size=36)
ws.append([cell, 3.14, None])

Working with style:

See also: https://openpyxl.readthedocs.io/en/default/styles.html

Builtin styles: https://openpyxl.readthedocs.io/en/default/styles.html#using-builtin-styles

Merge/Unmerge cells:

ws.merge_cells('A1:B1')
ws.unmerge_cells('A1:B1')

ws.merge_cells(start_row=2,start_column=1,end_row=2,end_column=4)
ws.unmerge_cells(start_row=2,start_column=1,end_row=2,end_column=4)

Set the width of column:

ws.column_dimensions['A'].width = 16

Using formulae:

ws['D1'] = '=SUM(A1:C1)'

Using number format:

ws['A2'] = datetime.datetime(2010, 7, 21)
ws['A2'].number_format   # 'yyyy-mm-dd h:mm:ss'

ws['A2'].number_format   # 'General'
ws['A2'] = 0.12          # 0.12 when open by MS office
ws['A2'].number_format = '0%'
ws['A2'].value           # value still 0.12, but shown as 12%

Insert an image:

from openpyxl.drawing.image import Image
img = Image('logo.png')
ws.add_image(img, 'A1')

Adding a comment to a cell:

# One comment can only be assgined to one cell
from openpyxl.comments import Comment
ws["A1"].comment = Comment("Text", "Author")

Create a chart:

>>> for i in range(1, 11):
...     ws['A%d'%i] = i
>>> from openpyxl.chart import BarChart, Reference, Series
>>> values = Reference(ws, min_col=1, min_row=1, max_col=1, max_row=10)
>>> chart = BarChart()
>>> chart.add_data(values)
>>> ws.add_chart(chart, "E15")
>>> wb.save("SampleChart.xlsx")

See also: https://openpyxl.readthedocs.io/en/default/charts/introduction.html

Fold columns:

ws.column_dimensions.group('A','D', hidden=True)

Using filters and sorts:

ws.auto_filter.ref = "A1:B15"
ws.auto_filter.add_filter_column(0, ["Kiwi", "Apple", "Mango"])
ws.auto_filter.add_sort_condition("B2:B15")

Save to a file:

wb.save('myfile.xlsx')
Loading from a file
::
>>> from openpyxl import load_workbook
>>> wb2 = load_workbook('test.xlsx')
>>> print wb2.get_sheet_names()
['Sheet2', 'New Title', 'Sheet1']

# Read-only mode wb = load_workbook(filename=’large_file.xlsx’, read_only=True)

Python Performance and Debug

pdb

python -m pdb xxx.py

time

time.time() timeit /usr/bin/time –verbose python test.py

trace

https://docs.python.org/3/library/trace.html

The trace module allows you to trace program execution, generate annotated statement coverage listings, print caller/callee relationships and list functions executed during a program run. It can be used in another program or from the command line.

python -m trace –count -C . somefile.py

cProfile

https://docs.python.org/3/library/profile.html

python -m cProfile -s cumulative test.py

memory_profiler

pip install psutil memory_profiler

https://pypi.python.org/pypi/psutil#downloads https://pypi.python.org/pypi/memory_profiler/

# line by line python -m memory_profiler test.py

# timing sequence mprof run test.py #output to mprofile_xxxx.dat by default mprof plot mprofile_xxx.dat

line_profiler

https://pypi.python.org/pypi/line_profiler/ https://github.com/rkern/line_profiler

sudo pip install line_profiler

@profile
def show_function():
     ...

kernprof.py -l -v test.py

guppy

http://guppy-pe.sourceforge.net/

Install: sudo pip install guppy

Example:

from guppy import hpy

def random_sort3(n):
  hp = hpy()
  print "Heap at the beginning of the functionn", hp.heap()
  l = [random.random() for i in range(n)]
  l.sort()
  print "Heap at the end of the functionn", hp.heap()
  return l

if __name__ == "__main__":
  random_sort3(2000000)

#hp.heap().more.more  for more defails

Python Template Libraries

jinja2

from jinja2 import Environment, PackageLoader

def template_render(name, args):
    env = Environment(loader=PackageLoader('myApp', 'templates'))
    template = env.get_template(name)
    return template.render(args=args)

Python Internationalization

gettext

Define Messages by _() function:

"""test.py"""
import gettext

try:
    gettext.translation('myapp', localedir='locale', languages=['zh_CN']).install()
except:
    _ = lambda s: s

# ...
print(_('This is a translatable string.'))

Generate the pot file:

mkdir -p ./locale/zh_CN/LC_MESSAGES/
xgettext -o locale/zh_CN/LC_MESSAGES/myapp.pot ./test.py

Generate the po and mo files:

# edit po file via poedit tool.
sudo apt-get install poedit

# /usr/bin/poedit
# create new translation or edit exist po file.

# add/edit/save

Python Charts

Data format and libraries

csv: [Standard Library] csv json: [Standard Library] json excel: openpyxl database: sqlite3/pymongodb

Aligned binary data: [Standard Library] struct:

>>> import struct
>>> struct.unpack_from('5s10s', b'abcde 0123456789')
(b'abcde', b' 012345678')

matplotlib

Installation:

sudo apt-get install python-numpy python-matplotlib python-scipy
Overview

Path for matplotlibrc:

./matplotlibrc
~/.config/matplotlib   # get by matplotlib.get_configdir()
xxx/site-packages/matplotlib/mpl-data/matplotlibrc    # installation path

#matplotlib.matplotlib_fname() get the matplitlibrc file name in use.

set rc parameters:

import matplotlib as mpl
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['lines.color'] = 'r'

# call the rc() function
mpl.rc('lines', linewidth=2, color='r')
mpl.rcdefaults()
plot

Examples:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)

plt.rcParams['lines.linewidth'] = 2
plt.rcParams['lines.color'] = 'r'
plt.plot(x, np.sin(x))

plt.plot(x, np.cos(x), linewidth=3, color='g')

plt.title('Function $\sin$ and $\cos$')
plt.xlim(-np.pi, np.pi)
plt.xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],
           [r'$-\pi$', r'$-\pi$', r'$0$', r'$+\pi/2$', r'$+\pi$',])
#plt.grid()
plt.show()
date index

Examples:

import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

start = datetime.datetime(2016, 10, 1)
stop  = datetime.datetime(2016, 10, 8)
delta = datetime.timedelta(days=1)
dates = mdates.drange(start, stop, delta)

values = np.random.rand(len(dates))

fig, ax = plt.subplots()
ax.plot_date(dates, values, linestyle='-')

date_format = mdates.DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(date_format)

fig.autofmt_xdate()

plt.show()
pie

Examples:

import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

labels = ['项目1', '项目2', '项目3', '项目4']
fracs = [60, 25, 5, 10]
explode = (0.01, 0, 0, 0)
pathes, texts, autotexts = plt.pie(fracs, labels=labels, explode=explode, counterclock=False,
                                   startangle=90, autopct='%3.1f%%', radius=0.5)

# Make the labels on the small plot easier to read.
font_zh = FontProperties(fname='/usr/share/fonts/truetype/arphic/uming.ttc')
for t in texts:
    t.set_size('smaller')
    t.set_fontproperties(font_zh)  # show labels in zh_CN
for t in autotexts:
    t.set_size('x-small')
autotexts[0].set_color('y')

plt.axis('equal')   # change ellipse to standard circle
plt.show()          # show in tkinter window

# save figure (eps, pdf, pgf, png, ps, raw, rgba, svg, svgz)
fig = plt.gcf()
fig.set_size_inches(6.4, 6.4)
fig.savefig('test2png.png', dpi=100)
fig.savefig('/tmp/test.png')
scatter

Examples:

x = [1, 2, 3, 4]
y = [5, 4, 3, 2]
plt.scatter(x, y)
bar

Examples:

plt.bar(x, y)
horizontal bar

Examples:

plt.barh(x, y)
stacked bar

Examples:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

font_zh = FontProperties(fname='/usr/share/fonts/truetype/arphic/uming.ttc')

N = 5
means_1 = (20, 35, 30, 35, 27)
means_2 = (25, 32, 34, 20, 25)
means_3 = (1, 3, 4, 2 ,4)

bottom_2 = means_1
bottom_3 = [i + j for i, j in zip(means_1, means_2)]

ind = np.arange(N)    # the x locations for the groups
width = 0.9           # the width of the bars: can also be len(x) sequence

p1 = plt.bar(ind, means_1, width, color='#d62728')
p2 = plt.bar(ind, means_2, width, color='#10e010', bottom=bottom_2)
p3 = plt.bar(ind, means_3, width, color='#1111e1', bottom=bottom_3)

plt.ylabel('Values')
plt.title('This Is The Title')
plt.xlabel('范围', fontproperties=font_zh)
plt.ylabel('项目1 -- 项目2 -- 项目3', fontproperties=font_zh)
plt.xticks(ind, ('X1', 'X2', 'X3', 'X4', 'X5'), fontproperties=font_zh)
plt.yticks(np.arange(0, 81, 10))
#plt.legend((p1[0], p2[0], p3[0]), ('Item1', 'Item2', 'Item3'))

plt.show()
layout

Examples:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 1.0, 0.01)

plt.subplot(121)
plt.plot(t, np.sin(2 * np.pi * t))

plt.subplot(122)
plt.plot(t, np.cos(2 * np.pi * t))

plt.show()

Python Data Analysis

Installations

Canopy(epdfree)

http://www.enthought.com

sudo bash ./canopy-1.7.4-rh5-64.sh
# Agree on the license and select installation directory

# start
/home/jxiao1/Canopy/canopy
ipython
sudo apt-get install ipython ipython-notebook

# start
ipython
ipython noteboot --pylab=inline

numpy

Overview

NumPy’s main object is the homogeneous multidimensional array(class ndarray). It is a table of elements (usually numbers), all of the same type, indexed by a tuple of positive integers. In Numpy dimensions are called axes. The number of axes is rank.

In the below example below, the array has rank 2 (it is 2-dimensional). The first dimension (axis) has a length of 2, the second dimension has a length of 3.

::
[[ 1., 0., 0.],
[ 0., 1., 2.]]
Create ndarray

Examples:

import numpy as np
a = np.arange(15).reshape(3, 5)     # arange(0, 15, 1)
b = np.linspace(0, 2, 9)            # 9 numbers from 0 to 2.0, including 2.0
c = np.random.random((2,3))         # 2 X 3 array

a = np.array([2,3,4])
b = np.array([(1.5,2,3), (4,5,6)])

np.empty((2,3))                     # value is not initialized, what in memory.
np.zeros((3,4))                     # value is initialized to '0'
np.ones((2,3,4), dtype=np.int16)    # value is initialized to '1'
np.eye(4)                           # 4x4 array I

f= lambda x, y: 10*x+y
np.fromfunction(f,(5,4),dtype=int)
Out[176]:
array([[ 0,  1,  2,  3],
       [10, 11, 12, 13],
       [20, 21, 22, 23],
       [30, 31, 32, 33],
       [40, 41, 42, 43]])

Note

reshape and slice only return new view of the array, but not copied the data. change the new view will change the sharing data buffer. If you want to copy data, copy() is required. d = a.copy()

Data types

https://docs.scipy.org/doc/numpy-1.10.1/user/basics.types.html

dtype is np.float64 in most cases by default.

============= ============== =======================================================================
Data type     Character Code Description
============= ============== =======================================================================
object        O              Python Object
string_       SN             String with fixed length of N, e.g. S10
unicode_      UN             Unicode with fixed length of N, e.g. U10
bool_         ?              Boolean (True or False) stored as a byte
int8          i1             Byte (-128 to 127)
int16         i2             Integer (-32768 to 32767)
int32         i4             Integer (-2147483648 to 2147483647)
int64         i8             Integer (-9223372036854775808 to 9223372036854775807)
uint8         u1             Unsigned integer (0 to 255)
uint16        u2             Unsigned integer (0 to 65535)
uint32        u4             Unsigned integer (0 to 4294967295)
uint64        u8             Unsigned integer (0 to 18446744073709551615)
float16       f2             Half precision float: sign bit, 5 bits exponent, 10 bits mantissa
float32       f4/f           Single precision float: sign bit, 8 bits exponent, 23 bits mantissa
float64       f8/d           Double precision float: sign bit, 11 bits exponent, 52 bits mantissa
float128      f16/d          Extend double precision float.
complex64     c8             Complex number, represented by two 32-bit floats (real and imaginary)
complex128    c16            Complex number, represented by two 64-bit floats (real and imaginary)
complex256    c32            Represented by two 128-bit floats (real and imaginary components)
============= ============== =======================================================================

Examples:

a = np.array([1.0, 2, 3])                   # dtype('float64')
a = np.array([1.0, 2, 3], dtype=np.int32)   # dtyoe('int32')
a = a.astype(np.int64)                      # dtype('int64')
a.astype(int).dtype                         # dtype('int64'),  convert pythyon type to numpy type.
a.astype('f').dtype                         # dtype('float32'), use the character codes
Array Operations

basic:

a = np.array( [20,30,40,50] )
b = np.arange( 4 )
c = a-b
b**2
b > 10                              # return the dtype=bool array
b += a
a *= 3

index:

a = np.array(12).reshape(4, 3)
a[0][0]                             # the element at raw 0 column 0
a[1:3]                              # raw from 1 to 3 (not included)
a[::-1]                             # raw in inverted sequence
a[1]                                # the second raw
a[-1]                               # the last raw
a[:, 1]                             # column 1 in each raw
a[1:3, [1, 2]]                      # column 1, 2 in raw 1, 2
a[1:5:2, ::3]                       # 1:5:2 for raw and ::3 for column

x = np.arange(10,1,-1)
x[np.array([3, 3, 1, 8])]           # array([7, 7, 9, 2])

a_idx = np.array([1, 2, 1])
a[a_idx]                            # select item at index 1, 2 ,1
a_idx = np.array([[1, 3], [2, 4]])
a[a_idx]                            # new array ([[a[1], a[3]], [a[2], a[4]])

y = np.arange(35).reshape(5,7)
y[np.array([0,2,4])]                        # array([[ 0,  1,  2,  3,  4,  5,  6],
                                                     [14, 15, 16, 17, 18, 19, 20],
                                                     [28, 29, 30, 31, 32, 33, 34]])
y[np.array([0,2,4]), np.array([0,1,2])]     # array([ 0, 15, 30])
y[[0,2,4]][:, [0,1,2]]                      # array([[ 0,  1,  2],
                                                     [14, 15, 16],
                                                     [28, 29, 30]])

y[y>20]     # array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34])
y[np.array([False, False, False,  True,  True])]  # the raws 3 and 4, which is true

y[y<10] = 10   # set all elements which are little than 10 to 10

x = np.arange(30).reshape(2,3,5)
b = np.array([[True, True, False], [False, True, True]])
x[b]                                        # raw 0, 1 in x[0], raw 1, 2 in x[1], total 4x5

y[np.array([0,2,4]),1:3]                    # raw 0, 2, 4 column 1~2

newaxis:

x = np.arange(5)
xx = x[:,np.newaxis]                # 5x1 array([[0],[1],[2],[3],[4]])
xy = x[np.newaxis, :]               # 1x5 array([[0, 1, 2, 3, 4]])
xx + xy                             # 5x5

functions:

#a.ufunc or np.ufunc(a)
abs
fabs
sqrt
square
exp
log/log10/log2
sign                                # return 1 (>0), 0(=0), -1(<0)
ceil                                # min integer that >= e for e in elements in a
floor                               # max integer that <= e for e in elements in a
rint
modf
isnan
isfinite
isinf
cos/sin
tan
logical_not

#np.ufunc(a, b)
add
subtract
multiply
divide/floor_divide
power
maximum, fmax
minimum, fmin
mod
copysign
greater/greater_equal
less/less_equal
equal/not_equal
logical_and/logical_or
logical_xor

# functions for bool
any()
all()

# functions for set
unique(x)
intersect1d(x, y)                   # in both x and y
union1d(x, y)                       # in x or y
in1d(x, y)                          # bool arrary than x[i] in y
setdiff1d(x, y)                     # in x and not in y
setxor1d(x, y)                      # only in x or only in y

#function for statistics
a.sum()                             # sum of all values
a.sum(axis=0)                       # sum of each axis
a.min()
a.max()
a.mean()                            # average
a.std()
a.argmin()                          # index of min
a.argmax()                          # index of max
a.cumsum()                          # 累计和
a.cumprod()                         # 累计积

# examples
(a > 0).sum()                       # number of element which is greater than 0
np.add(a, b)

for row in b:
for element in b.flat:
list(b.flat)

a = np.floor(10*np.random.random((3,4)))
a.ravel()
a.reshape(6,-1)     # -1 means automaticall get 12/6 =2
b1 = np.array([False,True,True])
a[b1,:]             # a[b1], show second and third raws which is True

a = np.floor(10*np.random.random((2,12)))
np.hsplit(a,3)   # Split a into 3
np.hsplit(a,(3,4))   # Split a after the third and the fourth column

x = np.arange(0,10,2)                     # x=([0,2,4,6,8])
y = np.arange(5)                          # y=([0,1,2,3,4])
m = np.vstack([x,y])                      # m=([[0,2,4,6,8],
                                          #     [0,1,2,3,4]])
xy = np.hstack([x,y])                     # xy =([0,2,4,6,8,0,1,2,3,4])

b = np.sort(a)
Data input and output

https://docs.scipy.org/doc/numpy-1.10.1/reference/routines.io.html

np.save('filename.npy', a)               # save array a as filename.npy dat file
a = np.load('filename.npy')              # load filename.npy to array a

np.savez('filename.npz', a=arr_a, b=arr_b)  # save array arr_a and arr_b in one file as filename.npz
arch = np.load('filename.npy')              # load filename.npz to dictionary {'a': arr_a, 'b': arr_b}

np.savetxt('filename.txt', a, fmt='%4d', delimiter=' ', newline='\n', header='', footer='')
a = np.loadtxt('filename.txt', delimiter=',')
Random sampling

https://docs.scipy.org/doc/numpy-dev/reference/routines.random.html https://docs.scipy.org/doc/numpy-1.10.1/reference/routines.random.html#simple-random-data

Examples:

np.random.rand(10)                          # 10 samples in [0, 1)
np.random.rand(2, 4)                        # 2 X 4 array, values in [0,1)
np.random.randn(2, 4)                         # Return samples from “standard normal” distribution.
np.random.randint(0, 10, 10)                # int in [0, 10)
np.random.random_integers(0, 10, 10)        # int in [0, 10]
np.random.random(10)                        # floats in [0.0, 1.0)
np.random.choice([1, 2, 3, 4], 10)          # 10 samples in the give array [1, 2, 3, 4]

pandas

http://pandas.pydata.org/pandas-docs/stable/index.html

Data Structures

http://pandas.pydata.org/pandas-docs/stable/dsintro.html

Series

Series is similar as the dictionary, but support more operations.

Example:

# the common import way
import numpy as np
import pandas as pd
from pandas import Series, DataFrame

pd.Series(np.random.randn(5))
pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])

pd.Series({'a' : 0., 'b' : 1., 'c' : 2.})
pd.Series(5, index=['a', 'b', 'c', 'd', 'e'])

# like a ndarray
s = pd.Series({'a' : 0., 'b' : 1., 'c' : 2.})
s[0]                # 0.0
s[1:]               # slice from 1 to end, 'b' and 'c' are left

s[s > s.median()]   # equal to s[[False, False, True]], only 'c' is left

s[[0, 0, 1]]        # select 'a', 'a', 'b'
s[[2, 1]]           # select 'c' and 'b'

# like a dictionary
s['a']              # 0.0
s.get('e', np.nan)  # support get function too.

np.square(s)        # square for each
s * 2               # i * 2 for i in s

s.name = 'something'
s.rename('otherthing')

DataFrame

DataFrame is a 2-dimensional labeled data structure with columns of potentially different types. You can think of it like a spreadsheet or SQL table, or a dict of Series objects. It is generally the most commonly used pandas object. Like Series, DataFrame accepts many different kinds of input:

  • Dict of 1D ndarrays, lists, dicts, or Series
  • 2-D numpy.ndarray
  • Structured or record ndarray
  • A Series
  • Another DataFrame

Examples:

# From dictionary of lists
#---------------------------------------------------------------------------
d = {'Column1': [1, 2, 3, 4],
     'Column2': [1., 2., 3., 4.]}
pd.DataFrame(d, index=['a', 'b', 'c', 'd'])

Out[51]:
      Column1  Column2
   a        1      1.0
   b        2      2.0
   c        3      3.0
   d        4      4.0

pd.DataFrame({'a' : [1, 0, 1], 'b' : [0, 1, 1] }, dtype=bool)
Out[74]:
          a      b
   0   True  False
   1  False   True
   2   True   True

# From ndarrays
#---------------------------------------------------------------------------
dates = pd.date_range('2013-01-01', periods=3)
pd.DataFrame(np.random.randn(3,2), index=dates, columns=list('AB'))
Out[63]:
                   A         B
2013-01-01  1.017122 -0.509179
2013-01-02 -0.165409 -0.185033
2013-01-03 -0.108724 -0.775507

# From dictionary for series
#---------------------------------------------------------------------------
d = {'Column1': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
     'Column2': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
pd.DataFrame(d)

# Select part of the data, and indexs
pd.DataFrame(d, index=['c', 'b', 'a'], columns=['Column1', 'Column3'])
Out[47]:
      Column1 Column3
   c      3.0     NaN
   b      2.0     NaN
   a      1.0     NaN


# From dict of objects that can be converted to series-like.
#---------------------------------------------------------------------------
In [10]: df2 = pd.DataFrame({ 'A' : 1.,
....:                      'B' : pd.Timestamp('20130102'),
....:                      'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
....:                      'D' : np.array([3] * 4,dtype='int32'),
....:                      'E' : pd.Categorical(["test","train","test","train"]),
....:                      'F' : 'foo' })
....:

In [11]: df2
Out[11]:
     A          B    C  D      E    F
0  1.0 2013-01-02  1.0  3   test  foo
1  1.0 2013-01-02  1.0  3  train  foo
2  1.0 2013-01-02  1.0  3   test  foo
3  1.0 2013-01-02  1.0  3  train  foo

#From structured or record array
#---------------------------------------------------------------------------
data = np.zeros((2,), dtype=[('A', 'i4'),('B', 'f4'),('C', 'a10')])
data[:] = [(1,2.,'Hello'), (2,3.,"World")]

pd.DataFrame(data)
Out[44]:
      A    B      C
   0  1  2.0  Hello
   1  2  3.0  World

pd.DataFrame(data, index=['first', 'second'])
Out[45]:
           A    B      C
   first   1  2.0  Hello
   second  2  3.0  World

pd.DataFrame(data, columns=['C', 'A'])
Out[46]:
          C  A
   0  Hello  1
   1  World  2

pd.DataFrame.from_records(data, index='C')
Out[53]:
          A    B
   C
   Hello  1  2.0
   World  2  3.0

#From a list of dicts
#---------------------------------------------------------------------------
data2 = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]

pd.DataFrame(data2, index=['R1', 'R2'])
Out[48]:
       a   b     c
   R1  1   2   NaN
   R2  5  10  20.0
Series Operations

Examples:

s1 = pd.Series(np.random.randn(4))
s1[s1>0]

s1 * 2
s1 + 5

s1.index
s1.values

s2 = pd.Series(s1.values,index=['norm_'+ str(i) for i in xrange(4)])
s2['norm_1':'norm_3']       # raws from 'norm_1' to 'norm_3' (included)
s2[['norm_1','norm_3']]     # raws 'norm_1' and 'norm_3'

data = pd.Series([1, 2.1, np.nan, None, '', 0])
data.isnull()       # only np.nan and None is null.
DataFrame Operations

Indexing/Selection:

df['A']
df[['A', 'B']]
df[0:3]

df.loc['bar':'kar']
df.loc['2013-01-03', 'A']
df.loc['2013-01-03':'2013-01-06', ['A', 'B']]

df.iloc[1,1]
df.iloc[3:5,0:2]
df.iloc[[1,2,4],[0,2]]
df.iloc[:,1:3]

df.ix('2013-01-03', 'A')
df.at[dates[0],'A']
df.iat[1,1]

df[df.A > 0]
df.loc[(df.A > 0) & (df.C >0), 'B']

crit1 = df.A > 0
crit2 = df.B > 0
crit3 = df.C > 0
crit = crit1 & crit2 & crit3
df[crit]

df[~((df.A <= 6) & (df.index.isin([0,2,4])))]  # ~ means not
Operation Syntax Result
Select column df[‘col’]/df.col Series
Select row by label df.loc[label] Series
Select row by integer location df.iloc[loc] Series
Slice rows df[5:10] DataFrame
Select Columns df[[‘A’, ‘B’]] DataFrame
Select rows by boolean vector df[bool_vec] DataFrame

Deletion:

del df['Column1']

Addtion:

df['Status'] = 'ready'  # Set the whole new column 'Status' to 'ready'

df['ColumnN'] = df['Column1'] * df['Column2']
df['ColumnN'] = df['Status'] == 'ready'

df.insert(1, 'Column1-copy', df['Column1'])

Copy:

df2 = df.copy()

Data view:

df.index
df.columns
df.values

df.head(2)  # first 5 by default
df.tail(3)  # last 5 by default

df.describe()  # Quick statistic summary of your data

df.sort_index(axis=1, ascending=False)
df.sort_values(by='B')

Missing Data

df1.dropna(how=’all’, axis=1) df1.fillna(value=5, inplace=True) df1.fillna({1:10, 2:20}) # 10 for column 1 and 20 for column 2 pd.isnull(df1) pd.notnull(df1)

Data alignment and arithmetic:

df - df.iloc[0]
df.sub(df.iloc[0], axis=1)

df.sub(df['A'], axis=0)

df*5 + 2

df.T

np.square(df)

Join:

pd.merge(df1, df2, on='key_index')

Concat:

pd.concat(list_of_dfs)

Append:

pd.append(df, df.iloc[3], ignore_index=True)  # Generate new index

Group:

df.groupby('A').sum()

Sort:

df.sort_values(by='A')

if/then:

df.ix[df.A >= 0,'B'] = True; df

df_mask = pd.DataFrame({'A' : [True] * 4, 'B' : [False] * 4,'C' : [True,False] * 2})
df.where(df_mask, 1000)   # Set all 'False' to the value 1000

# add new column 'result' to show status of value 'A', 'high' if >5, otherwise 'low'.
df['result'] = np.where(df['A'] > 5,'high','low'); df
Plot in Pandas

Both Series and DataFrame support plot function.

Examples:

ts = pd.Series(np.random.randn(10, index=pd.date_range('1/1/2000', periods=10))
ts1.cumsum()  # the sum of all previous values
ts1.plot()

df = pd.DataFrame(np.random.randn(10, 4), index=ts.index, columns=['A', 'B', 'C', 'D'])
df1 = df.cumsum()
pf = plt.figure()
pf.legend(loc='best')
df.plot()
df1.plot(kind='bar')
Data import and export

csv:

pd.read_csv('foo.csv')
df.to_csv('foo.csv')

excel:

pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])
df.to_excel('foo.xlsx', sheet_name='Sheet1')

binary file:

# offsets are larger than the size of the type because of struct padding
names = 'count', 'avg', 'scale'
formats = 'i4', 'f8', 'f4'
offsets = 0, 8, 16

dt = np.dtype({'names': names, 'offsets': offsets, 'formats': formats}, align=True)
df = pd.DataFrame(np.fromfile('binary.dat', dt))

Python GUI

Phoenix(wxPython)

Phoenix is the code name of for the new version of wxPython, which runs on the python3.

colorama

Cross-platform colored terminal text: - https://pypi.python.org/pypi/colorama - https://github.com/tartley/colorama

Python Differences Between Versions

Mainly about the differences between Python2.7 and Python3.5

  1. Rename raw_input() to input(), and always return string。Remove original input()
  2. Rename xrange() to range(), and remove original range()
  3. ‘a/b’ return integer in python2, but float in python3 by default.

Flask Beginner

Installation

http://flask.pocoo.org/docs/0.10/installation/#installation

virtualenv:

Virtualenv enables multiple side-by-side installations of Python, one for each project. It doesn’t actually install separate copies of Python, but it does provide a clever way to keep different project environments isolated.

$ sudo easy_install virtualenv

Or even better:

$ sudo pip install virtualenv

Maybe it’s even in your package manager. If you use Ubuntu, try:

$ sudo apt-get install python-virtualenv

Once you have virtualenv installed, just fire up a shell and create your own environment:

$ mkdir myproject
$ cd myproject
$ virtualenv [--python=python3] venv  # default is python2

Now, whenever you want to work on a project, you only have to activate the corresponding environment:

$ . venv/bin/activate or $ source venv/bin/activate

After all, if you want to exit the virtualenv:

(venv) $ deactivate

flask:

Now you can just enter the following command to get Flask activated in your virtualenv:

(venv) $ pip install flask jinja2 werkzeug

Any time, you can generate the required packages list like this:

(venv) $ pip freeze > ./requirements.txt

And set up the same virtual environment in other place list this:

(venv) $ pip install -r requirements.txt

Quickstart

http://flask.pocoo.org/docs/0.10/quickstart/#quickstart

A minimal Flask application looks something like this:

Create hello.py:

from flask import Flask
app = Flask(__name__)

@app.route('/user/<name>')
def hello(name):
    return 'Hello %s!' % name

if __name__ == '__main__':
    # Listen any client host
    # Never use debug mode in product project
    app.run(host='0.0.0.0', debug=True)

Note

If you enable debug support the server will reload itself on code changes, and it will also provide you with a helpful debugger if things go wrong. Because of security risk, never use debug mode on production machines.

Start the service:

$ python hello.py >/dev/null 2>&1 &

Now head over to http://127.0.0.1:5000/user/flask, and you should see your ‘hello flask!’ greeting. Or in command line mode:

$ curl -i http://127.0.0.1:5000/user/flask

Books

Flask Web Development: Developing Web Application with Python

Author: Miguel Grinberg github: https://github.com/miguelgrinberg Example source code: https://github.com/miguelgrinberg/flasky Blog: http://blog.miguelgrinberg.com

Flask Routing

@app.route('/')
def index(): pass

@app.route('/hello')
def hello(): pass

Variable in the URL

<variable_name> or <converter:variable_name>

Converters Description
string accepts any text without a slash (the default)
int accepts integers
float like int but for floating point values
path like the default but also accepts slashes
@app.route('/user/<username>')
def show_user_profile(username): pass

@app.route('/post/<int:post_id>')
def show_post(post_id): pass

# Support variable and also default value
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None): pass

@app.route('/<name>/test/<age>')
def user(name, age):
    return '<h1>Hello %s, age is %s!</h1>' %(name, age)

Trailing slash in the URL

Flask’s URL rules are based on Werkzeug’s routing module.

# '/projects' is redirected to '/projects/'
@app.route('/projects/')
def projects(): pass

# '/about/' will result in 404 error
@app.route('/about')
def about(): pass

URL Building

To build a URL to a specific function you can use the url_for() function. It accepts the name of the function as first argument and a number of keyword arguments, each corresponding to the variable part of the URL rule. Unknown variable parts are appended to the URL as query parameters.

Here are some examples:

from flask import Flask, url_for
app = Flask(__name__)

@app.route('/')
def index(): pass

@app.route('/login')
def login(): pass

@app.route('/user/<username>')
def profile(username): pass

with app.test_request_context():
    print url_for('index')
    print url_for('index', _external=True)
    print url_for('login')
    print url_for('login', next='/')
    print url_for('profile', username='John Doe')

The result:

/
http://localhost:5000/
/login
/login?next=/
/user/John%20Doe

Note

The_request_context() method tells Flask to behave as though it is handling a request, even though we are interacting with it through a Python shell. (see also: http://flask.pocoo.org/docs/0.10/quickstart/#context-locals).

HTTP Methods

By default, a route only answers to GET requests, but that can be changed by providing the methods argument to the route() decorator.

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        do_the_login()
    else:
        show_the_login_form()

Static files

Dynamic web applications also need static files. That’s usually where the CSS and JavaScript files are coming from. Ideally your web server is configured to serve them for you, but during development Flask can do that as well. Just create a folder called static in your package or next to your module and it will be available at /static on the application.

As static is the default routing function created when app is initialized. To generate URLs for static files, use the special ‘static’ endpoint name:

url_for('static', filename='style.css')

The file has to be stored on the filesystem as static/style.css.

Redirects

To redirect a user to another endpoint, use the redirect() function; to abort a request early with an error code, use the abort() function:

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

Error Pages

By default a black and white error page is shown for each error code. You can use the errorhandler() decorator to customize the error page:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

Note

The 404 after the render_template() call. This tells Flask that the status code of that page should be 404 which means not found. By default 200 is assumed which translates to: all went well.

Flask Bluepoint

A Blueprint object works similarly to a Flask application object, but it is not actually an application. It is a set of operations which can be registered on an application, even multiple times. We can group views and resources in many subclass blueprint and flexibly register them to application later.

Basic example

from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound

simple_page = Blueprint('simple_page', __name__,
                        template_folder='templates')

@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
    try:
        return render_template('pages/%s.html' % page)
    except TemplateNotFound:
        abort(404)

Registering Blueprints

from flask import Flask
from yourapplication.simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page)

If you check the rules registered on the application, you will find these:

[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/' (HEAD, OPTIONS, GET) -> simple_page.show>]

Blueprints however can also be mounted at different locations:

app.register_blueprint(simple_page, url_prefix='/pages')

And sure enough, these are the generated rules:

[<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>,
 <Rule '/pages/<page>' (HEAD, OPTIONS, GET) -> simple_page.show>,
 <Rule '/pages/' (HEAD, OPTIONS, GET) -> simple_page.show>]

On top of that you can register blueprints multiple times though not every blueprint might respond properly to that. In fact it depends on how the blueprint is implemented if it can be mounted more than once.

Blueprint Resources

Sometimes you might want to introduce a blueprint only for the resources.

Like for regular applications, blueprints are considered to be contained in a folder. While multiple blueprints can originate from the same folder, it does not have to be the case and it’s usually not recommended.

The folder is inferred from the second argument to Blueprint which is usually __name__. This argument specifies what logical Python module or package corresponds to the blueprint. If it points to an actual Python package that package (which is a folder on the filesystem) is the resource folder. If it’s a module, the package the module is contained in will be the resource folder. The Blueprint.root_path property show what the resource folder is:

>>> simple_page.root_path
'/Users/username/TestProject/yourapplication'

To quickly open sources from this folder you can use the open_resource() function:

with simple_page.open_resource('static/style.css') as f:
    code = f.read()

Static Files

A blueprint can expose a folder with static files by providing a path to a folder on the filesystem via the static_folder keyword argument. It can either be an absolute path or one relative to the folder of the blueprint:

admin = Blueprint('admin', __name__, static_folder='static')

By default the rightmost part of the path is where it is exposed on the web. Because the folder is called static here it will be available at the location of the blueprint + /static. Say the blueprint is registered for /admin the static folder will be at /admin/static.

The endpoint is named blueprint_name.static so you can generate URLs to it like you would do to the static folder of the application:

url_for('admin.static', filename='style.css')

Templates

If you want the blueprint to expose templates you can do that by providing the template_folder parameter to the Blueprint constructor:

admin = Blueprint('admin', __name__, template_folder='templates')

As for static files, the path can be absolute or relative to the blueprint resource folder. The template folder is added to the searchpath of templates but with a lower priority than the actual application’s template folder. That way you can easily override templates that a blueprint provides in the actual application.

So if you have a blueprint in the folder yourapplication/admin and you want to render the template ‘admin/index.html’ and you have provided templates as a template_folder you will have to create a file like this: yourapplication/admin/templates/admin/index.html.

Building URLs

If you want to link from one page to another you can use the url_for() function just like you normally would do just that you prefix the URL endpoint with the name of the blueprint and a dot (.):

url_for('admin.index')

Additionally if you are in a view function of a blueprint or a rendered template and you want to link to another endpoint of the same blueprint, you can use relative redirects by prefixing the endpoint with a dot only:

url_for('.index')

This will link to admin.index for instance in case the current request was dispatched to any other admin blueprint endpoint.

Flask Templates

Generating HTML from within Python is not fun, and actually pretty cumbersome because you have to do the HTML escaping on your own to keep the application secure. Because of that Flask configures the Jinja2 template engine for you.

http://jinja.pocoo.org/docs/dev/

Rendering Templates

To render a template you can use the render_template() method. All you have to do is provide the name of the template and the variables you want to pass to the template engine as keyword arguments.

Here’s a simple example of how to render a template:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask will look for templates in the templates folder. So if your application is a module, this folder is next to that module, if it’s a package, it’s actually inside your package:

Case 1: a module:

/application.py
/templates
    /hello.html

Case 2: a package:

/application
    /__init__.py
    /templates
            /hello.html

Example of the template:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}

Note

Inside templates you also have access to the request, session and g objects as well as the get_flashed_messages() function.

Automatic escaping is enabled, so if name contains HTML it will be escaped automatically. If you can trust a variable and you know that it will be safe HTML you can mark it as safe by using the Markup class or by using the safe filter in the template.

Global Variables within templates

The following global variables are available within Jinja2 templates by default.

config:

The current configuration object (flask.config) This is now always available, even in imported templates.

request:

The current request object (flask.request). This variable is unavailable if the template was rendered without an active request context.

session:

The current session object (flask.session). This variable is unavailable if the template was rendered without an active request context.

g:

The request-bound object for global variables (flask.g). This variable is unavailable if the template was rendered without an active request context.

url_for():

The flask.url_for() function.

get_flashed_messages()

The flask.get_flashed_messages() function.

Context Processors

To inject new variables automatically into the context of a template, context processors exist in Flask. Context processors run before the template is rendered and have the ability to inject new values into the template context. A context processor is a function that returns a dictionary. The keys and values of this dictionary are then merged with the template context, for all templates in the app:

@app.context_processor
def inject_user():
    return dict(user=g.user)

The context processor above makes a variable called user available in the template with the value of g.user. This example is not very interesting because g is available in templates anyways, but it gives an idea how this works.

Variables are not limited to values; a context processor can also make functions available to templates:

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

The context processor above makes the format_price function available to all templates:

{{ format_price(0.33) }}

You could also build format_price as a template filter, but this demonstrates how to pass functions in a context processor.

Syntax of Jinja templates

http://jinja.pocoo.org/docs/dev/templates/

The default Jinja delimiters are configured as follows:

  • {% … %} for Statements
  • {{ … }} for Expressions to print to the template output
  • {# … #} for Comments not included in the template output
  • # … ## for Line Statements

Examples:

{# join string and variable value to one string  #}
{{ "Hello " ~ name ~ "!" }}
Filters

http://jinja.pocoo.org/docs/dev/templates/#builtin-filters

Variables can be modified by filters. Filters are separated from the variable by a pipe symbol (|) and may have optional arguments in parentheses. Multiple filters can be chained. The output of one filter is applied to the next.

For example, {{ name|striptags|title }} will remove all HTML Tags from variable name and title-case the output (title(striptags(name))).

Filters that accept arguments have parentheses around the arguments, just like a function call. For example: {{ listx|join(', ') }} will join a list with commas (str.join(‘, ‘, listx)).

If you want to register your own filters in Jinja2 you have two ways to do that. You can either put them by hand into the jinja_env.filter of the application:

def reverse_filter(s):
    return s[::-1]
    app.jinja_env.filters['reverse'] = reverse_filter

Or use the template_filter() decorator:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

List of Popular Builtin Filters:

Filter Name Description
abs Return the absolute value of the argument.
capitalize The first character will be uppercase, all others lowercase
title Return a titlecased version of the value.
lower Convert a value to lowercase.
upper Convert a value to uppercase.
indent Return a copy of string each line indented by 4 spaces.
center Centers the value in a field of a given width.
trim Strip leading and trailing whitespace.
wordwrap Wrap string, line length is 79 characters by default.
default If the value is undefined it will return the default value.
dictsort Sort a dict and yeild (key, value) pairs. (‘for xx in xx’)
escape Convert &, <, >, ‘, and ” in string to HTML-safe sequences.
filesizeformat Format the value like a ‘human-readable’ file size (13 kB).
first Return the first item of a sequence.
last Return the last item of a sequence.
random Return a random item from the sequence.
format {{ "%s - %s"|format("Hello?", "Foo!") }}
groupby Group items in dict with the same value to a specified key.
int Convert the value into an integer.
float Convert the value into a floating point number.
list Convert the value into a list.
string Make a string unicode if it isn’t already.
join Return the concatenation of the strings in the sequence.
length Return the number of items of a sequence or mapping.
wordcount Count the words in that string.
map() Filte on a sequence of objects or looks up an attribute.
pprint Pretty print a variable. Useful for debugging.
select Filters a sequence of objects. {{ numbers|select(“odd”) }}
selectattr Filters a sequence of objects by attribute.
reject Filters a sequence, {{ numbers|reject(“odd”) }}
rejectattr Filters a sequence/objects by applying test to an attribute
replace Return a copy of the value after replaced old by new.
reverse Reverse the object.
round Round a given precision. {{ 42.55|round}} ->43.0
safe Safe means this variable will not be escaped.
striptags Strip XML tags and replace adjacent whitespace by one space
slice Slice an iterator
sort Sort an iterable.
sum {{ items|sum(attribute='price') }}
truncate {{ "foo bar baz"|truncate(9, True) }} -> “foo ba…”
urlencode Escape strings for use in URLs (uses UTF-8 encoding).
urlize Converts URLs in plain text into clickable links.
xmlattr Create an XML attribute string based on the items in a dict
Tests
{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

{% if foo.expression is equalto 42 %}
    the foo attribute evaluates to the constant 42
{% endif %}

{{ users|selectattr("email", "equalto", "foo@bar.invalid") }}

List of Builtin Tests

Test Name Description
callable Return whether the object is callable (has __call__ method)
defined Return true if the variable is defined.
undefined Like defined() but the other way round.
divisibleby Check if a variable is divisible by the specified number.
iterable Check if it’s possible to iterate over an object.
escaped Check if the value is escaped.
equalto Check if an object has the same value as another object.
sameas Check if the objects points to the same memory address
odd Return true if the variable is odd.
even Return true if the variable is even.
lower Return true if the variable is lowercased.
upper Return true if the variable is uppercased.
mapping Return true if the object is a mapping (dict etc.).
none Return true if the variable is none.
number Return true if the variable is a number.
sequence Return true if the variable is a sequence.
string Return true if the object is a string.
Template Inheritance

extends:

{% extends "layout/default.html" %}
{% extends layout_template if layout_template is defined else 'master.html' %}

include:

{% include 'header.html' %}
Body
{% include 'footer.html' %}

{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
{% include ['page_detailed.html', 'page.html'] %}
{% include ['special_sidebar.html', 'sidebar.html'] ignore missing %}

import:

Imagine we have a helper module that renders forms (called forms.html):

{% macro input(name, value='', type='text') -%}
    <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}

{%- macro textarea(name, value='', rows=10, cols=40) -%}
    <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols
        }}">{{ value|e }}</textarea>
{%- endmacro %}

The easiest and most flexible way to access a template’s variables and macros is to import the whole template module into a variable:

{% import 'forms.html' as forms %}
<dl>
    <dt>Username</dt>
    <dd>{{ forms.input('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>

You can import specific names from a template into the current namespace:

{% from 'forms.html' import input as input_field, textarea %}
<dl>
    <dt>Username</dt>
    <dd>{{ input_field('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>

Note

By default, included templates are passed the current context and imported templates are not. The reason for this is that imports, unlike includes, are cached; as imports are often used just as a module that holds macros.

This is only the default behaviour, you can change it if you want to:

{% from 'forms.html' import input with context %}
{% include 'header.html' without context %}
block
{% block sidebar %}
    {{ super() }}
    {% for item in seq %}
        <li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>
    {% endfor %}
{% endblock sidebar %}

Note

supper block is to inherit the contents in the pararnt block.

Note

Blocks can be nested for more complex layouts. However, per default blocks may not access variables from outer scopes. ‘item’ variable is out of item in above case because it defined out of the block. ‘scoped’ is to fix this kind of issue.

macro block

Macros are comparable with functions in regular programming languages. They are useful to put often used idioms into reusable functions.

Here’s a small example of a macro that renders a form element:

{% macro input(name, value='', type='text', size=20) -%}
    <input type="{{ type }}" name="{{ name }}" value="{{
        value|e }}" size="{{ size }}">
{%- endmacro %}

The macro can then be called like a function in the namespace:

<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>

Note

If the macro was defined in a different template, you have to import it first.

Note

If a macro name starts with an underscore, it’s not can’t be exported/imported.

call block

Here’s an example of how a call block can be used with arguments:

{% macro dump_users(users) -%}
    <ul>
    {%- for user in users %}
        <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
    {%- endfor %}
    </ul>
{%- endmacro %}

{# define the caller(user) in above macro block #}
{% call(user) dump_users(list_of_user) %}
    <dl>
        <dl>Realname</dl>
        <dd>{{ user.realname|e }}</dd>
        <dl>Description</dl>
        <dd>{{ user.description }}</dd>
    </dl>
{% endcall %}
filter block

Filter sections allow you to apply regular Jinja2 filters on a block of template data. Just wrap the code in the special filter section:

{% filter upper %}
    This text becomes uppercase
{% endfilter %}
assignments block
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}

{% set navigation %}
    <li><a href="/">Index</a>
    <li><a href="/downloads">Downloads</a>
{% endset %}
List of Control Structures

for: Loop over each item in a sequence.

Inside of a for-loop block, you can access some special variables:

Variable Description
loop.index The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex The number of iterations from the end of the loop (1 indexed)
loop.revindex0 The number of iterations from the end of the loop (0 indexed)
loop.first True if first iteration.
loop.last True if last iteration.
loop.length The number of items in the sequence.
loop.cycle A helper function to cycle between a list of sequences. See the explanation below.
loop.depth Indicates how deep in deep in a recursive loop the rendering currently is. Starts at level 1
loop.depth0 Indicates how deep in deep in a recursive loop the rendering currently is. Starts at level 0

For example:

{% for user in users %}
  <li>{{ user.username|e }}</li>
{% endfor %}


<dl>
{% for key, value in my_dict.iteritems() %}
    <dt>{{ key|e }}</dt>
    <dd>{{ value|e }}</dd>
{% endfor %}
</dl>

# will get the value 'odd', 'even' in turn.
{% for row in rows %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}

{% for user in users if not user.hidden %}
    <li>{{ user.username|e }}</li>
{% endfor %}

{% for user in users %}
    {%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}

{% for user in users %}
    {%- if loop.index is even %}{% continue %}{% endif %}
    ...
{% endfor %}

Note

Note, however, that Python dicts are not ordered; so you might want to either pass a sorted list or a collections.OrderedDict to the template, or use the dictsort filter.

Note

Unlike in Python, it’s not possible to break or continue in a loop. You can, however, filter the sequence during iteration, which allows you to skip items.

If no iteration took place because the sequence was empty or the filtering removed all the items from the sequence, you can render a default block by using else:

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% else %}
    <li><em>no users found</em></li>
{% endfor %}
</ul>

Note

In Python, else blocks are executed whenever the corresponding loop did not break. Since Jinja loops cannot break anyway, a slightly different behavior of the else keyword was chosen.

if: The if statement in Jinja is comparable with the Python if statement.

For example:

{% if users %}
<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}


{% if kenny.sick %}
    Kenny is sick.
{% elif kenny.dead %}
    You killed Kenny!  You bastard!!!
{% else %}
    Kenny looks okay --- so far
{% endif %}
autoescape expression
{% autoescape true %}
Autoescaping is active within this block
{% endautoescape %}
With Statement
{% with %}
{% set foo = 42 %}
{{ foo }}           foo is 42 here
{% endwith %}
foo is not visible here any longer
i18n
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}
{% endtrans %}

{# `_` is the alias of the gettext function #}
{{ _('Hello World!') }}
{{ gettext('Hello %(name)s!', name='World') }}

Flask Request Object

Overview Example

from flask import request

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None

    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'

    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

Response to Request:

  • Plain text string
  • response object
  • redirect(‘<ohter-url>’)
  • abort(<error_code>)

dir(request)

"['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__enter__', '__eq__', '__exit__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__',
'__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'_get_file_stream', '_get_stream_for_parsing', '_is_old_module',
'_load_form_data', '_parse_content_type',
'accept_charsets', 'accept_encodings', 'accept_languages', 'accept_mimetypes', 'access_route',
'application', 'args', 'authorization', 'base_url', 'blueprint', 'cache_control',
'charset', 'close', 'content_encoding', 'content_length', 'content_md5', 'content_type',
'cookies', 'data', 'date', 'dict_storage_class', 'disable_data_descriptor',
'encoding_errors', 'endpoint', 'environ', 'files',
'form', 'form_data_parser_class', 'from_values', 'full_path',
'get_data', 'get_json', 'headers', 'host', 'host_url',
'if_match', 'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since',
'input_stream', 'is_json', 'is_multiprocess', 'is_multithread',
'is_run_once', 'is_secure', 'is_xhr', 'json', 'list_storage_class',
'make_form_data_parser', 'max_content_length', 'max_form_memory_size', 'max_forwards',
'method', 'mimetype', 'mimetype_params', 'module', 'on_json_loading_failed',
'parameter_storage_class', 'path', 'pragma', 'query_string', 'range', 'referrer',
'remote_addr', 'remote_user', 'routing_exception', 'scheme', 'script_root',
'shallow', 'stream', 'trusted_hosts', 'url', 'url_charset', 'url_root', 'url_rule',
'user_agent', 'values', 'view_args', 'want_form_data_parsed']"

Get the args in the URL

To access parameters submitted in the URL (?key=value):

searchword = request.args.get('key', '')

Callback Functions

Decorator to define callback function:


@app.before_first_request # Only before the first request
@app.before_request # Before each request
@app.after_request # After each request if no exception
@app.teardown_request # After each request even there is exceptions

Global variable ‘g’ is valid in above functions. For example, we can use g.user to share login information among these functions.

Flask Response Object

The return value from a view function is automatically converted into a response object for you. If the return value is a string it’s converted into a response object with the string as response body, an 200 OK error code and a text/html mimetype.

The logic that Flask applies to converting return values into response objects is as follows:

  • If a response object of the correct type is returned it’s directly returned from the view.
  • If it’s a string, a response object is created with that data and the default parameters.
  • If a tuple is returned the items in the tuple can provide extra information. Such tuples have to be in the form (response, status, headers) where at least one item has to be in the tuple. The status value will override the status code and headers can be a list or dictionary of additional header values.
  • If none of that works, Flask will assume the return value is a valid WSGI application and convert that into a response object.

If you want to get hold of the resulting response object inside the view, you can use the make_response() function. Imagine you have a view like this:

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

You just need to wrap the return expression with make_response() and get the response object to modify it, then return it:

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

Flask Cookies

To access cookies you can use the cookies attribute. To set cookies you can use the set_cookie method of response objects. The cookies attribute of request objects is a dictionary with all the cookies the client transmits. If you want to use sessions, do not use the cookies directly but instead use the Sessions in Flask that add some security on top of cookies for you.

Reading cookies:

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

Storing cookies:

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

Note

Cookies are set on response objects. Since you normally just return strings from the view functions Flask will convert them into response objects for you. If you explicitly want to do that you can use the make_response() function and then modify it.

If you want to set a cookie at a point where the response object does not exist yet. This is possible by utilizing the Deferred Request Callbacks pattern.

Flask Sessions

Session allows you to store information specific to a user from one request to the next. This is implemented on top of cookies for you and signs the cookies cryptographically. What this means is that the user could look at the contents of your cookie but not modify it, unless they know the secret key used for signing.

In order to use sessions you have to set a secret key.

Example

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

# set the secret key.  keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

Note

The escape() mentioned here does escaping for you if you are not using the template engine (as in this example).

How to generate good secret keys

The problem with random is that it’s hard to judge what is truly random. And a secret key should be as random as possible. Your operating system has ways to generate pretty random stuff based on a cryptographic random generator which can be used to get such a key:

>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'

Just take that thing and copy/paste it into your code and you’re done.

Note

Flask will take the values you put into the session object and serialize them into a cookie. If you are finding some values do not persist across requests, cookies are indeed enabled, and you are not getting a clear error message, check the size of the cookie in your page responses compared to the size supported by web browsers.

Flask Uploading Files

http://flask.pocoo.org/docs/0.10/patterns/fileuploads/#uploading-files

Example:

from flask import request
from werkzeug import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

Flask Message Flashing

http://flask.pocoo.org/docs/0.10/patterns/flashing/#message-flashing-pattern

Good applications and user interfaces are all about feedback. If the user does not get enough feedback they will probably end up hating the application.

Flask provides a really simple way to give feedback to a user with the flashing system. The flashing system basically makes it possible to record a message at the end of a request and access it (only) on the next request. This is usually combined with a layout template to expose the message.

To flash a message use the flash() method, to get hold of the messages you can use get_flashed_messages() which is also available in the templates.

Flask Logging

http://flask.pocoo.org/docs/0.10/errorhandling/

Sometimes you might be in a situation where you deal with data that should be correct, but actually is not. For example you may have some client-side code that sends an HTTP request to the server but it’s obviously malformed. This might be caused by a user tampering with the data, or the client code failing. Most of the time it’s okay to reply with 400 Bad Request in that situation, but sometimes that won’t do and the code has to continue working.

You may still want to log that something fishy happened. This is where loggers come in handy. As of Flask 0.3 a logger is preconfigured for you to use.

Here are some example log calls:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

The attached logger is a standard logging Logger, so head over to the official logging documentation for more information.

Logger handlers

There are a couple of handlers provided by the logging system out of the box, but not all of them are useful for basic error logging. The most interesting are probably the following: | | SMTPhandler - logs messages by sending out a email | FileHandler - logs messages to a file on the filesystem. | RotatingFileHandler - logs messages to a file on the filesystem | and will rotate after a certain number of messages. | SysLogHandler - logs messages to a UNIX syslog. |

Example codes for SMTPhandler:

if not app.debug:
    import logging
    from logging.handlers import SMTPHandler
    mail_handler = SMTPHandler('host-ip-or-name',
                               'from@example.com',
                               [to-list1@example.com],
                               'Email-title')
    mail_handler.setLevel(logging.ERROR)
    app.logger.addHandler(mail_handler)

...

app.logger.error('Some content in the E-mail!')

Note

The from address will not be checked, so it doesn’t need to be a valid address. However, if it’s invalid, it can not be replied.

Better format

Email Format:

from logging import Formatter
mail_handler.setFormatter(Formatter('''
Message type:       %(levelname)s
Location:           %(pathname)s:%(lineno)d
Module:             %(module)s
Function:           %(funcName)s
Time:               %(asctime)s

Message:

%(message)s
'''))

Log file Format:

from logging import Formatter
file_handler.setFormatter(Formatter(
    '%(asctime)s %(levelname)s: %(message)s '
    '[in %(pathname)s:%(lineno)d]'
))

Flask Sqlite3

Using flask-sqlalchemy

(venv) $ pip install flask-sqlalchemy

Using Sqlite3 with Flash

http://flask.pocoo.org/docs/0.10/patterns/sqlite3/#sqlite3

Python sqlite3 standard library : https://docs.python.org/2/library/sqlite3.html

Module functions and constants:

connect(db-path[, timeout, ...])

Connection Objects:

cursor()
commit()
rollback()
close()

Cursor Objects:

execute(sql[, parameters])
executemany(sql, seq_of_parameters)
executescript(sql_script)
fetchone()
fetchmany([size=cursor.arraysize])
fetchall()

Example:

# -*- coding: utf-8 -*-

import os
import sqlite3
from flask import g

class Sqlite3DB():
    app = None

    @classmethod
    def bindapp(cls, app):
        cls.app = app

    @classmethod
    def connect(cls):
        if not hasattr(g, 'sqlite_db'):
            assert cls.app is not None, 'Application is not binded to DB'
            path = cls.app.config.get('DATABASE')
            assert path is not  None, 'DB path is not set!'
            if not os.path.isfile(path):
                cls.app.logger.debug('Initialize the DB')
                db = sqlite3.connect(path)
                with cls.app.open_resource('../database/schema.sql', mode='r') as f:
                    db.cursor().executescript(f.read())
                db.commit()
            else:
                cls.app.logger.debug('Connect the DB')
                db = sqlite3.connect(path)
            db.row_factory = sqlite3.Row

            g.sqlite_db = db
        return g.sqlite_db

    @classmethod
    def fetchall(cls, sql):
        cls.app.logger.debug('Fetch all entries in the DB')
        db = cls.connect()
        cur = db.cursor().execute(sql)
        return cur.fetchall()

    @classmethod
    def addone(cls, sql, data=None):
        db = cls.connect()
        db.cursor().execute(sql, data)
        db.commit()

    @classmethod
    def close(cls):
        db = cls.connect()
        db.close()

Flask Extension

Flask extensions are listed on the Flask Extension Registry and can be downloaded with easy_install or pip. If you add a Flask extension as dependency to your requirements.rst or setup.py file they are usually installed with a simple command or when your application installs.

Using Extensions

Extensions typically have documentation that goes along that shows how to use it. There are no general rules in how extensions are supposed to behave but they are imported from common locations.

If you have an extension called Flask-Foo or Foo-Flask it will be always importable from flask.ext.foo:

from flask.ext import foo

Flask Project

Typical Strucature

The typical project directory tree:

.
├── app
│   ├── hello.py
│   ├── static
│   └── templates
├── config.py
├── requirements.txt
├── run.py
├── tests
│   └── test_basic.py
└── venv

Examples:

Project Template

https://github.com/sloria/cookiecutter-flask

Install cookiecutter:

$ sudo pip install cookiecutter
$ cookiecutter https://github.com/sloria/cookiecutter-flask.git

$ sudo apt-get install libpq-dev python-dev
$ sudo pip install -r requirements/dev.txt  (or do this in virtualenv)

Configuration Handling

http://flask.pocoo.org/docs/0.10/config/

The config attribute of the Flask object is the place where Flask itself puts certain configuration values and also where extensions can put their configuration values. This is also where you can have your own configuration.

The config is a subclass of a dictionary and can be modified just like any dictionary:

app = Flask(__name__)
app.config['DEBUG'] = True

Certain configuration values are also forwarded to the Flask object so you can read and write them from there:

app.debug = True

To update multiple keys at once you can use the dict.update() method:

app.config.update(
    DEBUG=True,
    SECRET_KEY='...'
)

Note

The SERVER_NAME key is used for the subdomain support. Because Flask cannot guess the subdomain part without the knowledge of the actual server name, this is required if you want to work with subdomains. This is also used for the session cookie.

Please keep in mind that not only Flask has the problem of not knowing what subdomains are, your web browser does as well. Most modern web browsers will not allow cross-subdomain cookies to be set on a server name without dots in it. So if your server name is ‘localhost’ you will not be able to set a cookie for ‘localhost’ and every subdomain of it. Please chose a different server name in that case, like ‘myapplication.local’ and add this name + the subdomains you want to use into your host config or setup a local bind.

Configuring from Files

Configuration becomes more useful if you can store it in a separate file, ideally located outside the actual application package. This makes packaging and distributing your application possible via various package handling tools (Deploying with Distribute) and finally modifying the configuration file afterwards.

So a common pattern is this:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

This first loads the configuration from the yourapplication.default_settings module and then overrides the values with the contents of the file the YOURAPPLICATION_SETTINGS environment variable points to. This environment variable can be set on Linux or OS X with the export command in the shell before starting the server:

$ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
$ python run-app.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader...

The configuration files themselves are actual Python files. Only values in uppercase are actually stored in the config object later on. So make sure to use uppercase letters for your config keys.

Here is an example of a configuration file:

# Example configuration
DEBUG = False
SECRET_KEY = '?\xbf,\xb4\x8d\xa3"<\x9c\xb0@\x0f5\xab,w\xee\x8d$0\x13\x8b83'

Make sure to load the configuration very early on, so that extensions have the ability to access the configuration when starting up. There are other methods on the config object as well to load from individual files. For a complete reference, read the Config object’s documentation.

Other Examples:

app.config.from_pyfile('yourconfig.cfg')


DEBUG = True
SECRET_KEY = 'development key'
app.config.from_object(__name__)

Configuration Best Practices

The downside with the approach mentioned earlier is that it makes testing a little harder. There is no single 100% solution for this problem in general, but there are a couple of things you can keep in mind to improve that experience:

  1. create your application in a function and register blueprints on it. That way you can create multiple instances of your application with different configurations attached which makes unittesting a lot easier. You can use this to pass in configuration as needed.
  2. Do not write code that needs the configuration at import time. If you limit yourself to request-only accesses to the configuration you can reconfigure the object later on as needed.

Development / Production

Most applications need more than one configuration. There should be at least separate configurations for the production server and the one used during development. The easiest way to handle this is to use a default configuration that is always loaded and part of the version control, and a separate configuration that overrides the values as necessary as mentioned in the example above:

app = Flask(__name__)
app.config.from_object('yourapplication.default_settings')
app.config.from_envvar('YOURAPPLICATION_SETTINGS')

Then you just have to add a separate config.py file and export YOURAPPLICATION_SETTINGS=/path/to/config.py and you are done. However there are alternative ways as well. For example you could use imports or subclassing.

An interesting pattern is to use classes and inheritance for configuration:

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'

class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    TESTING = True

To enable such a config you just have to call into from_object():

app.config.from_object('configmodule.ProductionConfig')

There are many different ways and it’s up to you how you want to manage your configuration files. However here a list of good recommendations:

  1. keep a default configuration in version control repository. Either populate the config with this default configuration or import it in your own configuration files before overriding values.
  2. use an environment variable to switch between the configurations. You can quickly and easily switch between different configs without having to touch the code at all. If you are working often on different projects you can even create your own script for sourcing that activates a virtualenv and exports the development configuration for you.

Instance Folders

With Flask 0.8 a new attribute was introduced: Flask.instance_path. It refers to a new concept called the “instance folder”. The instance folder is designed to not be under version control and be deployment specific. It’s the perfect place to drop things that either change at runtime or configuration files.

You can either explicitly provide the path of the instance folder when creating the Flask application or you can let Flask autodetect the instance folder. For explicit configuration use the instance_path parameter:

app = Flask(__name__, instance_path='/path/to/instance/folder')

Note

Please keep in mind that this path must be absolute when provided.

If the instance_path parameter is not provided the following default locations are used:

Uninstalled module:

/myapp.py
/instance

Uninstalled package:

/myapp
    /__init__.py
/instance

Installed module or package:

$PREFIX/lib/python2.X/site-packages/myapp
$PREFIX/var/myapp-instance

Note

$PREFIX is the prefix of your Python installation. This can be /usr or the path to your virtualenv. You can print the value of sys.prefix to see what the prefix is set to.

Since the config object provided loading of configuration files from relative filenames we made it possible to change the loading via filenames to be relative to the instance path if wanted. The behavior of relative paths in config files can be flipped between “relative to the application root” (the default) to “relative to instance folder” via the instance_relative_config switch to the application constructor:

app = Flask(__name__, instance_relative_config=True)

Here is a full example of how to configure Flask to preload the config from a module and then override the config from a file in the config folder:

app = Flask(__name__, instance_relative_config=True)
app.config.from_object('yourapplication.default_settings')
app.config.from_pyfile('application.cfg', silent=True)

The path to the instance folder can be found via the Flask.instance_path. Flask also provides a shortcut to open a file from the instance folder with Flask.open_instance_resource().

Example usage for both:

filename = os.path.join(app.instance_path, 'application.cfg')
with open(filename) as f:
    config = f.read()

# or via open_instance_resource:
with app.open_instance_resource('application.cfg') as f:
    config = f.read()

JavaScript Basic

http://www.w3school.com.cn/b.asp http://www.w3school.com.cn/js/index_pro.asp https://developer.mozilla.org/en-US/docs/Web/JavaScript

JavaScript Overview

  • JavaScript programs are written using the Unicode character set.
  • JavaScript is a case-sensitive language. (However, HTML is not case-sensitive.)
  • JavaScript ignores spaces that appear between tokens in programs and ignores line breaks.
  • JavaScript supports two styles of comments, the same as C language.
  • JavaScript uses the semicolon ( ; ) to separate statements (see Chapter 5) from each other.
  • JavaScript identifier names must match “^[a-zA-z_$][a-zA-z0-9_$]*”
  • JavaScript interpreter performs automatic garbage collection for memory management.
  • JavaScript is an object-oriented language.
  • JavaScript variables are untyped, you can assign a value of any type to a variable.
  • All numbers in JavaScript are represented as floating-point values.
  • JavaScript numbers can approximate 0.1 very closely, but cannot be represented exactly.
  • JavaScript code behaves as if all variable declarations in a function (but not any associated assignments) are “hoisted” to the top of the function.

JavaScript Reserved Words

JavaScript reserves a number of identifiers as the keywords of the language itself. You cannot use these words as identifiers in your programs:

break       case        catch       continue    debugger    default
delete      do          else        false       finally     for
function    if          in          instanceof  new         null
return      switch      this        throw       true        try
typeof      var         void        while       with

JavaScript also reserves certain keywords that are not currently used by the language but which might be used in future versions. ECMAScript 5 reserves the following words:

class       const       enum        export      extends     import      super

The following words are legal in ordinary JavaScript code, but reserved in strict mode:

implements  interface   let         package     private     protected
public      static      yield

Strict mode also imposes restrictions on the use of the following identifiers. They are not fully reserved, but they are not allowed as variable, function, or parameter names:

arguments   eval

ECMAScript 3 reserved all the keywords of the Java language, and although this has been relaxed in ECMAScript 5, you should still avoid all of these identifiers if you plan to run your code under an ECMAScript 3 implementation of JavaScript:

abstract    boolean     byte        char        class       const
double      enum        export      extends     final       float
goto        implements  import      int         interface   long
native      package     private     protected   public      short
static      super     synchronized  throws      transient   volatile

JavaScript predefines a number of global variables and functions, and you should avoid using their names for your own variables and functions:

arguments           Array               Boolean             Date
decodeURI           decodeURIComponent  encodeURI           encodeURIComponent
Error               eval                EvalError           Function
Infinity            isFinite            isNaN               JSON
Math                NaN                 Number              Object
parseFloat          parseInt            RangeError          ReferenceError
RegExp              String              SyntaxError         TypeError
undefined           URIError

JavaScript Types and Variables

Examples:

const pi = 3.1415926;  // const value cannot be changed
var a = 'test';
var b = 'test';
a == b ;           // true, Primitive type only compare value

var a = {x: 1};
var a = {x: 1};
a == b             // false

c = a;
c.x = 2;
a.x;               // => 2, object is reference type
a === c;           // true

// 'let' defines block level values in loop or function.
for (let i=1; i<len; i++) { ...}

[x, y] = [1, 2]                                // x=1, y=2
[x, y] = [y, x]                                // switch x and y
[a, b, c] = [1, 2]                             // a=1, b=2, c=undefined
[a, [b, c]] = [1, [2,3], 4]                    // a=1, b=2, c=3
{r: red, g:green, b:blue} = {r:0, g:255, b:0}; // red=0, green=255, blue=0

var data=[1, 2, -3];
var squares = [x*x for each (x in data) if (x>=0)] // squares = [1, 4]

Primitive/Object Type

Primitive Type:

  • number
  • string
  • boolean
  • null
  • undefined

Object Type:

  • object/class
  • array
  • function
  • date
  • regexp
  • error

Mutable/Immutable Type

Mutable Type:

  • object
  • array

Immutable Type:

  • number
  • string
  • boolean
  • null
  • undefined

Number

0 === -0       # true
(0.3 - 0.2) == (0.2 -0.1) # False

Math.pow(2,53)          // => 9007199254740992: 2 to the power 53
Math.round(.6)          // => 1.0: round to the nearest integer
Math.ceil(.6)           // => 1.0: round up to an integer
Math.floor(.6)          // => 0.0: round down to an integer
Math.abs(-5)            // => 5: absolute value
Math.max(x,y,z)         // Return the largest argument
Math.min(x,y,z)         // Return the smallest argument
Math.random()           // Pseudo-random number x where 0 <= x < 1.0
Math.PI                 // π: circumference of a circle / diameter
Math.E                  // e: The base of the natural logarithm
Math.sqrt(3)            // The square root of 3
Math.pow(3, 1/3)        // The cube root of 3
Math.sin(0)             // Trigonometry: also Math.cos, Math.atan, etc.
Math.log(10)            // Natural logarithm of 10
Math.log(100)/Math.LN10 // Base 10 logarithm of 100
Math.log(512)/Math.LN2  // Base 2 logarithm of 512
Math.exp(3)             // Math.E cubed

Date

var then = new Date(2010, 0, 1);  // The 1st day of the 1st month of 2010
var later = new Date(2010, 0, 1, 17, 10, 30);
var now = new Date();       // The current date and time
var elapsed = now - then;   // Date subtraction: interval in milliseconds
later.getFullYear()         // => 2010
later.getMonth()            // => 0: zero-based months
later.getDate()             // => 1: one-based days
later.getDay()              // => 5: day of week. 0 is Sunday 5 is Friday.
later.getHours()            // => 17: 5pm, local time
later.getUTCHours()         // -> hours in UTC time; depends on timezone
later.toString()            // => "Fri Jan 01 2010 17:10:30 GMT-0800 (PST)"
later.toUTCString()         // => "Sat, 02 Jan 2010 01:10:30 GMT"
later.toLocaleDateString()  // => "01/01/2010"
later.toLocaleTimeString()  // => "05:10:30 PM"
later.toISOString()         // => "2010-01-02T01:10:30.000Z"; ES5 only

String

http://www.w3school.com.cn/jsref/jsref_obj_string.asp

In ECMAScript 3, string literals must be written on a single line. In ECMAScript 5, however, you can break a string literal across multiple lines by ending each line but the last with a backslash ( ). In ECMAScript 5, strings can be treated like read-only arrays, and you can access individual characters from a string using square brackets.

Basic Functions:

var s = "Hello, " + "world";
s.charAt(0)                 // => "h": the first character.
s.charAt(s.length-1)        // => "d": the last character.
s.substring(1,4)            // => "ell": the 2nd, 3rd and 4th
s.slice(1,4)                // => "ell": same thing
s.slice(-3)                 // => "rld": last 3 characters
s.indexOf("l")              // => 2: position of first letter
s.lastIndexOf("l")          // => 10: position of last letter
s.indexOf("l", 3)           // => 3: position of first "l" at or after 3
s.split(", ")               // => ["hello", "world"] split into substrings
s.replace("h", "H")         // => "Hello, world": replaces all instances
s.toUpperCase()             // => "HELLO, WORLD"
s[0]                        // => "h"
s[s.length-1]               // => "d"
s.search(/world/);          // => 7, first position
s.match(/l+/g)              // => ["ll", "l"], 'g' means return all matches

Advance Usage:

"1, 2, 3, 4, 5".split(/\s*,\s*/);   // Returns ["1","2","3","4","5"]

var s = 'My name is "John"' ;       // $1 refer to the first matches
s.replace(/"([^'"]*)"/g, "'$1'")    // => My name is 'John'

"1 plus 2 equals 3".match(/\d+/g)   // returns ["1", "2", "3"]
"1 plus 2 equals 3".match(/\d+/)    // returns ["1"]
"1 plus 2 equals 3".match(/(\d+)/g) // returns ["1", "2", "3"]
"1 plus 2 equals 3".match(/(\d+)/)  // returns ["1", "1"], the first matches and content in "()" in turn

var url_pattern = /(\w+):\/\/([\w.]+)\/(\S*)/;
var text = "Visit my blog at http://www.example.com/~david";
var result = text.match(url_pattern);
if (result != null) {
    var fullurl = result[0];    // Contains "http://www.example.com/~david"
    var protocol = result[1];   // Contains "http"
    var host = result[2];       // Contains "www.example.com"
    var path = result[3];       // Contains "~david"
}

Boolean

All other values, including all objects (and arrays) convert to, and work like, true. Except the following false values:

undefined    null    0    -0    NaN    ""

null == undefined  // true
0 == false         // true
"0" == 0           // true

Note

null is a language keyword and undefined is a predefined global variable. You might consider undefined to represent a system-level, unexpected, or error-like absence of value and null to represent program-level, normal, or expected absence of value.

Type Conversions

10 + " objects"    // "10 objects"
"7" * "4"          // 28
1 - ""             // 1
1 - "x"            // NaN

Number("3")        // 3
String(false)      // "false"
Boolean([])        // true
Object(3)          // new Number(3)

x + ""             // equal to String(x)
+x                 // qeual to Number(x)
!!x                // equal to Boolean(x)

var n = 17;
n.toString(2)      // "10001"
n.toString(16)     // "11"

var n = 123456.789
n.toFixed(0)       // 123457
n.toFixed(2)       // 123456.79
n.toFixed(5)       // 123456.78900
n.toExponential(1) // "1.2e+5"
n.toPrecision(4)   // "1.235e+5"

parseInt("3 blind mice")     //3
parseFloat(" 3.14 meters")   // 3.14
parseInt("0xFF")             //255
parseInt(".1")               // NaN
parseInt("0.1")              // 0
parseFloat(".1")             // 0.1
parseFloat("$12.34")         // NaN
parseInt("11", 2)            // 3
parseInt("11", 16)           // 17

[1,2,3].toString()           // "1,2,3"

Special Global Number Variables

Infinity

  • Number.POSITITVE_INFINITY
  • 1/0
  • Number.MAX_VALUE + 1

-Infinity

  • Number.NEGATIVE_INFINITY
  • -1/0
  • -Number.MAX_VALUE - 1

NaN

  • 0/0

Note

isNaN(x) # true if x != x, that means x is NaN
isFinite(x) # true if x is not NaN, Infinity, -Infinity

JavaScript Expression

Operator Overview

The following operators re arranged in order from high precedence to low precedence, with horizontal lines separating groups of operators at the same precedence level:

============ ============================ ==== ==== ==================
Operator     Operation                    A    N    Types
============ ============================ ==== ==== ==================
++           Pre- or post-increment       R    1       lval -> num
--           Pre- or post-decrement       R    1       lval -> num
-            Negate number                R    1        num -> num
+            Convert to number            R    1        num -> num
~            Invert bits                  R    1        int -> int
!            Invert boolean value         R    1       bool -> bool
delete       Remove a property            R    1       lval -> bool
typeof       Determine type of operand    R    1        any -> str
void         Return undefined value       R    1        any -> undef
----------------------------------------------------------------------
* / %        Multiply, divide, remainder  L    2    num,num -> num
----------------------------------------------------------------------
+  -         Add, subtract                L    2    num,num -> num
+            Concatenate strings          L    2    str,str -> str
----------------------------------------------------------------------
<<           Shift left                   L    2    int,int -> int
>>           Shift right with sign        L    2    int,int -> int
>>>          Shift right with zero        L    2    int,int -> int
----------------------------------------------------------------------
< <= > >=    Compare in numeric order     L    2    num,num -> bool
< <= > >=    Compare in alphabetic order  L    2    str,str -> bool
instanceof   Test object class            L    2    obj,func-> bool
in           Test whether property exists L    2    str,obj -> bool
----------------------------------------------------------------------
==           Test for equality            L    2    any,any -> bool
!=           Test for inequality          L    2    any,any -> bool
===          Test for strict equality     L    2    any,any -> bool
!==          Test for strict inequality   L    2    any,any -> bool
----------------------------------------------------------------------
&            Compute bitwise AND          L    2    int,int -> int
----------------------------------------------------------------------
^            Compute bitwise XOR          L    2    int,int -> int
----------------------------------------------------------------------
|            Compute bitwise OR           L    2    int,int -> int
----------------------------------------------------------------------
&&           Compute logical AND          L    2    any,any -> any
----------------------------------------------------------------------
||           Compute logical OR           L    2    any,any -> any
----------------------------------------------------------------------
?:           Choose 2nd or 3rd operand    R    3    bool,any,any->any
----------------------------------------------------------------------
=            Variable or property assign  R    2    lval,any-> any
*= /= %= +=  Operate and assign           R    2    lval,any-> any
-= &= ^= |=  Operate and assign           R    2    lval,any-> any
<<= >>= >>>= Operate and assign           R    2    lval,any-> any
----------------------------------------------------------------------
,            Discard 1st, return 2nd      L    2    any,any -> any
============ ============================ ==== ==== ==================

Note

+ prefer to convert number to string
< <= > >= prefer to convert string to number
compare NaN with anything will return false
var v = a || b || 2, common way to provide defualt values.
Global variables are properties of the global object, so they can be deleted

=== and ==

The strict equality operator === evaluates its operands, and then compares the two values as follows, performing no type conversion:

  • If the two values have different types, they are not equal.
  • If both values are null or both values are undefined , they are equal.
  • If both values are the boolean value(true or false), they are equal.
  • If one or even both values is NaN , they are not equal.
  • If both values are numbers and have the same value, they are equal.
  • If one value is 0 and the other is -0 , they are also equal.
  • If both values are strings and have same content, they are equal.
  • If both values refer to the same object, array, or function, they are equal.
  • If they refer to different object instances, they are not equal.

The equality operator == is like the strict equality operator, but it is less strict:

  • If the two values have the same type, test them for strict equality as described above. If they are strictly equal, they are equal. If they are not strictly equal, they are not equal.

  • If the two values do not have the same type, the == operator attempts some type conversions and tries the comparison again:

    • If one value is null and the other is undefined , they are equal.
    • If one value is a number and the other is a string, convert the string to a number and try the comparison again, using the converted value.
    • If either value is true , convert it to 1 and try the comparison again.
    • If either value is false , convert it to 0 and try the comparison again.
    • If one value is an object and the other is a number or string, convert the object to a primitive value and try the comparison again. (toString/valueOf)
    • Any other combinations of values are not equal.

typeof

======================= ===========
x                       typeof x
======================= ===========
undefined               "undefined"
null                    "object"
true or false           "boolean"
any number or NaN       "number"
any string              "string"
any function            "function"
any native object       "object"
======================= ===========

JavaScript Statements

Overview

JavaScript does not have block scope and variables declared within a statement block are not private to the block.

Variables are defined throughout the script or function in which they are declared. Their declaration is “hoisted” up to the start of the script or function. Initialization, however, occurs at the location of the var statement, and the value of the variable is undefined before that point in the code.

Function declaration statements may appear in top-level JavaScript code, or they may be nested within other functions. When nested, however, function declarations may only appear at the top level of the function they are nested within. That is, function definitions may not appear within if statements, while loops, or any other statements.

With var, only the variable declaration is hoisted, the variable initialization code remains where you placed it. With function declaration statements, however, both the function name and the function body are hoisted: all functions in a script or all nested functions in a function are declared before any other code is run.

Like the var statement, function declaration statements create variables that cannot be deleted.

Finally, note that a break statement, with or without a label, can not transfer control across function boundaries. You cannot label a function definition statement, for ex- ample, and then use that label inside the function.

Statements Structure

statements:

// Initialize an array a
for(i = 0; i < a.length; a[i++] = 0) /* empty */ ;

var f = function(x) { return x+1; }  // Expression assigned to a variable
function f(x) { return x+1; }        // Function declaration statement

if (expression) {
    statements
}
else if (expression) {
    statements
}
else {
    statements
}

// compare by "==="
switch(expression) {
    case value1:
        statements
        break;
    case value2:
        statements
        break;
    default:
        statements
        break;
}

while (expression) {
    statements
}

do {
    statements
} while (expression) ;  // Must always be terminated with a semicolon.

for(initialize; test; increment) {
    statements
}

for (var p in o) {   // Enumerable properties in object
    statements
}

var o = {x:1, y:2, z:3}, a = [], i = 0;
for (a[i++] in o) {  // Store properties of object into arrray
    statements
}

lablename: loop-statements {
    loop-statement {
        ...
        continue lablename;
        ...
        break lablename;
    }
}

throw new Error("x must not be negative");

try {
    // Normally, this code runs from the top of the block to the bottom
    // without problems. But it can sometimes throw an exception,
    // either directly, with a throw statement, or indirectly, by calling
    // a method that throws an exception.
}
catch (e) {
    // The statements in this block are executed if, and only if, the try
    // block throws an exception. These statements can use the local variable
    // e to refer to the Error object or other value that was thrown.
    // This block may handle the exception somehow, may ignore the
    // exception by doing nothing, or may rethrow the exception with throw.
}
finally {
    // This block contains statements that are always executed, regardless of
    // what happens in the try block. They are executed whether the try
    // block terminates:
    //   1) normally, after reaching the bottom of the block
    //   2) because of a break, continue, or return statement
    //   3) with an exception that is handled by a catch clause above
    //   4) with an uncaught exception that is still propagating
}

if (o === undefined) debugger;

examples:

var o = {one: 1, two: 2, three: 3};
for (let p in o) console.log(p);            // indexes: one, two, three
for each (let v in o) console.log(v)        // values: 1, 2, 3

try {
    // more than one type of exception where
    throw 1;
}
catch(e if e instanceof ReferenceError) {
    //do something here
}
catch(e if e === "quit") {
    // do something here
}
catch(e){ //all other cases
    // do something here
}
finally {
    // do something here
}

‘use strict’ Directive

It can appear only at the start of a script or at the start of a function body, before any real statements have appeared. It need not be the very first thing in the script or function.

The differences between strict mode and non-strict mode are the following:

  • The with statement is not allowed in strict mode.
  • In strict mode, all variables must be declared: a ReferenceError is thrown if you assign a value to an identifier that is not a declared variable, function, function parameter, catch clause parameter, or property of the global object. (In non-strict mode, this implicitly declares a global variable by adding a new property to the global object.)
  • In strict mode, functions invoked as functions (rather than as methods) have a this value of undefined . (In non-strict mode, functions invoked as functions are always passed the global object as their this value.) This difference can be used to determine whether an implementation supports strict mode: var hasStrictMode = (function() { "use strict"; return this===undefined}());
  • Also, in strict mode, when a function is invoked with call() or apply() , the this value is exactly the value passed as the first argument to call() or apply() . (In nonstrict mode, null and undefined values are replaced with the global object and non-object values are converted to objects.)
  • In strict mode, assignments to nonwritable properties and attempts to create new properties on nonextensible objects throw a TypeError. (In non-strict mode, these attempts fail silently.)
  • In strict mode, code passed to eval() cannot declare variables or define functions in the caller’s scope as it can in non-strict mode. Instead, variable and function definitions live in a new scope created for the eval() . This scope is discarded when the eval() returns.
  • In strict mode, the arguments object (§8.3.2) in a function holds a static copy of the values passed to the function. In non-strict mode, the arguments object has “magical” behavior in which elements of the array and named function parameters both refer to the same value.
  • In strict mode, a SyntaxError is thrown if the delete operator is followed by an unqualified identifier such as a variable, function, or function parameter. (In non- strict mode, such a delete expression does nothing and evaluates to false .)
  • In strict mode, an attempt to delete a nonconfigurable property throws a TypeError. (In non-strict mode, the attempt fails and the delete expression eval- uates to false .)
  • In strict mode, it is a syntax error for an object literal to define two or more prop- erties by the same name. (In non-strict mode, no error occurs.)
  • In strict mode, it is a syntax error for a function declaration to have two or more parameters with the same name. (In non-strict mode, no error occurs.)
  • In strict mode, octal integer literals (beginning with a 0 that is not followed by an 0x) are not allowed. (In non-strict mode, some implementations allow octal literals.)
  • In strict mode, the identifiers eval and arguments are treated like keywords, and you are not allowed to change their value. You cannot assign a value to these identifiers, declare them as variables, use them as function names, use them as function parameter names, or use them as the identifier of a catch block.
  • In strict mode, the ability to examine the call stack is restricted. arguments.caller and arguments.callee both throw a TypeError within a strict mode function. Strict mode functions also have caller and arguments properties that throw TypeError when read. (Some implementations define these nonstandard properties on non-strict functions.)

JavaScript Objects

JavaScript’s fundamental datatype is the object. An object is an unordered collection of properties, each of which has a name and a value.

Overview

JavaScript objects are dynamic(properties can usually be added and deleted), but they can be used to simulate the static objects and “structs” of statically typed languages.

The most common things to do with objects are create them and to set, query, delete, test, and enumerate their properties.

In addition to its properties, every object has three associated object attributes: - An object’s prototype is a reference to another object from which properties are inherited. - An object’s class is a string that categorizes the type of an object. - An object’s extensible flag specifies whether new properties may be added to the object.

Finally, here are some terms we’ll use to distinguish among three broad categories of JavaScript objects and two types of properties:

Types of objects:

  • A native object is an object or class of objects defined by the ECMAScript specification. Arrays, functions, dates, and regular expressions (for example) are native objects.
  • A host object is an object defined by the host environment (such as a web browser) within which the JavaScript interpreter is embedded. The HTMLElement objects that represent the structure of a web page in client-side JavaScript are host objects. Host objects may also be native objects, as when the host environment defines methods that are normal JavaScript Function objects.
  • A user-defined object is any object created by the execution of JavaScript code.

Types of properties:

  • An own property is a property defined directly on an object.
  • An inherited property is a property defined by an object’s prototype object.

property attributes

  • The writable attribute specifies whether the value of the property can be set.
  • The enumerable attribute specifies whether the property name is returned by a for/in loop.
  • The configurable attribute specifies whether the property can be deleted and whether its attributes can be altered.
// Returns {value: 1, writable:true, enumerable:true, configurable:true}
Object.getOwnPropertyDescriptor({x:1}, "x");

// Now query the octet property of the random object defined above.
// Returns { get: /*func*/, set:undefined, enumerable:true, configurable:true}
Object.getOwnPropertyDescriptor(random, "octet");

// Returns undefined for inherited properties and properties that don't exist.
Object.getOwnPropertyDescriptor({}, "x");        // undefined, no such property
Object.getOwnPropertyDescriptor({}, "toString"); // undefined, inherited

// Does not have to include all four attributes at the same time.
Object.defineProperty(o, "x", { value : 1,
                                writable: true,
                                enumerable: false,
                                configurable: true});

var p = Object.defineProperties({}, {
    x: { value: 1, writable: true, enumerable:true, configurable:true },
    y: { value: 1, writable: true, enumerable:true, configurable:true },
    r: {
        get: function() { return Math.sqrt(this.x*this.x + this.y*this.y) },
        enumerable:true,
        configurable:true
    }
});

Note

Here are the complete rules. Calls to Object.defineProperty() or Object.defineProperties() that attempt to violate them throw TypeError:

  • If an object is not extensible, you can edit its existing own properties, but you cannot add new properties to it.
  • If a property is not configurable, you cannot change its configurable or enumerable attributes.
  • If an accessor property is not configurable, you cannot change its getter or setter method, and you cannot change it to a data property.
  • If a data property is not configurable, you cannot change it to an accessor property.
  • If a data property is not configurable, you cannot change its writable attribute from false to true , but you can change it from true to false .
  • If a data property is not configurable and not writable, you cannot change its value. You can change the value of a property that is configurable but nonwritable. (making it writable, then changing the value, then converting it back to nonwritable).

Objects Operators

Creating Objects

var point = {x:0, y:0};
var o = Object.create(Object.prototype)
var o = new Object();
var a = new Arrays();
var d = new Date();
var r = new RegExp();

Querying and Setting Properties

The fact that inheritance occurs when querying properties but not when setting them is a key feature because it allows us to selectively override inherited properties.

Property assignment examines the prototype chain to determine whether the assignment is allowed. If o inherits a read-only property named x , for example, then the assignment is not allowed.

It is not an error to query a property that does not exist, undefined will be return. It is an error, however, to attempt to query a property of an object that does not exist.

An attempt to set a property p of an object o fails in these circumstances:

  • o has an own property p that is read-only: it is not possible to set read-only prop- erties. (See the defineProperty() method, however, for an exception that allows configurable read-only properties to be set.)
  • o has an inherited property p that is read-only: it is not possible to hide an inherited read-only property with an own property of the same name.
  • o does not have an own property p ; o does not inherit a property p with a setter method, and o ’s extensible attribute is false . If p does not already exist on o , and if there is no setter method to call, then p must be added to o . But if o is not extensible, then no new properties can be defined on it.
/* If an object has properties whose name is a reserved
word, you must use square bracket notation to access them */

var author = book.author;           // Get the "author" property of the book.
var name = author.surname;          // Get the "surname" property of the author.
var title = book["main title"];     // Get the "main title" property of the book.
book.edition = 6;                   // Create an "edition" property of book.
book["main title"] = "ECMAScript";  // Set the "main title" property.

var len = book && book.subtitile && book.subtitle.length; // May doesn't exist

Deleting Properties

The delete operator only deletes own properties, not inherited ones. The delete operator does not remove properties that have a configurable attribute of false .

delete book.author;                 // The book object now has no author property.
delete book["main title"];          // Now it doesn't have "main title", either.

Testing Properties

var o = { x: 1 }
"x" in o;                           // true: o has an own property "x"
"y" in o;                           // false: o doesn't have a property "y"
"toString" in o;                    // true: o inherits a toString property

o.hasOwnProperty("x");              // true: o has an own property x
o.hasOwnProperty("y");              // false: o doesn't have a property y
o.hasOwnProperty("toString");       // false: toString is an inherited property

/* Only is property is an own property and its enumerable attribute is true */
o.propertyIsEnumerable("x");        // true: o has an own enumerable property x
Object.prototype.propertyIsEnumerable("toString"); // false: not enumerable

o.x !== undefined  // It's equal to 'in' execpt property is explicitly set to undefined
if (o.x) o.x *=2 ; // If exist and is not undefined, null, false, "", 0, NaN

Enumerating Properties

for(p in o) {
    if (!o.hasOwnProperty(p)) continue;
}
for(p in o) {
    if (typeof o[p] === "function") continue; // Skip methods
}

Object.keys()  // returns an array of the names of the enumerable own properties
Object.getOwnPropertyNames()  // returns the names of all the own properties

Property Getters and Setters

var p = {
    x: 1.0,
    y: 1.0,

    // r is a read-write accessor property with getter and setter.
    get r() {
        return Math.sqrt(this.x*this.x + this.y*this.y);
    },  // Don't forget to put a comma after accessor methods.
    set r(newvalue) {
        var oldvalue = Math.sqrt(this.x*this.x + this.y*this.y);
        var ratio = newvalue/oldvalue;
        this.x *= ratio;
        this.y *= ratio;
    }
};

Object Attributes

Every object has associated prototype, class, and extensible attributes.

The prototype Attribute

var p = {x:1};
var o = Object.create(p);
p.isPrototypeOf(o)                  // => true: o inherits from p
Object.prototype.isPrototypeOf(o)   // => true: p inherits from Object.prototype

Object.getPrototypeOf(o) ;          // => Object { x=1}

The class Attribute

function classof(o) {
    if (o === null) return "Null";
    if (o === undefined) return "Undefined";
    return Object.prototype.toString.call(o).slice(8,-1);
}
classof(null)                       // => "Null"
classof(1)                          // => "Number"
classof("")                         // => "String"
classof(false)                      // => "Boolean"
classof({})                         // => "Object"
classof([])                         // => "Array"
classof(/./)                        // => "Regexp"
classof(new Date())                 // => "Date"
classof(window)                     // => "Window" (a client-side host object)
function f() {};
classof(new f());                   // => "Object"

The extensible Attribute

var p = {x:1};
Object.isExtensible(p)              // true
Object.preventExtensions(p)         // make object nonextensible
Object.isExtensible(p)              // false
p.y = 1                             // will not report error, but y is not added
p.y                                 // undefined
Object.seal(p)                      // object nonextensible, and all the own properties nonconfigurable.
Object.isSealed(p)                  // true
delete p.x                          // return false means cannot delete it
p.x                                 // still exist with value 1
Object.freeze(p)                    // besides seal, all data properties will be read only.
Object.isFrozen()                   // true

Object Methods

var o = {x:1, y:1};
s = o.toString() ;                  // "[object object]"
s = JSON.stringify(o)               // "{"x":1, "y":1}"
p = JSON.parse(s)                   // p is the deepcopy of o

p = new Number(3)
p.valueOf()                         // 3

JavaScript Array

Overview

JavaScript arrays are a specialized form of JavaScript object, and array indexes are really little more than property names that happen to be integers. What is special about arrays is that when you use property names that are non-negative integers less than 2^32 , the array automatically maintains the value of the length property for you. (JavaScript arrays are zero-based and use 32-bit indexes.)

JavaScript arrays are untyped: an array element may be of any type, and different elements of the same array may be of different types.

Array elements may even be objects or other arrays, which allows you to create complex data structures, such as arrays of objects and arrays of arrays.

JavaScript arrays are dynamic: they grow or shrink as needed and there is no need to declare a fixed size for the array when you create it or to reallocate it when the size changes.

JavaScript arrays may be sparse: the elements need not have contiguous indexes and there may be gaps.

Every JavaScript array has a length property. For nonsparse arrays, this property specifies the number of elements in the array. For sparse arrays, length is larger than the index of all elements.

Array Operators

Creating Arrays

var empty = [];                     // An array with no elements
var primes = [2, 3, 5, 7, 11];      // An array with 5 numeric elements
var misc = [ 1.1, true, "a", ];     // 3 elements of various types + trailing comma
var b = [[1,{x:1, y:2}], [2, {x:3, y:4}]];

var base = 1024;
var table = [base, base+1, base+2, base+3];

var count = [1,,3];         // An array with 3 elements, the middle one undefined.
var undefs = [,,];          // Normal array with 2 elements, both undefined.
var a = new Array(10)       // Sparse array, length is 10, indexs/elements are all undefined
var a = new Array(5, 4, 3, 2, 1, "testing, testing"); // array with these elements

Reading and Writing Array Elements

var a = ["world"];
var value = a[0];
a[1] = 3.14;
i = 2;
a[i] = 3;
a[i + 1] = "hello";

a[-1.23] = true;            // Invalid index number, this creates a property named "-1.23"
a["1000"] = 0;              // Valid index string, this the 1001st element of the array
a[1.000]                    // Valid index float, same as a[1]

Adding and Deleting Array Elements

a = []
a[0] = "zero";              // a = ["zero"]
a.push("one")               // Add a value at the end. a = ["zero", "one"]
a.push("two", "three")      // Add two more values. a = ["zero", "one", "two", "three"]

delete a[2]                 // Delete will not change lenght, lenght is still 4
a.length = 2                // Delete elements, a = ["zero", "one"]

Iterating Arrays

for(var i = 0, len = a.length ; i < len; i++) {
    if (!a[i]) continue;                // Skip null, undefined, and nonexistent elements
    if (a[i] === undefined) continue;   // Skip undefined + nonexistent elements
    if (!(i in a)) continue ;           // Skip nonexistent elements
    // loop body here
}

Array Type

Array.isArray([])           // => true
Array.isArray({})           // => false
Array.isArray{""}           // => false

Array Methods

join():

var a = [1, 2, 3];          // Create a new array with these three elements
a.join();                   // => "1,2,3"
a.join(" ");                // => "1 2 3"
var b = new Array(10);      // An array of length 10 with no elements
b.join('-')                 // => '---------': a string of 9 hyphens

reverse():

a.reverse()                 // a is now [3,2,1]

sort:

/* Always in dictionary order by default. Numbers will also be converted to string
   If an array contains undefined elements, they are sorted to the end of the array.
*/
["one", "two", undefined, "four"].sort()    // => ["four", "one", "two", undefined]
[11, 444, 2].sort();                            // => [11, 2, 444]
[11, 444, 2].sort(function(a,b) {return a-b;}); // => [2, 11, 444]

concat():

/* concat() will always create new array, but not to change the original array.
   If any of these arguments is itself an array, then it is the array elements that
   are concatenated, not the array itself.
*/
var a = [1,2,3];
a.concat(4, 5)              // return new array [1, 2, 3, 4, 5]
a.concat([4,5]);            // return new array [1, 2, 3, 4, 5]
a.concat(4, [5,[6,7]])      // return new array [1, 2, 3, 4, 5, [6,7]]

slice():

var a = [1,2,3,4,5];
a.slice(0,3);               // Returns [1,2,3]
a.slice(3);                 // Returns [4,5]
a.slice(1,-1);              // Returns [2,3,4]
a.slice(-3,-2);             // Returns [3]

splice():

/* Unlike slice() and concat() , splice() modifies the array on which it is invoked.
   Unlike concat() , splice() inserts arrays themselves, not the elements of them.
*/
var a = [1,2,3,4,5,6,7,8];
a.splice(4);                // Returns [5,6,7,8]; a is [1,2,3,4]
a.splice(1,2);              // Returns [2,3]; a is [1,4]

var a = [1,2,3,4,5];
a.splice(2,0,'a','b');      // Returns []; a is [1,2,'a','b',3,4,5]
a.splice(2,2,[1,2],3);      // Returns ['a','b']; a is [1,2,[1,2],3,3,4,5]

push()/pop():

/* The push() method appends one or more new elements to the end of an array and
   returns the new length of the array. The pop() method ddeletes the last element
   of an array, decrements the array length, and returns the value that it removed.
   Note that both methods modify the array in place rather than produce a new array.
*/
var stack = [];
stack.push("one", "two");   // stack = ["one", "two"], return 2
stack.pop();                // stack = ["one"], return "two"
stack.push([2, 3]);         // stack = ["one", [2, 3]], return 2
stack.pop();                // stack = ["one"], return [2, 3]

unshift()/shift():

/* The unshift() and shift() methods behave much like push() and pop() , except that
   they insert and remove elements from the beginning of an array.
*/
var a = [1, 2];
a.unshift(0);               // a = [0, 1, 2], return 3
a.shift()                   // a = [1, 2], return 0
a.unshift(3, [4, 5])        // a = [3, [4, 5], 1, 2], return 4

toString()/toLocalString():

[1,2,3].toString()          // => '1,2,3'
["a", "b", "c"].toString()  // => 'a,b,c'
[1, [2,'c']].toString()     // => '1,2,c'

Note

The following methods are defined in ECMAScript 5

forEach():

/*  function arguments: value[, index, array-itself]
*/
var data = [1,2,3,4,5];
var sum = 0;
data.forEach(function(value) { sum += value; });
sum                         // => 15
data.forEach(function(v, i, a) { a[i] = v + 1; });
data                        // => [2,3,4,5,6]

map():

/* Returns an new array containing the values returned by specified function.
   The same function arguments as forEach(), neet return in function.
*/
a = [1, 2, 3];
b = a.map(function(x) { return x*x; });             // b = [1, 4, 9]

filter():

/* Unlike map(), filter method will skips missing elements in sparse arrays
*/
a = [5, 4, 3, 2, 1];
b = a.filter(function(x) { return x < 3 });         // b = [2, 1]

var dense = sparse.filter(function() { return true; }); // return dense array

reduce()/reduceRight():

/* //first time with initial value
   function(firstElement, initialValue[, index=0, arrayitself])

   // first time without initial value
   function(firstElement, secondElement[, index=1, arrayitself])

   // other times when reducing
   function(lastReturnValue, nextElement[, index, arrayitself])

   reduceRight() works just like reduce() , except that it processes the array from
   highest index to lowest (right-to-left), rather than from lowest to highest.
*/
var a = [1,2,3,4,5]
var sum = a.reduce(function(x,y) { return x+y }, 0);     // Sum of values
var product = a.reduce(function(x,y) { return x*y }, 1); // Product of values
var max = a.reduce(function(x,y) { return (x>y)?x:y; }); // Largest value

function extend(o, p) {
    for (prop in p) {
        o[prop] = p[prop];
    }
    return o;
}
var a = [{x:1, a:1}, {y:2, a:2}, {z:3, a:3}];
var unionLeft = {}
var unionRight = {}                 // Please note the different value to a
a.reduce(extend, unionLeft)         // unionLeft = {x:1, a:3, y:2, z:3}
a.reduceRight(extend, unionRight)   // unionRight = {z:3, a:1, y:2, x:1}

every()/some():

/* Both every() and some() stop iterating array elements as soon as they know
   what value to return.
   every() returns true and some returns false when invoked on an empty array.
*/
a = [1,2,3,4,5];
a.every(function(x) { return x < 10; })         // => true: all values < 10.
a.every(function(x) { return x % 2 === 0; })    // => false: not all values even.
a.some(function(x) { return x % 2 === 0; })     // => true: a has some even numbers.

indexOf()/lastIndexOf():

/* indexOf() and lastIndexOf() search an array for an element with a specified value,
   and return the index of the first such element found, or –1 if none is found.
*/

a = [0,1,2,1,0];
a.indexOf(1)                        // => 1: a[1] is 1
a.lastIndexOf(1)                    // => 3: a[3] is 1
a.indexOf(3)                        // => -1: no element has value 3
a.indexOf(1,1)                      // => 3: a[3] is 1, begin the search at 1

JavaScript Function

Overview

Function names are often verbs or phrases that begin with verbs. It is a common con- vention to begin function names with a lowercase letter. When a name includes multiple words, one convention is to separate words with underscores like_this() ; another convention is to begin all words after the first with an uppercase letter likeThis() .

Function declaration statements are “hoisted” to the top of the enclosing script or the enclosing function, so that functions declared may be invoked from code that appears before they are defined. However, this is not true for functions defined as expressions, variable declarations are hoisted, variables are not hoisted, so functions defined with expressions cannot be invoked before they are defined.

If the return statement does not have an associated expression, it returns the undefined value. If a function does not contain a return statement, it return the undefined value to the caller.

Function declaration statements are not true statements, and the ECMAScript specification only allows them as top-level statements. They can appear in global code, or within other functions, but they cannot appear inside of loops, conditionals, or try/catch/finally or with statements. Note that this restriction applies only to functions declared as statements. Function definition expressions may appear anywhere in your JavaScript code. (But firefox allows define function in if statement)

In JavaScript, however, functions are not only syntax but also values, which means they can be assigned to variables, stored in the properties of objects or the elements of arrays, passed as arguments to functions, and so on.

Defining/Invoking Functions

declaration statement/definiton expression:

function functionName(arg1, arg2[, argN, ...]) {
    //statements
    return [value]  //optional
}

// Function expressions can include names, which is useful for recursion.
var f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); };

// Function expressions are sometimes defined and immediately invoked:
var tensquared = (function(x) {return x*x;}(10));

Invoked ways:

/* JavaScript functions can be invoked in four ways:
- as functions,
- as methods,
- as constructors,
- indirectly through their call() and apply() methods.
*/

var total = distance(0,0,2,1) + distance(2,1,3,5);

o.m(x, y);  // m is method of object o

var o = new Object();
var o = new Object;     //only when the constructor function has no args.

f.call(o, x, y)   // f is not method of o, but want use o as invocation context.

method chaining:

// If object methods always return 'this' (the object itself)
shape.setX(100).setY(100).setSize(50).setOutline("red").setFill("blue").draw();

Constructor Invocation

If a function or method invocation is preceded by the keyword new , then it is a constructor invocation. Constructor invocations differ from regular function and method invocations in their handling of arguments, invocation context, and return value.

You can always omit a pair of empty parentheses in a constructor invocation. If a constructor has no parameters, then JavaScript constructor invocation syntax allows the argument list and parentheses to be omitted entirely.

A constructor invocation creates a new, empty object that inherits from the prototype property of the constructor. Constructor functions are intended to initialize objects and this newly created object is used as the invocation context, so the constructor function can refer to it with the this keyword.

Constructor functions do not normally use the return keyword. They typically initialize the new object and then return it. If a constructor explicitly used the return statement to return an object, then that object becomes the value of the invocation expression. But if the constructor uses return with no value, or if it returns a primitive value, that return value is ignored and the new object is used as the value of the invocation.

Function Arguments and Parameters

JavaScript function definitions do not specify an expected type for the function pa- rameters, and function invocations do not do any type checking on the argument values you pass. In fact, JavaScript function invocations do not even check the number of arguments being passed.

Optional Parameters

When a function is invoked with fewer arguments than declared parameters, the additional parameters are set to the undefined value:

function getPropertyNames(o, /* optional */ a) {
    a = a || []; // If undefined, use a new array
    for(var property in o) a.push(property);
    return a;
}

Note

When designing functions with optional arguments, you should be sure to put the optional ones at the end of the argument list. The comment “optional” in the function definition to emphasize the fact that the parameter is optional.

Variable-Length Argument Lists

When a function is invoked with more argument values than declared parameter, names, the additional arguments cannot be read by names, but the Arguments object “arguments” refers to all the arguments. “arguments” is not a array, but it happens to have number indexes.

function max(initialValue, /* numbers ... */) {
    var max = initialValue;   //or arguments[0]

    // Loop through the arguments, looking for other arguments.
    for(var i = 1; i < arguments.length; i++) {
        if (arguments[i] > max) max = arguments[i];
    }
    return max;
}

There are also “callee” and “caller” properties in Arguments object: - arguments.callee refers to this currently running function. - arguments.caller refers to the function that called this one.

Using Object Properties As Arguments

When a function has more than three parameters, it becomes difficult for the programmer who invokes the function to remember the correct order in which to pass arguments.

function easycopy(args) {
    if (isArray(args.from) && isArray(args.to)) {
        arraycopy(args.from,
            args.from_start || 0, // Note default value provided
            args.to,
            args.to_start || 0,
            args.length);
    }
    else throw new Error("argument from and to must be array!");
}
// Here is how you might invoke easycopy():
var a = [1,2,3,4], b = [];
easycopy({from: a, to: b, length: 4});

Properties of Function

length Function itself also has length, you can access it like this: “functionName.length” or “arguments.callee.length”

prototype Every function(except the one return by bind) will have this property. It’s used when invoked as constructor, and class inheritance.

“prototype” will auto have a “constructor” property. F.prototype.constructor===F is true for any function.

Defining Your Own Function Properties Function is a specialized kind of object, which means that functions can have properties. Sometimes, it is better to store the information in a property of the Function object instead of cluttering up the name space by defining a global variable.

// Compute factorials and cache results as properties of the function itself.
function factorial(n) {
    if (isFinite(n) && n>0 && n==Math.round(n)) {   // Finite, positive ints only
        if (!(n in factorial))                      // If no cached result
            factorial[n] = n * factorial(n-1);      // Compute and cache it
        return factorial[n];                        // Return the cached result
    }
    else return NaN;                                // If input was bad
}
factorial[1] = 1;                   // Initialize the cache to hold this base case.

Methods of Function

call()/apply():

functionName.call(object, arg1, arg2, ...argN)
functionName.apply(object, [arg1, arg2, ...argN])  # arguments list

bind():

var g = f.bind(o[,args]); // g(args...) is equal to o.f(args...)

function f(y,z) { return this.x + y + z };
var g1 = f.bind({x:1});              // Bind object as this only
var g2 = f.bind({x:1}, 2);           // Bind this and y
g1(2, 3)                 // => 6: this.x is bound to 1, y is 2 and z is 3
g2(3)                    // => 6: this.x is bound to 1, y is bound to 2 and z is 3

toString():

f.toString();            // => '[native code]'

Function():

var f = new Function("x", "y", "return x*y;");

Note

There are a few points that are important to understand about the Function() constructor:

  • The Function() constructor allows JavaScript functions to be dynamically created and compiled at runtime.
  • The Function() constructor parses the function body and creates a new function object each time it is called. If the call to the constructor appears within a loop or within a frequently called function, this process can be inefficient. By contrast, nested functions and function definition expressions that appear within loops are not recompiled each time they are encountered.
  • The Function() constructor creates functions which do not use lexical scoping; instead, they are always compiled as if they were top-level functions, use global object as invoked context.

Functions As Namespaces

Sometimes, it’s useful to define a function simply to act as a temporary namespace in which you can define variables without polluting the global namespace.

var some = (function() { // function as module or namespace
    // Module code goes here.
    return somethings
}());       // end the function literal and invoke it now.

this

Note that this is a keyword, not a variable or property name. JavaScript syntax does not allow you to assign a value to this .

For function invocation in ECMAScript 3 and nonstrict ECMAScript 5, the invocation context (the this value) is the global object. In strict mode, however, the invocation context is undefined .

Functions written to be invoked as functions do not typically use the this keyword at all. It can be used, however, to determine whether strict mode is in effect:

// Define and invoke a function to determine if we're in strict mode.
var strict = (function() { return !this; }());

When a function is invoked on or through an object, that object is the invocation context or this value for the function.

Unlike variables, the this keyword does not have a scope, and nested functions do not inherit the this value of their caller. If a nested function is invoked as a method, its this value is the object it was invoked on. If a nested function is invoked as a function then its this value will be either the global object (non-strict mode) or undefined (strict mode). It is a common mistake to assume that a nested function invoked as a function can use this to obtain the invocation context of the outer function. If you want to access the this value of the outer function, you need to store that value into a variable that is in scope for the inner function. It is common to use the variable self for this purpose. For example:

var o = {
    m: function() {
        var self = this;                // Save the this value in a variable.
        console.log(this === o);        // true, if called by o.m()

        function f() {                  // A nested function f
            console.log(this === o);    // false, this is global object or undefined.
            console.log(self === o);    // true, self is the this of outer function.
        }

        f();
    }
};
o.m();

Note that the new object is always set as the invocation context even if the constructor invocation looks like a method invocation. For example:

// o.m() is used as constructor, o is not used as the invocation context, it's p.
p = new o.m()

closure

Like most modern programming languages, JavaScript uses lexical scoping. This means that functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked. In order to implement lexical scoping, the internal state of a JavaScript function object must include not only the code of the function but also a reference to the current scope chain. This is an old term that refers to the fact that the function’s variables have bindings in the scope chain and that therefore the function is “closed over” its variables.

This combination of a function object and a scope (a set of variable bindings) in which the function’s variables are resolved is called a closure in the computer science literature.

Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them.

Closures become interesting when they are invoked under a different scope chain than the one that was in effect when they were defined. This happens most commonly when a nested function object is returned from the function within which it was defined. common in JavaScript programming.

In C language, function’s local variables are defined on a CPU stack, then they would indeed cease to exist when the function returned. But JavaScript described it as a list of objects.

Each time a JavaScript function is invoked, a new object is created to hold the local variables for that invocation, and that object is added to the scope chain. When the function returns, that variable binding object is removed from the scope chain. If there were no nested functions, there are no more references to the binding object and it gets garbage collected. If there were nested functions defined, then each of those functions has a reference to the scope chain, and that scope chain refers to the variable binding object.

If those nested functions objects remained within their outer function, however, then they themselves will be garbage collected, along with the variable binding object they referred to. But if the function defines a nested function and returns it or stores it into a property somewhere, then there will be an external reference to the nested function. It won’t be garbage collected, and the variable binding object it refers to won’t be garbage collected either.

Example 1:

var scope = "global scope";         // A global variable
function checkscope() {
    var scope = "local scope";      // A local variable
    function f() { return scope; }
    return f;
}

/* Remember the fundamental rule of lexical scoping: JavaScript functions are executed
using the scope chain that was in effect when they were defined. */
checkscope()();                     // It should return "local scope" here.

Example 2:

// Function declarations are hoisted so we can do this assignment here.
uniqueInteger.counter = 0;

// This function returns a different integer each time it is called.
function uniqueInteger() {
    return uniqueInteger.counter++; // Increment and return counter property
}

/* The above version has one problem, uniqueInteger.counter can be changed out of function.
   So, rewrite the uniqueInteger() function using closures.
*/
var uniqueInteger = (function() {                   // Define and invoke immediately
                        var counter = 0;            // Private state of function below
                        return function() { return counter++; };
                    }());                // no way to access counter after function return

Example 3:

/* Two or more nested functions to be defined within the same outer function
   will share the same scope chain.
*/
function counter(n) {
    return {
        count: function() { return n++; },
        reset: function() { n = 0; }
    };
}
var c = counter(0), d = counter(0); // two counters with two copies of scope chains
c.count()                           // => 0
d.count()                           // => 0: they count independently
c.reset()                           // reset() and count() methods share state
c.count()                           // => 0: because we reset c
d.count()                           // => 1: d was not reset

Note

As what mentioned above, nested functions in closure function will not share ‘this’ and ‘arguments’ of the outer function, except that we save them by other variables.

JavaScript Classes

Define Class by Constructors/Prototype

The prototype object is fundamental to the identity of a class: two objects are instances of the same class if and only if they inherit from the same prototype object.

The constructor function that initializes the state of a new object is not fundamental: two constructor functions may have prototype properties that point to the same prototype object. Then both constructors can be used to create instances of the same class.

function Range(from, to) {
    // Store the start and end points (state) of this new range object.
    // These are noninherited properties that are unique to this object.
    this.from = from;
    this.to = to;
}

// Extend the predefined Range.prototype object so we don't overwrite
// the automatically created Range.prototype.constructor property.
// All Range objects inherit from this object.
// Note that the property name must be "prototype" for this to work.
Range.prototype.includes = function(x) {
    return this.from<=x && x<=this.to;
};
Range.prototype.foreach = function(f) {
    for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);
};
Range.prototype.toString = function() {
    return "(" + this.from + "..." + this.to + ")";
};

// Here are example uses of a range object
var r = new Range(1,3);             // Create a range object
r.includes(2);                      // => true: 2 is in the range
r.foreach(console.log);             // => "1 2 3"
r.toString();                       // => "(1...3)"

Java-Style Classes in JavaScript

Constructor object: The constructor function (an object) defines a name for a JavaScript class.

Properties you add to this constructor object serve as class fields and class methods (depending on whether the property values are functions or not). But these properties of constructor are not inheritable.

Prototype object: The properties of this object are inherited by all instances of the class, and properties whose values are functions behave like instance methods of the class.

Instance object: Each instance of a class is an object in its own right, and properties defined directly on an instance are not shared by any other instances. Nonfunction properties defined on instances behave as the instance fields of the class.

Augmenting Classes

JavaScript’s prototype-based inheritance mechanism is dynamic: an object inherits properties from its prototype, even if the prototype changes after the object is created. This means that we can augment JavaScript classes simply by adding new methods to their prototype objects.

JavaScript Regular Expressions

Just as string literals are specified as characters within quotation marks, regular expression literals are specified as characters within a pair of slash ( / ) characters.

var pattern = /s$/;
var pattern = new RegExp("s$");
var pattern = new RegExp("\\d{5}", "g");

// RegExp can create regular expression dynamically in runtime
var something;               // Maybe some thing from user.
var pattern = new RegExp(something)

Regular-expression literal characters

=============== ================================================================
Character       Matches
=============== ================================================================
Alphanumeric    character Itself
\0              The NUL character (\u0000)
\t              Tab (\u0009 )
\n              Newline ( \u000A )
\v              Vertical tab ( \u000B )
\f              Form feed ( \u000C )
\r              Carriage return ( \u000D )
\xnn            The hexadecimal number; \x0A == \n
\uxxxx          The hexadecimal number Unicode; \u0009 == \t
\cX             The control character ^X ; \cJ == \n
=============== ================================================================

Regular expression character classes

=============== ================================================================
Character       Matches
=============== ================================================================
[...]           Any one character between the brackets.
[^...]          Any one character not between the brackets.
.               Any character except newline or another Unicode line terminator.
\w              Any ASCII word character.
\W              Any character that is not an ASCII word character.
\s              Any Unicode whitespace character.
\S              Any character that is not Unicode whitespace.
\d              Any ASCII digit. Equivalent to [0-9] .
\D              Any character other than an ASCII digit. Equivalent to [^0-9] .
[\b]            A literal backspace (special case).
=============== ================================================================

Regular expression repetition characters

=============== ================================================================
Character       Meaning
=============== ================================================================
{n, m}          Match previous item at least n times but no more than m times.
{n,}            Match the previous item n or more times.
{n}             Match exactly n occurrences of the previous item.
?               Match zero or one occurrences of the previous item. {0,1}
+               Match one or more occurrences of the previous item. {1,}
*               Match zero or more occurrences of the previous item. {0,}
=============== ================================================================

Note

The repetition characters listed above table match as many times as possible while still allowing any following parts of the regular expression to match. We say that this repetition is “greedy.”

It is also possible to specify that repetition should be done in a nongreedy way. Simply follow the repetition character or characters with a question mark: ?? , +? or even {1,5}? .

Match of /a+?b/ in ‘aaab’ still return ‘aaab’ because start at first ‘a’.

Regular expression alternation, grouping, and reference characters

=============== ================================================================
Character       Meaning
=============== ================================================================
|               Alternation. Match either the subexpression to the left or
                the subexpression to the right.
(...)           Grouping. Group items into a single unit that can be used with
                * , + , ? , | , and so on. Also remember the characters
                that match this group for use with later references.
(?:...)         Grouping only. Group items into a single unit, but do not
                remember the characters that match this group.
\n              Match the same characters that were matched when group number n
                was first matched.
                Groups are subexpressions within (possibly nested) parentheses.
                Group numbers are assigned by counting left parentheses from
                left to right. Groups formed with (?: are not numbered.
=============== ================================================================

Examples:

/ab|cd|ef/          // matches “ab” or “cd” or “ef”.
/\d{3}|[a-z]{4}/    // matches either three digits or four lowercase letters.


/java(script)?/     // matches “java” followed by the optional “script”.
/(ab|cd)+|ef/       // matches either the string “ef” or one or more
                    // repetitions of either of the strings “ab” or “cd”.

/([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/    // ([Ss]cript) is referred to as \2
/(['"][^'"]*\1)                          // matches '.*' or ".*"

Regular-expression anchor characters

=============== ================================================================
Character       Meaning
=============== ================================================================
^               Match beginning of string. (or line in multiline searches)
$               Match the end of string. (end of a line in multiline searches)
\b              Match a word boundary. (Note: [\b] matches backspace.)
\B              Match a position that is not a word boundary.
(?=p)           A positive lookahead assertion.
                Require that the following characters match the pattern p,
                but do not include those characters in the match.
(?!p)           A negative lookahead assertion.
                Require that the following characters don't match the pattern p.
=============== ================================================================

Examples:

/\B[Ss]cript/       // Matches "JavaScript" and "postscript", but not "script".

/[Jj]ava([Ss]cript)?(?=\:)/         // Matches the word "JavaScript" in
                    "JavaScript: The Definitive Guide", but it does not match
                    "Java" in "Java in a Nutshell".

/Java(?!Script)/    // Matches "Java" in "JaveBeans" but null in "JavaScript"

Regular-expression flags

=============== ================================================================
Character       Meaning
=============== ================================================================
i               Perform case-insensitive matching.
g               Perform a global match—that is, find all matches.
m               Multiline mode. ^/$ matche beginning/end of line or string.
=============== ================================================================

Examples:

/java$/im   // Matches “java” as well as “Java\nis fun”

RegExp Properties

source: Read-only string that contains the text of the regular expression.

global: Read-only boolean value that specifies whether the regular expression has the g flag.

ignoreCase: Read-only boolean value that specifies whether the regular expression has the i flag.

multiline: Read-only boolean value that specifies whether the regular expression has the m flag.

lastIndex: Read/write integer. For patterns with the g flag, it stores the position in the string at which the next search is to begin. It is used by the exec() and test() methods

RegExp Methods

exec():

var pattern = /Java/g;
var text = "JavaScript is more fun than Java!";
var result;
while((result = pattern.exec(text)) != null) {
    alert("Matched '" + result[0] + "'" +
    " at position " + result.index +
    "; next search begins at " + pattern.lastIndex);
}

test():

var pattern = /java/i;
pattern.test("JavaScript"); // Returns true

Shell Variables

Internal Variables:

$SHELL                  Current shell name, such as "/bin/bash"
$PPID                   Parent PID
$UID                    User ID, specially, root UID is zero
$RANDOM                 Return a random number
$IFS                    shell separator character, default value is "\ "
$PATH                   System path
$PWD                    Current directory
$HOME                   Home directory
$SECONDS                time from it begin to run
$LINENO                 Current line number
$FUNCNAME               Current function name
$BASH_LINENO            Line number where this function is called

$$                      Current PID
$!                      PID of the last process which running in the background
$#                      Number of parameters
$?                      Command or script return value
$0                      Script or function name which is called.
$1                      Ther first parameter, $N means the Nth parameter
$*                      all parameters
“$*”                    "$1 $2 $3 ..."
“$@”                    "$1" "$2" "$3" ...

Wildcard Variables:

[[:alnum:]]             all number characters
[[:digit:]]             all number characters
[[:xdigit:]]            all hex number characters
[[:alpha:]]             all letter characters
[[:lower:]]             all lower letter characters
[[:upper:]]             all upper letter characters
[[:punct:]]             all punctuation characters
[[:graph:]]             all nonblank characters
[[:space:]]             all space characters
[[:blank:]]             all blank characters, such as whitespace and tab
[[:cntrl:]]             all control characters
[[:print:]]             all printable characters

Wildcard Variables:

$variable              variable value
${variable}            variable value, separate name from the following letters
${variable:n:m}        part of variable string, start at n, lenght is m
${variable:n}          part of variable string, from the n to the end
${#variable}           length of the variable string

${variable:?message}   If the variable exists and is not NULL, returen it,
                       otherwise output the message and exit the script.
${variable:=word}      If the variable exists and is not NULL, returen it,
                       otherwise set the variable to word and return the word.
${variable:-word}      If the variable exists and is not NULL, returen it,
                       otherwise return ther word, variable is not changed.
${variable:+word}      If the variable exists and is not NULL, return the word,
                       otherwise return NULL.

${variable%.*}         From right to left, match ".*", then remove this part.
                       e.g. if variable="file-v1.0.txt", then return "file-v1.0"
${variable%%.*}        From right to left, match ".*" as long as possible, then
                       remove this part. e.g. if variable="file-v1.0.txt",
                       then return "file-v1"
${variable#*.}         From left to right, match "*.", then remove this part,
                       e.g. if variable="file-v1.0.txt", then return "0.txt"
${variable##*.}        From left to right, match "*." as long as possible, then
                       remove this part. e.g. if variable="file-v1.0.txt",
                       then return ".txt"
${variable/patt/str}   Replace pattern matching part with string.
${variable//patt/str}  Replace pattern matching part (as long as possible) with string.

Variables expression:

let result=no1+no2
let i++
result=$[ $no1 +  $no2 ]
result=$(($no1 +  $no2))
result=`expr 3+4`
result=$(expr $no1 + 5)

Shell Test And Compoare

File test:

-b  File is block special device (for files like /dev/hda1)
-c  File is character special (for files like /dev/tty)
-d  File is a directory
-e  File exists
-f  File is a regular file
-g  File has its set-group-ID bit set
-h  File is a symbolic link (same as -L)
-G  File is owned by the effective group ID
-k  File has its sticky bit set
-L  File is a symbolic link (same as -h)
-O  File is owned by the effective user ID
-p  File is a named pipe
-r  File is readable
-s  File has a size greater than zero
-S  File is a socket
-u  File has its set-user-ID bit set
-w  File is writable
-x  File is executable

Variable Test:

-lt         <               Less than
-le         <=              Less than or equal to
-gt         >               Greater than
-ge         >=              Greater than or equal to
-eq         =, ==           Equal to
-ne         !=              Not equal to

-n "$var"               Variable is not empty
-z "$var"               Varibale is empty

Examples:

if [ -r $FILE -a -w $FILE ]
if [ -z "$V1" -o -z "${V2:=YIKES}" ]
if [[ "${MYFILENAME}" == *.jpg ]]
if [[ "$FN" == *.@(jpg|jpeg) ]]
if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)- ([[:digit:]]*) - (.*)$" ]]

Shell Terminal

terminal color:

ESC="\e" or "\033"

ESC[0m       # reset all (colors and brightness)
ESC[1m       # bright
ESC[2m       # dim (looks same as normal brightness)
ESC[22m      # normal brightness

# FOREGROUND:
ESC[30m      # black
ESC[31m      # red
ESC[32m      # green
ESC[33m      # yellow
ESC[34m      # blue
ESC[35m      # magenta
ESC[36m      # cyan
ESC[37m      # white
ESC[39m      # reset

# BACKGROUND
ESC[40m      # black
ESC[41m      # red
ESC[42m      # green
ESC[43m      # yellow
ESC[44m      # blue
ESC[45m      # magenta
ESC[46m      # cyan
ESC[47m      # white
ESC[49m      # reset

Other Control code:

ESC[4m       # under line
ESC[5m       # blink
ESC[7m       # enable echo
ESC[8m       # disable echo
ESC[nA       # move up <n> lines
ESC[nB       # move up <n> lines
ESC[nC       # move right <n> colums
ESC[nD       # move left <n> colums
ESC[y;xH     # set the cursor position
ESC[2J       # clear full screen
ESC[K        # clear from current to end of the line
ESC[s        # save the cursor position
ESC[u        # restore the cursor position
ESC[?25l     # hidden the cursor
ESC[?25h     # display the cursor

References

Linux Shell Sed

Exampes

# & means the matched pattern 'aaa'.
sed -e 's/aaa/+&+/g input.txt

# Multi command be be executed together.
sed -e '2d;s/aaa/eee/g' input.txt  #or
sed -e '2d' -e 's/aaa/eee/g' input.txt

#If in script file with -f option, {} is used to
execute multi line commands.

#If not last line, append to one line
#Otherwise for the last line, replace \n to ''.
:loop
N
$!b loop
s/\n//g

sed [OPTION]… {script-only-if-no-other-script} [input-file]…

OPTIONS

Popular Options:

-n, --quiet, --silent
   suppress automatic printing of pattern space
-e script, --expression=script
-f script-file, --file=script-file
-i[SUFFIX], --in-place[=SUFFIX]
   edit files in place (makes backup if SUFFIX supplied)
-l N, --line-length=N
   specify the desired line-wrap length for the `l' command
--posix
   disable all GNU extensions.
-r, --regexp-extended
   use extended regular expressions in the script.

Addresses

Sed commands can be given with no address, one address or two addresses as range.

  • With no addresses, the command will be executed for all input lines;
  • With one address, the command will only be executed for input lines which match that address;
  • With two addresses, the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address.

Three things to note about address ranges:

  • The syntax is addr1,addr2 (i.e., the addresses are separated by a comma);
  • The line which addr1 matched will always be accepted, even if addr2 selects an earlier line;
  • If addr2 is a regexp, it will not be tested against the line that addr1 matched.

After the address (or address-range), and before the command, a ! may be inserted, which specifies that the command shall only be executed if the address (or address-range) does not match.

The following address types are supported:

number Match only the specified line number (which increments cumulatively across files, unless the -s option is specified on the
       command line).

first~step
       Match every step'th line starting with line first.  For example, ``sed -n 1~2p'' will print all the odd-numbered lines in
       the input stream, and the address 2~5 will match every fifth line, starting with the second.

$      Match the last line.

/regexp/
       Match lines matching the regular expression regexp.

0,addr2
       Start  out  in  "matched  first  address"  state,  until addr2 is found.  This is similar to 1,addr2, except that if addr2
       matches the very first line of input the 0,addr2 form will be at the end of its range, whereas the 1,addr2 form will still
       be at the beginning of its range.  This works only when addr2 is a regular expression.

addr1,+N
       Will match addr1 and the N lines following addr1.

addr1,~N
       Will match addr1 and the lines following addr1 until the next line whose input line number is a multiple of N.

COMMAND

Zero-address commands:

   : label     Label for b and t commands.
   #comment    The comment extends until the next newline
   }           The closing bracket of a { } block.

Zero- or One- address commands::

   =           Print the current line number.
   a text      Append text, which has each embedded newline preceded by a backslash.
   i text      Insert text, which has each embedded newline preceded by a backslash.
   q [exit-code]   Immediately  quit  the sed script without processing any more input,
               except that if auto-print is not disabled the current pattern space will be printed.
   Q [exit-code]   Immediately quit the sed script without processing any more input.
   r filename  Append text read from filename.
   R filename  Append a line read from filename.  Each invocation of the command
               reads a line from the file.  This is a GNU extension.

Commands which accept address ranges:

{           Begin a block of commands (end with a }).
b label     Branch to label; if label is omitted, branch to end of script.
c text      Replace the selected lines with text, which has each embedded newline preceded by a backslash.
d           Delete pattern space.  Start next cycle.
D           If pattern space contains no newline, start a normal new cycle
            as if the d command was issued.  Otherwise, delete text in the
            pattern space up to the first newline, and restart cycle with
            the resultant pattern space, without reading a new line of input.
h H         Copy/append pattern space to hold space.
g G         Copy/append hold space to pattern space.
l           List out the current line in a ``visually unambiguous'' form.
l width     List out the current line in a ``visually unambiguous'' form,
            breaking it at width characters.  This is a GNU extension.
n N         Read/append the next line of input into the pattern space.
p           Print the current pattern space.
P           Print up to the first embedded newline of the current pattern space.
s/regexp/replacement/
            Attempt to match regexp against the pattern space. If successful,
            replace that portion  matched  with  replacement.  The replacement
            may contain the special character & to refer to that portion of the
            pattern space which matched, and the special escapes \1 through \9
            to refer to the corresponding matching sub-expressions in the regexp.
y/source/dest/
            Transliterate the characters in the pattern space which appear
            in source to the corresponding character in dest.
t label     If a s/// has done a successful substitution since the last input
            line was read and since the last t or T command,  then branch to
            label; if label is omitted, branch to end of script.
T label     If no s/// has done a successful substitution since the last input
            line was read and since the last t or T command, then branch to label;
            if label is omitted, branch to end of script.
w filename  Write the current pattern space to filename.
W filename  Write the first line of the current pattern space to filename.
x           Exchange the contents of the hold and pattern spaces.

Shell Magic Commands

Daily Commands

  1. Run some thing in the background screen session

    screen -d -m -S session_name "comman"

    See also

    screen --help or tmux --help

  2. Run the last command by root account

    sudo !!

  3. Go to the last cd history directory.

    cd -

  4. Replace in last command and then run.

    ^old^new

  5. Show ASCII Table

    man ascii

  6. find and rm

    find ./ -name "xxx.xx" -exec rm -rf {} \;

  7. ssh remote command, no need to copy script to server

    ssh user@server bash </path/to/script.sh

Network Commands

  1. port monitor

    netstat -tlnp

  2. Get the external IP of this host

    curl ifconfig.me

Shell Project

Self Decompress

Example:

#! /bin/bash

UNZIP_DIR=`mktemp -d /tmp/mytool.$$.XXXX`
PAYLOAD_OFFSET=`grep -an -m1 "^ARCHIVE_MARKER:" $0 | cut -d: -f1`

tail -n +$((PAYLOAD_OFFSET+1)) $0 | tar zxf - --ignore-command-error -C ${UNZIP_DIR} 2>/dev/null
exec ${UNZIP_DIR}/mytool.sh "$@"
exit $?

ARCHIVE_MARKER:
...#The tar file here

Shell Switch Root

chroot

Example:

cd $ROOT
mount -t proc proc proc
mount -t sysfs sys sys
mount -t devtmpfs devtmpfs dev
chroot $ROOT /bin/systemd-tmpfiles --create --remove --boot >/dev/null 2>&1

chroot $ROOT <command-and-args-doing-something>
RET=$?

chroot $ROOT /bin/systemd-tmpfiles --clean >/dev/null 2>&1
umount -l dev
umount -l sys
umount -l proc

exit $RET

switch_root

Usually, it’s used in initramfs to switch to the real root filesystem. switch_root moves already mounted /proc, /dev, /sys and /run to newroot and makes newroot the new root filesystem and starts init process.

Example:

exec /sbin/switch_root "$ROOTMNT" /sbin/init $@

Python Parallel

Example 1:

#!/bin/bash

SUB_PROCESS_NUM=8
TMPFILE="/tmp/$$.fifo"

# Open w/r FIFO on file handler 9
mkfifo $TMPFILE
exec 9<>$TMPFILE

for ((i=0; i<$SUB_PROCESS_NUM; i++)) ; do
    echo ""
done >&9

for ((i=0; i<20; i++)) ; do
    read -u 9
    {   # do something here
        echo "${i} start------------------------------"
        sleep 1
        echo "${i} exit-------------------------------"

        # must add new line to enable another sub-process
        echo "" >&9
    } &
done

# wait for all background process done and exit.
wait
exec 9>&-
rm -f $TMPFILE

Example 2:

task_start() {
    local name="$1"

    touch $TMPDIR/${name}.monitor_running
    while [ -e "$TMPDIR/${name}.monitor_running" ] ; do
        ...
        # add_task $other_task_name $action
    done
}

task_stop() {
    local name="$1"
    rm -rf $TMPDIR/${name}.monitor_running
}

add_task() {
    local name=$1
    local action=$2
    grep -o "$name.$action" $JOBFILE >&- 2>&- || {
        echo "$name.$action" >> $JOBFILE 2>&-
    }
}

# Process each task in the $jobfile in FIFO order
do_tasks() {
    local line queued_task

    if [ -f $JOBFILE ] ; then
        mv $JOBFILE ${JOBFILE}.work
        while read line; do
            execute_task() {
                case $2 in
                    "action1") task_start $action2_task_name &;;
                    "action2") task_start $action1_task_name &;;
                    *) DBG_ERROR "## Unknown task command: $2 ##";;
                esac
            }
            queued_task=$(echo $line | awk -F "." '{print $1,$2}')
            execute_task $queued_task
        done < ${JOBFILE}.work
        rm -rf ${JOBFILE}.work
    fi
}

task_loop() {
    task_start $first_task_name &

    while [ "$task_daemon_running" == 1 ] ; do
        do_tasks
        sleep 1
    done
}

Shell Opensource

Awesome-shell: https://github.com/alebcay/awesome-shell

Git Quickstart

https://git-scm.com/book

Installation

For example, in Ubuntu:

sudo apt-get install git
sudo apt-get install git-doc git-svn git-email git-gui gitk
sudo apt-get install gitg
sudo apt-get install qgit
sudo apt-get install kdiff3

Get help

git help [command]

Configuration

git config --global user.name "myname"
git config --global user.email "my@example.com"
git config --global core.editor vim
git config --global color.ui true
git config --global merge.tool kdiff3
git config --global pull.rebase true
git config --global commit.template "~/.gitmessage"

# For current user only
git config --global alias.st status
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

# For all user
sudo git config --system alias.st status
sudo git config --system alias.ci commit
sudo git config --system alias.co checkout
sudo git config --system alias.br branch

# Get current repo settings
git config --get remote.origin.url
git config -f path-to-repo/.git/config --get remote.origin.url
git ls-remote <rempte-origin-url> refs/heads/master #remote head id
git ls-remote ./ refs/heads/master                  #local head id

git-extras

Install: sudo apt-get install git-extras

Usage: https://github.com/tj/git-extras/blob/master/Commands.md

Git Commands

Complete the command by ‘tab’

git --version                       #Prints the Git suite version

git config -e                       #edit .git/config
git config -e --global              #edit ~/.gitconfig
git config -e --system              #edit /etc/gitconfig
git config a.b                      #get a.b in .git/config
git config --global a.b something   #set a.b in ~/.gitconfig
git config --unset a.b              #remove a.b

git add hello.c                     #Add a single file to stage
git add doc/\*.txt                  #Add all *.txt file
git add -A                          #Add all the modified, deleted and new files
git add -i                          #Add modified contents in the working tree interactively to the index.
git add -p [filename]               #equal to -i and then select the patch command
        stage this hunk [y,n,q,a,d,/,s,e?]
           y - stage this hunk
           n - do not stage this hunk
           q - quit; do not stage this hunk nor any of the remaining ones
           a - stage this hunk and all later hunks in the file
           d - do not stage this hunk nor any of the later hunks in the file
           g - select a hunk to go to
           / - search for a hunk matching the given regex
           j - leave this hunk undecided, see next undecided hunk
           J - leave this hunk undecided, see next hunk
           k - leave this hunk undecided, see previous undecided hunk
           K - leave this hunk undecided, see previous hunk
           s - split the current hunk into smaller hunks
           e - manually edit the current hunk
           ? - print help

git clean -fd                       #Clear all unmanaged files
git clean -fX                       #Clear all the files defined in .gitignore
git checkout .                      #Clear all changes to the managed files

git commit -s                       #Add signoff line automatically, and need to add log message in editor.
git commit -m "log message"         #Commit with log message without pop-up editor.
git commit --amend                  #Update the log message in last commit
git commit --amend --allow-empty --reset-author   #Update the author in last commit

git checkout master                 #checkout master branch
git checkout .                      #clear all the changes to the managed file in workspace
git checkout -- filename            #checkout single file
git checkout branchname -- filename #checkout file in other branch, both stage and workspace will be changed.
git checkout -b branchname          #create and switch to the new branch

git reset --soft <commit>           #reset HEAD refernce, but not the content
git reset --soft HEAD^              #revert the git commit
git reset --hard HEAD^              #reset both reference and content changed.
git reset --hard master@{2}
git reset [HEAD]                    #revert git add, reset what are not committed.
git reset HEAD filename             #reset single file in stage

git clone
git push
git pull
git pull --rebase                   #rebase
git merge <commit>                  # merge current HEAD and commit
git cherry-pick <commit>            #pick commit in any branch and put it after current HEAD
git revert HEAD                     #revert itself is a commit

git rebase --autostash              #Stash changes before rebasing

git grep --line-number "something"  #grep in tracked files

git status                          #option -s for short version
git status --ignored                #show the ignored files list at the same time

git config user.name [value]        #no value means get value, otherwise set the value
git config --luser.name

git log --pretty=fuller
git log --pretty=oneline            #equal to --oneline
git log --pretty=raw
git log --graph --oneline
git log -p HEAD                     #-p is to show the diff patch in each commit
git log --stat HEAD                 #show what files are changed
git log --oneline --decorate        #Show all tags and other references
git log -3
git log ^HEAD~3 HEAD
git log HEAD~3..HEAD
git log --pretty=short --decorate   #Show commit log together with ref names, such as tags.
git log --format="%h | %s | %d"     #Show log in "Hash | Subject | Ref-names" format
git log Branch1 ^Branch2            #Show commit which in Branch1 but not in Branch2
git log --all --grep 'something'    #Show commit log which match the special text.
git log -- filename                 #Show commit log related to special file.

git shortlog                        #Show summary only, but grouped by author.

git cherry -v master                #Show all commits which are not merged to master yet.

git describe --tags --abbrev=0      #Show the last tag

git show HEAD --stat
git show-ref
git show <branch_name>:<file_name>  #Show file in special branch

git diff                            #workspace to stage
git diff --cached                   #stage to remote
git diff HEAD                       #workspace to remote
git diff HEAD^ HEAD
git diff HEAD^ HEAD -- filename     #the diff of single file
git diff --word-diff                #Show inline changes in detail

git blame filename
git blame -L 6 +5 filename          #only show 5 lines begin from line 6

git format-patch -1

git stash                           #store all current changes
git stash list                      #list all stash
git stash pop                       #apply and remove the newest stash
git stash apply                     #only apply but do not remove
git stash drop [stash]              #remove the stash, the newest by default
git stash clear                     #clear all stash

git branch                          #show local branches
git branch -r/-a                    #show remote/all branches
git branch branchname <commit>      #create branch based on <commit>, HEAD by default
git branch -d branchname            #remove local branch, see also -D
git branch -m oldbranch newbranch   #rename branch,see also -M
git push <url>  :remote-branch      #remove remote branch, need to sync back by 'git fetch -p'

git tag -m "log message" tagname    #create tag
git tag                             #show local tags
git tag -l V3_*                     #show local tags which match the pattern
git tag -d tagname                  # delete the tag
git push origin tagname             #push the tag in local
git describe --tags                 #desciption about the last tags

git remote -v                       #show remote URL
git remote add new-remote path      #add new remote URL
git remote rename old-remote new-remote
git remote rm remotename            #remove remote
git remote show origin              #show info about current origin
git remote update

git rev-parse --git-dir             #show the path of .git folder of current repository
git rev-parse --show-toplevel       #show the top direcotry of current repository
git rev-parse --show-prefix         #how to go from top directory to current directory
git rev-parse --show-cdup           #how to back to top directory (e.g. '../../../')
git rev-parse HEAD                  #show the commit ID of HEAD
git rev-parse HEAD^
git rev-parse --symbolic --branches #show local branches
git rev-parse --symbolic --tags     #show local tags
git rev-parse --abbrev-ref HEAD     #Show the name of current branch

git rev-list --oneline A            #show the version relationship

git ls-files -s                     #show file tree and last commit ID
git ls-tree -l HEAD
git ls-files --others -i --exclude-standard  # Show all files which are ignored.

git cat-file -t <ID>                #type of the ID (commit or tag ...)
git cat-file -p <ID>                #content of the ID

git reflog show master              #show the log on master branch
git reflog -1                       #show last action of HEAD

Git Work Flow

Create Repository

Initialize a empty repository:

git init --bare
Clone a mirror repository, sync via “git remote update/git fetch” later::
git clone –mirror

Generate git patch outside git repo

git init
git add -A
git commit -s

#change some things ...

git add -A
git commit -s
git show

git format-patch -1

Git flow

http://nvie.com/posts/a-successful-git-branching-model/

Install:

$ sudo apt-get install git-flow

Usage:

|         +-- init
|         |
|git flow +-- feature --+-- start   --+-- name
|         |             |             |
|         +-- release --+-- finish  --+
|         |             |             |
|         +-- hotfix  --+-- publish --+
|                       |             |
|                     --+-- pull    --+

Details:

a. create develop branch

git branch develop
git push -u origin develop

b. Start new feature

git checkout -b some-feature develop
# Optionally, push branch to origin:
git push -u origin some-feature

git status
git add some-file
git commit

c. finish the feature

git pull origin develop
git checkout develop
git merge --no-ff some-feature
git push origin develop

git branch -d some-feature

# If you pushed branch to origin:
git push origin --delete some-feature

d. Start new relase

git checkout -b release-0.1.0 develop

# Optional: Bump version number, commit
# Prepare release, commit

e. Finish the release

git checkout master
git merge --no-ff release-0.1.0
git push

git checkout develop
git merge --no-ff release-0.1.0
git push

git branch -d release-0.1.0

# If you pushed branch to origin:
git push origin --delete release-0.1.0


git tag -a v0.1.0 master
git push --tags

f. Start new hotfix

git checkout -b hotfix-0.1.1 master

g. Finish the hotfix

git checkout master
git merge --no-ff hotfix-0.1.1
git push


git checkout develop
git merge --no-ff hotfix-0.1.1
git push

git branch -d hotfix-0.1.1

git tag -a v0.1.1 master
git push --tags

sphinx

Install

  • $ sudo apt-get install sphinx-common python-sphinx texlive
  • $ sudo pip install recommonmark
  • $ sudo pip install sphinx_rtd_theme

Quick Start

  1. $ sphinx-quickstart
+ *conf.py*: sphinx `configuration file`_
+ *index.rst*: top level document, define project structure
+ *Makefile*: make html/pdf
  1. $ make html or $ sphinx-build -b html  ./ ./_build/html

Theme

http://www.sphinx-doc.org/en/stable/theming.html

For example, use the “Read the Docs” theme:

$ sudo pip install sphinx_rtd_theme

$ vi conf.py
html_theme = 'sphinx_rtd_theme'

Deploy to Read the Docs

http://avnpc.com/pages/writing-best-documentation-by-sphinx-github-readthedocs

http://docs.readthedocs.org/en/latest/getting_started.html

Note

When push to github, let “Read the Docs” updeate automatically: github repo page => settings tabpage => Webhooks & Services => Add service => ReadTheDocs => Active

Convert file format

http://pandoc.org/

For example, between markdown and reStructureText.

Markdown

Difference between md and rst

Markdown to HTML

  1. Download markdown-browser-0.6.0-beta1.tgz

  2. Test it like this:

    tar -xvf markdown-browser-0.6.0-beta1.tgz
    cd markdown-browser-0.6.0-beta1
    vi test.html && firefox test.html
    

    test.html:

    <!DOCTYPE html>
    <html>
    <head>
    <link href="http://cdn.bootcss.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body style="padding:30px">
    <textarea id="text-input" oninput="this.editor.update()">Type **Markdown** here.</textarea>
    <div id="preview"> </div>
    <script src="markdown.js"></script>
    <script>
    function Editor(input, preview) {
        this.update = function () {
            preview.innerHTML = markdown.toHTML(input.value);
        };
        input.editor = this;
        this.update();
    }
    var $ = function (id) { return document.getElementById(id); };
    new Editor($("text-input"), $("preview"));
    </script>
    </body>
    </html>
    

Linux syslinux

https://wiki.archlinux.org/index.php/syslinux http://git.kernel.org/cgit/boot/syslinux/syslinux.git/tree/doc/menu.txt http://git.kernel.org/cgit/boot/syslinux/syslinux.git/

Syslinux is a collection of boot loaders capable of booting from hard drives, CDs, and over the network via PXE.

It supports the FAT, ext2, ext3, ext4, and Btrfs file systems.

Boot process overview

  1. Stage 1 : Part 1 - Load MBR - At boot, the BIOS loads the 440 byte MBR boot code at the start of the disk (/usr/lib/syslinux/bios/mbr.bin or /usr/lib/syslinux/bios/gptmbr.bin).
  2. Stage 1 : Part 2 - Search active partition. The Stage 1 MBR boot code looks for the partition that is marked as active (boot flag in MBR disks). Let us assume this is the /boot partition for example.
  3. Stage 2 : Part 1 - Execute volume boot record - The Stage 1 MBR boot code executes the Volume Boot Record (VBR) of the /boot partition. In the case of syslinux, the VBR boot code is the starting sector of /boot/syslinux/ldlinux.sys which is created by the extlinux –install command.
  4. Stage 2 : Part 2 - Execute /boot/syslinux/ldlinux.sys - The VBR will load rest of /boot/syslinux/ldlinux.sys. The sector location of /boot/syslinux/ldlinux.sys should not change, otherwise syslinux will not boot.

Note

In the case of Btrfs, the above method will not work since files move around resulting in changing of the sector location of ldlinux.sys. Therefore, in BTRFS the entire ldlinux.sys code is embedded in the space following the VBR and is not installed at /boot/syslinux/ldlinux.sys unlike the case of other filesystems.

  1. Stage 3 - Load /boot/syslinux/ldlinux.c32 - The /boot/syslinux/ldlinux.sys will load the /boot/syslinux/ldlinux.c32 (core module) that contains the rest of core part of syslinux that could not be fit into ldlinux.sys (due to file-size constraints). The ldlinux.c32 should be present in every syslinux installation and should match the version of ldlinux.sys installed in the partition. Otherwise syslinux will fail to boot. See http://bugzilla.syslinux.org/show_bug.cgi?id=7 for more info.
  2. Stage 4 - Search and Load configuration file - Once Syslinux is fully loaded, it looks for /boot/syslinux/syslinux.cfg (or /boot/syslinux/extlinux.conf in some cases) and loads it if it is found. If no configuration file is found, you will be dropped to a syslinux boot: prompt. This step and rest of non-core part of syslinux (/boot/syslinux/*.c32 modules, excluding lib*.c32 and ldlinux.c32) require /boot/syslinux/lib*.c32 (library) modules to be present (http://www.syslinux.org/wiki/index.php/Common_Problems#ELF). The lib*.c32 library modules and non-core *.c32 modules should match the version of ldlinux.sys installed in the partition.

Limitations of UEFI Syslinux

  1. UEFI Syslinux application syslinux.efi cannot be signed by sbsign (from sbsigntool) for UEFI Secure Boot. Bug report - http://bugzilla.syslinux.org/show_bug.cgi?id=8
  2. Using TAB to edit kernel parameters in UEFI Syslinux menu lead to garbaged display (text on top of one-another). Bug report - http://bugzilla.syslinux.org/show_bug.cgi?id=9
  3. UEFI Syslinux does not support chainloading other EFI applications like UEFI Shell or Windows Boot Manager. Enhancement request - http://bugzilla.syslinux.org/show_bug.cgi?id=17
  4. In some cases, UEFI Syslinux might not boot in some Virtual Machines like QEMU/OVMF or VirtualBox or some VMware products/versions and in some UEFI emulation environments like DUET. A Syslinux contributor has confirmed no such issues present on VMware Workstation 10.0.2 and Syslinux-6.02 or later. Bug reports - http://bugzilla.syslinux.org/show_bug.cgi?id=21 and http://bugzilla.syslinux.org/show_bug.cgi?id=23
  5. Memdisk is not available for UEFI. Enhancement request - http://bugzilla.syslinux.org/show_bug.cgi?id=30

Bootloader Grub2

http://www.gnu.org/software/grub/manual/grub.html http://www.gnu.org/software/grub/grub-documentation.html

Runtime Tools

grub-mkconfig:
make the template of the grub.cfg file
grub-reboot <idx>:
save current entry index to ‘prev_saved_entry’, and save <idx> to ‘saved_entry’ in grubenv.
grub-editenv [grubenv-file] <command> <var-name>:
Set/Delete/List the variables in grubenv.
grub-menulst2cfg:
Convert the grub 0.97 conf file to grub2 cfg file.

Linux Systemd

https://www.freedesktop.org/wiki/Software/systemd/ https://en.wikipedia.org/wiki/Systemd https://github.com/systemd/systemd/blob/master/README

Tips And Tricks

Basic operators:

$ sudo systemctl start nginx.service
$ sudo systemctl stop nginx.service
$ sudo systemctl restart nginx.service
$ sudo systemctl reload nginx.service
$ sudo systemctl enable nginx.service
$ sudo systemctl disable nginx.service

$ sudo systemctl daemon-reload
$ systemctl status nginx.service

$ sudo systemctl poweroff
$ sudo systemctl reboot

Other tools:

hostnamectl #get/set hostname
localectl   #get/set local settings, e.g. LANG
timedatectl #get/set time/date/timezone
    $ sudo timedatectl set-timezone America/New_York
    $ sudo timedatectl set-time YYYY-MM-DD
    $ sudo timedatectl set-time HH:MM:SS

.. note::
    timedatectl also show the systemd ntp(systemd-timesyncd service) status.

If you only wish to see the journal entries from the current boot:

$ journalctl -b
$ journalctl -u nginx.Service

To expand all dependent units recursively:

systemctl list-dependencies --all nginx.service

Cgroup Tree:

$ systemd-cgls

Switch the run level:

$ ln -sf /usr/lib/systemd/system/graphical.target /etc/systemd/system/default.target
$ ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target

Unit Dependencies:

$ systemctl show -p "Wants" multi-user.target

.. note::
    Instead of "Wants" you might also try "WantedBy", "Requires", "RequiredBy",
    "Conflicts", "ConflictedBy", "Before", "After" for the respective types of
    dependencies and their inverse.

Show the main PID:

systemctl -p MainPID show <service-name>

Mask a service, ensure that service cannot even be started manually anymore:

$ ln -s /dev/null /etc/systemd/system/ntpd.service
$ systemctl daemon-reload

You can modify the system state to transition between targets with the isolate option. This will stop any units that are not tied to the specified target. Be sure that the target you are isolating does not stop any essential services:

sudo systemctl isolate multi-user.target

Check the boot time:

$ systemd-analyze
$ systemd-analyze nginx
$ systemd-analyze critical-chain
$ systemd-analyze critical-chain atd.service

Systemd Units

service.service, socket.socket, device.device, mount.mount, automount.automount, swap.swap, target.target, path.path, timer.timer, slice.slice, scope.scope

systemd.unit

https://www.freedesktop.org/software/systemd/man/systemd.unit.html

[Unit] and [Install] section define the relationship between other units. [Unit] and [Install] sections configure the common configuration items, for example dependences, conditions, and other relationship between units. They are generic sections used in almost all type units.

Each unit may have a type-specific section, e.g. [Service] for a service unit.

Various settings are allowed to be specified more than once, often, multiple settings form a list

If systemd encounters an unknown option, it will write a warning log message but continue loading the unit.

If an option or section name is prefixed with X-, it is ignored completely by systemd. Options within an ignored section do not need the prefix. Applications may use this to include additional information in the unit files.

Boolean arguments used in unit files can be written in various formats. For positive settings the strings 1, yes, true and on are equivalent. For negative settings, the strings 0, no, false and off are equivalent.

Empty lines and lines starting with # or ; are ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the backslash is replaced by a space character. This may be used to wrap long lines.

If a unit file is empty (i.e. has the file size 0) or is symlinked to /dev/null, its configuration will not be loaded and it appears with a load state of “masked”, and cannot be activated. Use this as an effective way to fully disable a unit, making it impossible to start it even manually.

Unit files are loaded from a set of paths determined during compilation, described in the two tables below. Unit files found in directories listed earlier override files with the same name in directories lower in the list:

/etc/systemd/system     Local configuration
/run/systemd/system     Runtime units
/usr/lib/systemd/system Units of installed packages
systemd.service

https://www.freedesktop.org/software/systemd/man/systemd.service.html

[Service] section configure the service specific configuration options.

Unless DefaultDependencies is set to false, service units will implicitly have dependencies of type Requires= and After= on sysinit.target, a dependency of type After= on basic.target as well as dependencies of type Conflicts= and Before= on shutdown.target.

Note that notify type daemon has to support systemd’s notification protocol, else systemd will think the service has not started yet and kill it after a timeout. (systemd_notify can be used in script to tell systemd itself is ready.)

systemd.resource-control

https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html

The resource control configuration options are configured in the [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type.

systemd debug

https://freedesktop.org/wiki/Software/systemd/Debugging/

debug shell

You can enable shell access very early in the startup process to fall back on and diagnose systemd related boot up issues with various systemctl commands. It also active when shutdown is not finished. Enable it using:

systemctl enable debug-shell.service
shutdown debug

If normal reboot or poweroff work, but take a suspiciously long time, then boot with the debug options:

systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M enforcing=0

save the following script as /usr/lib/systemd/system-shutdown/debug.sh and make it executable:

#!/bin/sh
mount -o remount,rw /
dmesg > /shutdown-log.txt
mount -o remount,ro /

reboot

File System btrfs

https://btrfs.wiki.kernel.org/index.php/Main_Page

sudo apt-get install btrfs-tools

Create btrfs filesystem

# Create the btrfs filesystem
mkfs.btrfs -L label /dev/sdc2
mount /dev/sdc2 /mnt

# Show information
btrfs filesystem show

Modify the btrfs filesystem

# Add/Delete
btrfs device add /dev/sdc3 /mnt #Don't need mkfs firtly.
btrfs device delete /dev/sdc3 /mnt

# Resize btrfs filesystem online
btffs filesystem resize 4G /mnt
btffs filesystem resize +1G /mnt
btffs filesystem resize -1G /mnt

Snapshot and Rollback

# Create snapshot
btrfs subvolume snapshot /mnt /mnt/snap1

# Delete snapshot
btrfs subvolume delete /mnt/snap1

# Rollback
btrfs subvolume list
btrfs subvolume set-default <id> <path>
umount /mnt && mount /dev/sdc2 /mnt || reboot

Ubuntu Installation

Maybe we should also fork/create a project to do this automatically. http://yuez.me/cong-ling-da-jian-he-pei-zhi-osxkai-fa-huan-jing/

Pre-Installation

Backup: .bashrc .vimrc .vim .zshrc .mozilla .thunderbird .gitconfig

Installation

Ubuntu16.04, there is a gxfboot.c32 error, after the “boot:” promote, fix it manually, input “tab” => “live” or “liveinstall” => press ENTER

Post-Configurations

Restore: .bashrc .vimrc .vim .mozilla .thunderbird .gitconfig (If you have not formated the /home partition, you don’t need to do this)

All Settings => Languages All Settings => Dispalys All Settings => Appearance => Behavior => Auto-hide the Launcher

Post-Intallations

First time Upgrade:

sudo apt-get update && sudo apt-get upgrade

Change default shell:

sudo dpkg-reconfigure dash --> select No for set bash as default shell

Basic packages:

sudo apt-get install git-core git-email kdiff3 gitg
sudo apt-get install vim ctags g++ tofrodos quilt tree
sudo apt-get install rar unrar p7zip p7zip-rar p7zip-full
sudo apt-get install ntfs-3g ntfs-config
sudo apt-get install python-pip

Packages for Developer:

sudo apt-get install \
    autoconf autoconf2.64 autoconf-doc autoconf-archive \
    glib2.0 glib2.0-data glib2.0-dev \
    libdbus-1-dev libdbus-glib-1-dev \
    libtool libtool-doc \
    texlive texinfo libxml-parser-perl libxml-simple-perl \
    diffstat texi2html gawk chrpath \
    gcc-multilib g++-multilib  libc6-dev-i386 libzip-dev \
    libc6-i386

Installing the ia32 libs needs the ubuntu 13.04 sources, because this package is droped after this ubuntu 13.04:

sudo -i
cd /etc/apt/sources.list.d
echo "deb http://old-releases.ubuntu.com/ubuntu/ raring main restricted universe multiverse" > ia32-libs-raring.list
apt-get update
apt-get install ia32-libs
rm /etc/apt/sources.list.d/ia32-libs-raring.list
apt-get update

youtao-dict

To avoid gstreamer0.10-plugins-ugly dependence issue, use deepin version but not ubuntu version. http://codown.youdao.com/cidian/linux/youdao-dict_1.1.0-0-deepin_amd64.deb

sudo apt-get install python3-pyqt5 python3-xlib sudo apt-get install tesseract-ocr tesseract-ocr-chi-sim tesseract-ocr-chi-tra sudo apt-get install ttf-wqy-microhei sudo apt-get install python3-pyqt5.qtmultimedia python3-pyqt5.qtquick python3-pyqt5.qtwebkit sudo apt-get install qtdeclarative5-controls-plugin libqt5multimedia5-plugins sudo dpkg -i youdao-dict_1.1.0-0-deepin_amd64.deb

python3

Maybe the python3 is already installed, but you need to install pip3:

sudo apt-get install python3-pip

Then you can install python3 modules using sudo pip3 install xxx

Ubuntu Usage

Change the default application:

System Settings => System => Details => Default Applications

Ubuntu Services

Openssh

sudo apt-get install openssh-server
# Edit the etc/ssh/sshd_config file
UseDNS no
GSSAPIAuthentication no

Vnc

Set the vnc server password: vncpasswd Start the vncserver: vncserver Start the vncviewer: vncviewer IP/HOSTNAME:PORTNUM Kill the vncserver: vncserver -kill :1

Ubuntu Shortcuts

Ubuntu Terminal(16.04)

Edit => Preferences => Shortcuts:

New Terminal in New Tab         ctrl+shift+t
New Terminal in New Window      ctrl+shift+n
Close Terminal tab              ctrl+shift+w
Close all Terminal tabs         ctrl+shift+q

Copy                            ctrl+shift+c
Paste                           ctrl+shift+v

Full Screen                     F11
Zoom In                         ctrl++
Zoom Out                        ctrl+-
Normal Size                     ctrl+0

Switch to Previous Tab          ctrl+PageUp
Switch to Nexty Tab             ctrl+PageDown
Switch to Tab <N>               alt+<N>

Move Tab to the Left            ctrl+shift+PageUp
Move Tab to the Right           ctrl+shift+PageDown

Ubuntu Zsh Usage

zsh

https://wiki.gentoo.org/wiki/Zsh/Guide

sudo apt-get install zsh
chsh -s $(which zsh)  # need to reboot the system

oh-my-zsh

install oh-my-zsh:

sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

themes

Preview: https://github.com/robbyrussell/oh-my-zsh/wiki/Themes

or:

autoload -U promptinit
prompinit
prompt -p

Modify the prompt in ~/.oh-my-zsh/themes/robbyrussell.zsh-theme or export prompt directly in .zshrc:

local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )"
local suffix="%{$fg_bold[blue]%}$ %{$reset_color%}"
PROMPT='%{$fg_bold[cyan]%}%d%{$reset_color%} $(git_prompt_info)
${ret_status} %{$fg[green]%}[%* %D]%{$reset_color%} ${suffix}'

local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )"
local suffix="%{$fg_bold[blue]%}$ %{$reset_color%}"
export PROMPT='%{$fg_bold[cyan]%}%d%{$reset_color%} $(git_prompt_info)
%F{magenta}%B%K{magenta}█▓▒░%F{white}%K{magenta}%B%* %D%b%F{magenta}%K{black}█▓▒░ ${ret_status}%b%k%f%{$reset_color%} '

Sequence    Printed
%T          System time (HH:MM)
%*          System time (HH:MM:SS)
%D          System date (YY-MM-DD)
%n          Your username
%B - %b     Begin - end bold print
%U - %u     Begin - end underlining
%d          Your current working directory
%~          Your current working directory, relative to ~
%M          The computer's hostname
%m          The computer's hostname (truncated before the first period)
%l          Your current tty

plugins

1. git: Git is include by default. It will show git information in prompt line.

  1. autojump:

    sudo apt-get install autojump
    

The final plugins:

plugins=(git autojump)

FAQ

  1. Q: vi ~/.z (TAB Complete)
    arguments:450: _vim_files: function definition file not found.
    A: rm -rf ~/.zcompdump* ; then relogin the zsh

  2. Q: time -p ls (Command not found: -p)
    A: time in zsh is a shell reserved word, but not /usr/bin/time binary tool.

Ubuntu Vim Editor

Setup

https://github.com/VundleVim/Vundle.vim/wiki/Examples

Dependencies:

$ sudo apt-get install python vim exuberant-ctags git
$ sudo pip install dbgp vim-debug pep8 flake8 pyflakes isort
$ sudo npm -g install instant-markdown-d
Install vundle::
$ git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim

Prepare for YouCompleteMe:

$ sudo apt-get install cmake build-essential libclang1 libclang-dev python-dev
$ vim vimrc:
    Plugin 'Valloric/YouCompleteMe'

Install plugins:

:PluginInstall                  # Install all defined plugins
:PluginUpdate                   # Update all defined plugins

or:

$ vim +PluginInstall +qall        # Install all defined plugins outside Vim.

Postinstall for YouCompleteMe:

$ cd ~/.vim/bundle/YouCompleteMe
$ git submodule update --init --recursive
$ ./install.py --clang-completer

Plugins Usage

YouCompleteMe https://github.com/Valloric/YouCompleteMe

ctrl+o              # Return
ctrl+i              # Go ahead

Plugins Shortcuts

nerdtree:

<CR>|o: open in prev window (auto close if NERDTreeQuitOnOpen = 1)
go:     preview only, so will not change the window focuse.
gi:     split in preview window
gs:     vsplit in preview window
i:      split current nerdtree window, so it's better useing it with NERDTreeQuitOnOpen = 1
s:      open vsplist

Ubuntu Atom Editor

http://flight-manual.atom.io/ https://atom-china.org/t/atom/62 http://atom-china.org/ https://atom.io/docs

Install

https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md

Requirements:

sudo apt-get install build-essential git libgnome-keyring-dev fakeroot nodejs

Get deb package here: https://atom.io/ Install it like this:

sudo dpkg -i atom-amd64.deb

Or:

sudo add-apt-repository ppa:webupd8team/atom
sudo apt-get update
sudo apt-get install atom

Configurations

Plugins

you-complete-me autocomplete autocomplete-html autocomplete-css autocomplete-json autocomplete-paths

python-tools python-indent autocomplete-python linter-pep8 (pip install pep8) atom-beautify

docblockr

file-icons

tree-view-git-status

vim-mode-plus or vim-mode + vim-mode-visual-block

terminal-plus

fuzzy-grep

Shortcuts

ctrl-o          Open file
ctrl-shift-o    Open folder
ctrl-\          Hide folder tree
ctrl-/          Trigger line comments
ctrl-,          Open Settings pane
ctrl-w q        close current pane

ctrl+p          serach files
ctrl+g          go to line

alt-<N>         Switch to tab <N>
alt-\           Switch to foler-tree or return back

Ubuntu Tmux

shortcuts & cheatsheet

https://gist.github.com/MohamedAlaa/2961058

For example:

tmux new -s myname              #Start new named tmux session
tmux a[ttach] -t myname         #Attach named tmux session
tmux ls/list-sessions           #List all tmux session
tmux kill-session -t myname     #Kill named tmux session

Configuration Example

#--basic-------------------------------------------------------#
##set -g default-terminal "screen"
set -g default-terminal "screen-256color"
set -g display-time 5000
set -g repeat-time 1000
set -g escape-time 0
set -g history-limit 65535
set -g base-index 1
set -g pane-base-index 1
set -g history-limit 10000
set -g terminal-overrides 'xterm*:smcup@:rmcup@'


#--bindkeys----------------------------------------------------#
#Escape key
unbind C-b
set -g prefix C-a
bind a send-prefix

#windows
unbind '"'
bind h split-window -h
unbind %
bind v split-window -v
unbind i
bind C-g display-message

#pane
bind j select-pane -L
bind i select-pane -U
bind k select-pane -D
bind l select-pane -R

#quit
unbind x
unbind &
unbind q
bind q confirm-before -p "kill-pane #P? (y/n)" kill-pane
bind Q confirm-before -p "kill-window #W? (y/n)" kill-window
bind e confirm-before -p "kill-session #S? (y/n)" kill-session

#misc
bind r source-file ~/.tmux.conf \; display "Reloaded!"
#bind m command-prompt "splitw -h 'exec man %%'"
#bind @ command-prompt "splitw -h 'exec perldoc -f %%'"


#--Window------------------------------------------------------#
setw -g mode-keys vi
setw -g utf8 on
setw -g window-status-current-bg red
setw -g window-status-current-fg white
setw -g window-status-current-attr bright
setw -g window-status-attr bright
setw -g window-status-format '#[fg=cyan,dim]#I#[fg=blue] #[default]#W#[fg=grey,dim]'
setw -g window-status-current-format '#[fg=cyan,dim]#I#[fg=blue] #[default]#W#[fg=grey,dim]'


#--Statusbar---------------------------------------------------#
set -g status-keys vi
set -g status-utf8 on
set -g status-left ""
set -g status-left-length 0
set -g status-interval 2
set -g status-fg white
set -g status-bg blue
set -g status-right "#[fg=white]#S:#W:#P [#(tmux ls|wc -l) sessions]#[default]"
#set -g status-justify centre
#set -g status-right-length 10


#--Mouse-------------------------------------------------------#
setw -g mode-mouse on
set -g mouse-resize-pane on
set -g mouse-select-pane on
set -g mouse-select-window on

MongonDB QuickStart

Overview

A record in MongoDB is a document, which is a data structure composed of field and value pairs. MongoDB documents are similar to JSON objects. The values of fields may include other documents, arrays, and arrays of documents.

MongoDB stores documents in collections. Collections are analogous to tables in relational databases. Unlike a table, however, a collection does not require its documents to have the same schema.

ubuntu Setup

https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

Note

MongoDB only provides packages for 64-bit LTS (long-term support) Ubuntu releases.

Install V3.2:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list
sudo apt-get update
sudo apt-get install mongodb-org

Configuration:

https://docs.mongodb.com/manual/reference/configuration-options/

Create sub folders::
mkdir mongodb-simple && cd mongodb-simple mkdir data conf log

Create special conf file:

cp /etc/mongod.conf ./conf/

# vi dbpath and log path in the conf file
storage:
    dbPath: ./data
systemLog:
    path: ./log/mongod.log
processManagement:
   fork: true

Start:

$ mongod -f conf/mongod.conf

Stop:

kill <mongod-pid>  # kill or kill -15, don't use kill -9

Operators in JavaScript syntax compatiable Mongo shell:

$ mongo   # Connect "localhost:<defaultPort>/test" by default

$ use mydb  # use database, create new one if it doesn't exist.
$ db.user.insert({name:"xxx", age:18})  # create at first
$ db.user.find()
{ "_id" : ObjectId("549a6cae1cdcaf3b048887b8"), "age" : 18, "name" : "xxx" }

Python PyMongo

https://docs.mongodb.com/getting-started/python/

https://github.com/mongodb/mongo-python-driver

http://api.mongodb.com/python/current/

APIs:

collection.insert_one({})
collection.insert_many([{}])

collection.find_one({})
collection.find({})

collection.create_index()

collection.count()

WiFi Linux Commands

AP mode

WiFi AP mode commands:

brctl delif br-bridge wlan0
ifconfig br-bridge down
brctl delbr br-bridge
killall hostapd

#Configure correct WiFi mode
iw wlan0 del
iw phy phy0 interface add wlan0 type managed

/usr/local/bin/hostapd -B /root/examples/wifi-apmode/hostapd.conf

#Remove the wlan0 interface address and let the bridge do the work
brctl addbr br-bridge
ifconfig br-bridge  192.168.1.1
ifconfig wlan0 0.0.0.0

#Enable IPv4 forwarding
echo "1" > /proc/sys/net/ipv4/ip_forward

#Bring the bridge up
/sbin/ifconfig br-bridge up

#Use dnsmasq to provide dns and dhcp functions
killall dnsmasq
/usr/sbin/dnsmasq -Z -i br-bridge -F 192.168.1.100,192.168.1.249,255.255.255.0,720m

#Routing and NAT rules
/sbin/route add -net 239.0.0.0/8 br-bridge
/sbin/iptables -A FORWARD -i br-bridge -s 192.168.1.0/24 -j ACCEPT
/sbin/iptables -A POSTROUTING -t nat -j MASQUERADE

hostapd configuration file example:

interface=wlan0
bridge=br-bridge
driver=nl80211
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=WRIDPSDK
country_code=US
hw_mode=g
channel=11
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
macaddr_acl=0
auth_algs=3
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
eap_server=0
wpa=2
wpa_passphrase=mypassword
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP CCMP
wpa_group_rekey=600
wpa_gmk_rekey=86400

Client Mode

WiFi Client commands:

iw wlan0 del
iw phy phy0 interface add wlan0 type managed
iw wlan0 set channel  <channel>
ifconfig wlan0 up
# if remote AP uses no security mode, don't need wpa_supplicant
wpa_supplicant -B -D wext -i wlan0 -c /etc/wpasupplicant.conf
iw wlan0 connect -w <ap_essid>
iw wlan0 link  # show connection result information

#See also other commands
ifconfig wlan0 down
dhclient -r wlan0
ifconfig wlan0 up
iwconfig wlan0 essid "IDPDK-7AAA"
iwconfig wlan0 mode Managed
dhclient wlan0
dhclient -timeout 5 -pf /var/run/dhclient-wlan0.pid \
  -lf /var/lib/dhclient/dhclient-wlan0.leases wlan0

#Scan APs
ifconfig wlan0 up
iw wlan0 scan | grep "SSID:" | sort | uniq

#List all APs
iwlist wlan0 scan | grep -B 5 -A 20 "7AAA" | sed '/Address/,/Cell/p;d'

wpasupplicant.conf examples

WEP:

#/etc/wpasupplicant.conf
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel

# Allow all valid ciphers
network={
    ssid="ap_essid"
    scan_ssid=1
    key_mgmt=NONE
    wep_key0=my_wep_key
}

WPA2:

#/etc/wpasupplicant.conf
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel

# Allow all valid ciphers
network={
    ssid="ap_essid"
    scan_ssid=1
    key_mgmt=WPA-PSK
    psk=my_wpa_key
}

WPA Enterprise:

ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
network={
    ssid="ap_essid"
    scan_ssid=1
    key_mgmt=WPA-EAP
    pairwise=CCMP TKIP
    group=CCMP TKIP WEP104 WEP40
    eap=PEAP
    identity="username"
    password="password"
}

Ad-Hoc mode

To connect to a remote AP with no security Mode:

iw wlan0 del
iw phy phy0 interface add wlan0 type adhoc
iw wlan0 set channel  <channel>
ifconfig wlan0 up
iw dev wlan0 ibss join <ssid> <frequency>

The following table shows the channels and their corresponding frequencies to be used in the joining of the ad-hoc network using the iw command:

1   -   2412
2   -   2417
3   -   2422
4   -   2427
5   -   2432
6   -   2437
7   -   2442
8   -   2447
9   -   2452
10  -   2457
11  -   2462
12  -   2467
13  -   2472

PPPD usage

The simple way to use pppd is to provide the peers and chat file. The following example is for 3G.

/etc/ppp/peers/test:

debug debug debug
/dev/ttyACM0
115200
logfile /var/log/ppp.log
nomultilink
defaultroute
noipdefault
ipcp-restart 7
ipcp-accept-local
ipcp-accept-remote
lcp-echo-interval 0
lcp-echo-failure 999
modem
noauth
nocrtscts
noipdefault
noaccomp
noccp
novj
usepeerdns
persist
connect '/usr/sbin/chat -v -f /etc/ppp/chat/test'

/etc/ppp/chat/test:

ABORT BUSY
ABORT 'NO CARRIER'
ABORT VOICE
ABORT 'NO DIALTONE'
ABORT 'NO DIAL TONE'
ABORT 'NO ANSWER'
ABORT DELAYED
ABORT ERROR
SAY "Initializing\n"
'' 'ATZ'
OK 'AT+CGDCONT=1,"IP","$USE_APN"'
OK 'AT+CFUN=1'
OK 'AT'
OK 'ATD*99***1#'
SAY "Calling UMTS/GPRS"
TIMEOUT 120
CONNECT ' '

Vulnerability Scan Tools

Nexpose Community Edition

download https://www.rapid7.com/products/nexpose/compare-downloads.jsp

(Need to register with a non-personal email account, it seems 139.com is permitted. Then you will receive the activation code.)

Please download the user’s guide and installation guide document here: https://community.rapid7.com/community/nexpose?linkid=blue

install $ sudo NeXposeSetup-Linux64.bin -c (Note: You’d better to select the initialization when install it)

If your forgot to selecte initialization when install, then you can initialize it manually like this: $ cd ~/Disk2/rapid7/nexpose/nsc $ sudo ./nsc.sh

start

If your selected initialization when install, then it maybe already started. Otherwise, you can start it manually like this: $ cd ~/Disk2/rapid7/nexpose/nsc $ sudo ./nscsvc.sh start

Go to https://localhost:3780 to configure your scanner

Nessus Home

download http://www.tenable.com/products/nessus/select-your-operating-system

Get the free activation code of home version here: http://www.tenable.com/products/nessus/nessus-plugins/obtain-an-activation-code

install $ sudo dpkg -i Nessus-6.7.0-ubuntu1110_i386.deb

start $ /etc/init.d/nessusd start Go to https://localhost:8834/ to configure your scanner

OpenVAS

install http://www.openvas.org/install-packages.html

$ sudo vi /etc/apt/sources.list

(Add the following ppa information)
# For openvas
deb http://ppa.launchpad.net/mrazavi/openvas/ubuntu trusty main
deb-src http://ppa.launchpad.net/mrazavi/openvas/ubuntu trusty main

$ sudo apt-get update $ sudo apt-get install sqlite3 openvas

$ sudo openvas-nvt-sync $ sudo openvas-scapdata-sync $ sudo openvas-certdata-sync

start $ sudo service openvas-scanner restart $ sudo service openvas-manager restart $ sudo openvasmd –rebuild –progress

Login into https://localhost:443 with “admin” as username and password. In case of “Secure Connection Failed” in firefox, use chromium.

Openscap (Not Passed)

download https://fedorahosted.org/releases/o/p/openscap/ https://github.com/OpenSCAP/openscap https://github.com/OpenSCAP/scap-workbench

install $ sudo apt-get install gcc swig pkg-config xml2 libxml2-dev xsltproc libxslt-dev libgcrypt11-dev libpcre3-dev python-dev libcurl4-openssl-dev libbz2-dev $ sudo apt-get install libopenscap-dev

$ tar -xvf openscap-1.2.9.tar.gz $ cd openscap-1.2.9/ $ ./configure $ make $ sudo make install

start

scap-workbanch https://fedorahosted.org/released/scap-workbench/

https://github.com/OpenSCAP/scap-workbench $ git clone https://github.com/OpenSCAP/scap-workbench.git $ cd scap-workbench/ $ mkdir build; cd build $ cmake ../ $ make $ sudo make install