def function(a,b):
    print a, b

apply(function, ("wheather", "Canada?"))

apply(function, (1, 3+5))

"""
Explanation: 1.  _ builtin _ 模块
1.1 apply:使用元组或字典中的参数调用函数

Python 允许你实时地创建函数参数列表. 只要把所有的参数放入一个元组中，然后通过内建的 apply 函数调用函数.
End of explanation
"""


function("wheather", "Canada?")

function(1, 3+5)

"""
Explanation: 效果等同于：
End of explanation
"""


apply(function, (), {"a":"35cm", "b":"12cm"})

apply(function, ("v",), {"b":"love"})

apply(function, ( ,"v"), {"a":"hello"})

"""
Explanation: 那为什么要使用apply呢？
End of explanation
"""


class Rectangle:
    def __init__(self, color="white", width=10, height=10):
        print "Create a ", color, self, "sized", width, "X", height

class RoundRectangle:
    def __init__(self, **kw):
        apply(Rectangle.__init__, (self,), kw)

rect = Rectangle(color="green", width=200, height=156)

rect = RoundRectangle(color="brown", width=20, height=15)

"""
Explanation: 何谓“关键字参数”？  
apply使用字典传递关键字参数，实际上就是字典的键是函数的参数名，字典的值是函数的实际参数值。（相对于形参和实参）
根据上面的例子看，如果部分传递，只能传递后面的关键字参数，不能传递前面的。？？？？

apply 函数的一个常见用法是把构造函数参数从子类传递到基类, 尤其是构造函数需要接受很多参数的时候.

子类和基类是什么概念？
End of explanation
"""


class RoundRectangle(Rectangle):
    def __init__(self, **kw):
        apply(Rectangle.__init__, (self,), kw)

rect2 = RoundRectangle(color= "blue", width=23, height=10)

"""
Explanation: 第二个函数不知道如何使用 ？？？？
修改，子类要以父类为参数！！！
End of explanation
"""


args = ("er",)
kwargs = {"b":"haha"}
function(*args, **kwargs)

apply(function, args, kwargs)

"""
Explanation: 使用 * 来标记元组, ** 来标记字典.

apply的第一个参数是函数名，第二个参数是元组，第三个参数是字典。所以用上面这个表达最好不过。
End of explanation
"""


kw = {"color":"brown", "width":123, "height": 34}
rect3 = RoundRectangle(**kw)

rect4 = Rectangle(**kw)

arg=("yellow", 45, 23)
rect5 =  Rectangle(*arg)

"""
Explanation: 以上等价。
用这个意思引申：
End of explanation
"""


import glob, os

modules =[]

for module_file in glob.glob("*-plugin.py"):
    try:
        module_name, ext = os.path.splitext(os.path.basename(module_file))
        module = __import__(module_name)
        modules.append(module)
    except ImportError:
        pass #ignore broken modules

for module in modules:
    module.hello()
example-plugin says hello

def hello():
    print "example-plugin says hello"

def getfunctionname(module_name, function_name):
    module = __import__(module_name)
    return getattr(module, function_name)

print repr(getfunctionname("dumbdbm","open"))

"""
Explanation: 1.2 import
End of explanation
"""


import os
import string

def replace(file, search_for, replace_with):
    back = os.path.splitext(file)[0] + ".bak"
    temp = os.path.splitext(file)[0] + ".tmp"
    
    try:
        os.remove(temp)
    except os.error:
        pass
    
    fi = open(file)
    fo = open(temp, "w")
    
    for s in fi.readlines():
        fo.write(string.replace(s, search_for, replace_with))
    
    fi.close()
    fo.close()
        
    try:
        os.remove(back)
    except os.error:
        pass
    
    os.rename(file, back)
    os.rename(temp, file)

file = "samples/sample.txt"

replace(file, "hello", "tjena")

replace(file, "tjena", "hello")

"""
Explanation: 3. os模块
End of explanation
"""


def replace1(file, search_for, replace_with):
    back = os.path.splitext(file)[0] + ".bak"
    temp = os.path.splitext(file)[0] + ".tmp"
    
    try:
        os.remove(temp)
    except os.error:
        pass
    
    fi = open(file)
    fo = open(temp, "w")
    
    for s in fi.readlines():
        fo.write(string.replace(s, search_for, replace_with))
        
    fi.close()
    fo.close()
    
    try:
        os.remove(back)
    except os.error:
        pass

    
    os.rename(file, back)
    os.rename(temp, file)

replace1(file, "hello", "tjena")

replace1(file, "tjena", "hello")

doc = os.path.splitext(file)[0] + ".doc"

for file in os.listdir("samples"):
    print file

cwd = os.getcwd()

print 1, cwd

os.chdir("samples")

print 2, os.getcwd()

os.chdir(os.pardir)
print 3, os.getcwd()

"""
Explanation: os.path.splitext：切扩展名
os.remove：remove a file。上面的程序里为什么要remove呢？
End of explanation
"""


import stat

import os, time

st = os.stat("samples/sample.txt")

"""
Explanation: 5. stat模块
End of explanation
"""


import string

text = "Monty Python's Flying Circus"

print "upper", "=>", string.upper(text)

print "lower", "=>", string.lower(text)

print "split", "=>", string.split(text)

"""
Explanation: os.stat是将文件的相关属性读出来，然后用stat模块来处理，处理方式有多重，就要看看stat提供了什么了。
6. string模块
End of explanation
"""


print "join", "=>", string.join(string.split(text))

"""
Explanation: 分列变成了list
End of explanation
"""


print "replace", "=>", string.replace(text, "Python", "Cplus")

"""
Explanation: join和split相反。
End of explanation
"""


print "find", "=>", string.find(text, "Python")

print "find", "=>", string.find(text, "Python"), string.find(text, "Cplus")

print text

"""
Explanation: replace的参数结构是：
1. 整字符串  2. 将被替换的字符串  3. 替换后的字符串
End of explanation
"""


print "count", "=>", string.count(text,"n")

"""
Explanation: 上面replace的结果，没有影响原始的text。
find时，能找到就显示位置，不能找到就显示-1
End of explanation
"""


print string.atoi("23")

type(string.atoi("23"))

int("234")

type(int("234"))

type(float("334"))

float("334")

string.atof("456")

"""
Explanation: 和数学运算一样，这些方法也分一元的和多元的：  
upper, lower, split, join 都是一元的。其中join的对象是一个list。
replace, find, count则需要除了text之外的参数。replace需要额外两个，用以指明替换关系。find只需要一个被查找对象。count则需要一个需要计数的字符。
特别注意： replace不影响原始字符串对象。（好奇怪）
End of explanation
"""


import re

text = "The Attila the Hun Show"

m = re.match(".", text)
if m:
    print repr("."), "=>", repr(m.group(0))

"""
Explanation: 7. re模块
End of explanation
"""


import math

math.pi

math.e

print math.hypot(3,4)

math.sqrt(25)

import cmath

print cmath.sqrt(-1)

"""
Explanation: 8. math模块和cmath模块
End of explanation
"""


import operator

operator.add(3,5)

seq = 1,5,7,9

reduce(operator.add,seq)

reduce(operator.sub, seq)

reduce(operator.mul, seq)

float(reduce(operator.div, seq))

"""
Explanation: 10. operator模块
End of explanation
"""


operator.concat("ert", "erui")

operator.getitem(seq,1)

operator.indexOf(seq, 5)

"""
Explanation: operator下的这四则运算，都是针对两个数进行的，即参数只能是两个。为了能对多个数进行连续运算，就需要用reduce，它的意思是两个运算后，作为一个数，与下一个继续进行两个数运算，直到数列终。感觉和apply作用有点差不多，第一个参数是函数，第二个参数是数列（具体参数）。
End of explanation
"""


operator.sequenceIncludes(seq, 5)

"""
Explanation: getitem和indexOf为一对逆运算，前者求指定位置上的值，后者求给定值的位置。注意，后者是大写的字母ｏ。
End of explanation
"""


import UserList

def dump(data):
    print data,":"
    print type(data),"=>",
    if operator.isCallable(data):
        print "is a CALLABLE data."
    if operator.isMappingType(data):
        print "is a MAP data."
    if operator.isNumberType(data):
        print "is a NUMBER data."
    if operator.isSequenceType(data):
        print "is a SEQUENCE data."

dump(0)

dump([3,4,5,6])

dump("weioiuernj")

dump({"a":"155cm", "b":"187cm"})

dump(len)

dump(UserList)

dump(UserList.UserList)

dump(UserList.UserList())

"""
Explanation: 判断序列中是否包含某个值。结果是布尔值。
End of explanation
"""


import types

def check(object):
    if type(object) is types.IntType:
        print "INTEGER",
    if type(object) is types.FloatType:
        print "FLOAT",
    if type(object) is types.StringType:
        print "STRING",
    if type(object) is types.ClassType:
        print "CLASS",
    if type(object) is types.InstanceType:
        print "INSTANCE",
    print

check(0)

check(0.0)

check("picklecai")

class A:
    pass

check(A)

a = A()

check(a)

"""
Explanation: 15. types模块
End of explanation
"""


import gc

class Node:
    def __init__(self, name):
        self.name = name
        self.patrent = None
        self.children = []
        
    def addchild(self, node):
        node.parent = self
        self.children.append(node)
        
    def __repr__(self):
        return "<Node %s at %x" % (repr(self.name), id(self))
    
root = Node("monty")

root.addchild(Node("eric"))
root.addchild(Node("john"))
root.addchild(Node("michael"))

root.__init__("eric")

root.__repr__()

"""
Explanation: types 模块在第一次引入的时候会破坏当前的异常状态. 也就是说, 不要在异常处理语句块中导入该模块 ( 或其他会导入它的模块 ) .
16. gc模块
gc 模块提供了到内建循环垃圾收集器的接口。
End of explanation
"""


