<jupyter_start><jupyter_text>Python范儿：Coding Pythonically  1 数学定义：解析(Comprehensions，或称推导式)  1.1 让代码飞找到0-9之间的偶数<jupyter_code>#number = range(10)
size = 10
even_numbers = []

n = 0
while n < size:
    if n % 2==0:
         even_numbers.append(n)
    n += 1
print even_numbers<jupyter_output>[0, 2, 4, 6, 8]<jupyter_text>我们做的事情在数学定义上看来像是什么呢？$\{x|x \in \{0,1,2,....,9\}, s.t. x\%2==0 \}$<jupyter_code>{ x for x in range(10) if x % 2==0 }<jupyter_output><empty_output><jupyter_text>这种代码形式称为Comprehensions，也就是解析（推导式）。形式： {expr(item) for item in iterable if cond_expr(item)} 或者中括号、小括号包裹* 第一部分：元素，对元素的操作（运算与函数都可以）* 第二部分：遍历行为* 第三部分：筛选条件（可选）* 最后：用小括号，中括号，大括号包含住三部分，得到不同的数据结构或对象<jupyter_code>print [ x**2 for x in xrange(10)]<jupyter_output>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]<jupyter_text>1.2 使用中括号进行列表解析 回忆enumerate任务：把一个list里的元素和索引号找出来，更新回原来的list中去**循环操作可变类型**<jupyter_code>Lord_of_ring = ['Ainur','Dragons','Dwarves','Elves','Ents','Hobbits','Men','Orcs']

print type(enumerate(Lord_of_ring)),enumerate(Lord_of_ring)

for idx,element in enumerate(Lord_of_ring):
    Lord_of_ring[idx] ="{0}:{1}".format(idx,element)

print Lord_of_ring<jupyter_output><type 'enumerate'> <enumerate object at 0x1042d17d0>
['0:Ainur', '1:Dragons', '2:Dwarves', '3:Elves', '4:Ents', '5:Hobbits', '6:Men', '7:Orcs']<jupyter_text>**List Comprehension构造新列表**<jupyter_code>test =['Ainur','Dragons','Dwarves','Elves','Ents','Hobbits','Men','Orcs']

def _trans(idx,element):
    return '{0}:{1}'.format(idx,element)
print [_trans(idx,element) for idx,element in enumerate(test)]

print ['{0}:{1}'.format(idx,element) for idx,element in enumerate(test) ]<jupyter_output>['0:Ainur', '1:Dragons', '2:Dwarves', '3:Elves', '4:Ents', '5:Hobbits', '6:Men', '7:Orcs']
['0:Ainur', '1:Dragons', '2:Dwarves', '3:Elves', '4:Ents', '5:Hobbits', '6:Men', '7:Orcs']<jupyter_text>**老朋友Iterable，isinstance()检查**<jupyter_code>import collections

print isinstance("Hello,world",   collections.Iterable)
print isinstance( test,           collections.Iterable)<jupyter_output>True
True<jupyter_text>字典也是Iterable:<jupyter_code>language={"Scala":"<NAME>",\
          "Clojure":"<NAME>",\
          "C":"<NAME>",\
          "Standard ML":"<NAME>"}

['{0:<12} created by {1:<15}'.format(la,ua)\
 for la,ua in language.iteritems()]<jupyter_output><empty_output><jupyter_text>**多重解析**<jupyter_code>print [(x+1,y+1) for x in xrange(4) for y in xrange(4)]
print [(x+1,y+1) for x in xrange(4) for y in xrange(4) if y<x]
print [(x+1,y+1) for x in xrange(4) for y in xrange(x)]<jupyter_output>[(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 1), (4, 2), (4, 3), (4, 4)]
[(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3)]
[(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3)]<jupyter_text>1.3 使用小括号进行生成器 使用小括号做Comprehension返回生成器对象，占用O(1)内存空间：<jupyter_code>num=range(0,20)

simple_generator=(x**2 for x in num if x > 0)

print simple_generator

for element in simple_generator:
    print element,<jupyter_output><generator object <genexpr> at 0x1043e9dc0>
1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361<jupyter_text>1.4 使用大括号解析得到集合或字典 使用小括号解析并不会返回一个不可变元组而是生成器，是一个需要强记的规则；然而大括号解析式就普通了许多。<jupyter_code>x = range(10)

print { i for i in x if i%2==0 }
print { idx:i**2 for idx,i in enumerate(x) if i%2==0 }<jupyter_output>set([0, 8, 2, 4, 6])
{0: 0, 8: 64, 2: 4, 4: 16, 6: 36}<jupyter_text>注意生成字典时使用key:value的形式就可以了。  2 花样传参：zip与星号操作 * zip: 拉链函数* \*: 经常和zip在一起，用于传递参数。* \*\*: 用于传递关键字型参数  2.1 Zip(拉链) * enumerate: 返回生成器，生成器每次给出下标和Iterable的内容* sorted: 返回列表，可以进行排序* zip: 把多个长度相同的列表当成数据列组成的数据表，返回一个包含着元组的列表，每个元组是数据表中的一行<jupyter_code>war3_char = ['Orc','Humans','Undead','Night Elves']
dota_hero = ['Blade Master','Archmage','Death King','Demon Hunter']
Your_choice=zip(war3_char,dota_hero)
print Your_choice<jupyter_output>[('Orc', 'Blade Master'), ('Humans', 'Archmage'), ('Undead', 'Death King'), ('Night Elves', 'Demon Hunter')]<jupyter_text>取回原来的列表：<jupyter_code>choice1,choice2,choice3,choice4 = Your_choice
print zip(choice1,choice2,choice3,choice4)<jupyter_output>[('Orc', 'Humans', 'Undead', 'Night Elves'), ('Blade Master', 'Archmage', 'Death King', 'Demon Hunter')]<jupyter_text>用\*把Your_choice的内容而不是它本身作为参数传递<jupyter_code>print zip(*Your_choice)<jupyter_output>[('Orc', 'Humans', 'Undead', 'Night Elves'), ('Blade Master', 'Archmage', 'Death King', 'Demon Hunter')]<jupyter_text>\* 告诉Python即将传入的参数Your_choice不是单独一个序列，而是把Your_choice中的每一项作为参数从下面的字典里按值来排序，取到值最大或者值最小的那条记录：<jupyter_code>Base_Damage={'Blade Master':48,'Death King':65,'Tauren Chieftain':51}
print zip(Base_Damage.itervalues(),Base_Damage.iterkeys())
max_Damage=max(zip(Base_Damage.itervalues(),Base_Damage.iterkeys()))
min_Damage=min(zip(Base_Damage.itervalues(),Base_Damage.iterkeys()))

print max_Damage,min_Damage<jupyter_output>[(48, 'Blade Master'), (65, 'Death King'), (51, 'Tauren Chieftain')]
(65, 'Death King') (48, 'Blade Master')<jupyter_text>**花样传参**    刚才已经知道能把列表加星号保持有序地作为一个个参数（argument）传给方法/函数：<jupyter_code>def triplesum(a,b,c):
    return a*100+b*10+c

print triplesum(*[1,2,3])
print triplesum(1,2,3)<jupyter_output>123
123<jupyter_text>带默认值的参数叫keyword arguments(kargs):<jupyter_code>def triplesum_default(a=0,b=0,c=0,*args):
    return a*100+b*10+c

def ntuplesum_default(*args):
    sum = 0
    for i in args:
        sum*=10
        sum+=i
    return sum

print triplesum_default(*[1,2,3,4])
print ntuplesum_default(*[1,2,3,5])
print ntuplesum_default(1,2,3,5,6,7,8)
print triplesum_default(*[1,3])
print triplesum_default(**{'b':2,'c':3,'a':1})
print triplesum_default(**{'c':3,'a':1})<jupyter_output>123
1235
1235678
130
123
103<jupyter_text>3 变量之变：深浅拷贝 深浅拷贝：关系到变量的正确修改与复制变量的属性：* 身份：就像身份证（或者内存地址）那样，id()* 属性：表示变量的类型，type()或者isInstance()确认* 值：这个地址存的数据，通过与名字绑定的方法来读取  3.1 浅拷贝* 完全切片(Slicing)操作[:]* 工厂函数，比如list(),tuple()* copy中的copy<jupyter_code>import copy
unit = ['name',['Base_Damage',65.00]]
my_hero = unit[:]               #使用切片拷贝
your_hero = list(unit)          #使用工厂方法拷贝
its_hero = copy.copy(unit)      #使用浅拷贝
print [id(x) for x in unit,my_hero,your_hero,its_hero]
print [id(x[0]) for x in unit,my_hero,your_hero,its_hero]
print [id(x[1]) for x in unit,my_hero,your_hero,its_hero]<jupyter_output>[4361778168, 4361777736, 4371155352, 4371155424]
[4297703024, 4297703024, 4297703024, 4297703024]
[4361686984, 4361686984, 4361686984, 4361686984]<jupyter_text>假设一下，你的英雄打到了豪华套装（your_hero),或者游戏中的英雄（my_hero)有了一个嗜血的加成效果，所以数值会出现一些不一样的地方。<jupyter_code>my_hero[0] = 'Kel\'Thuzad'
your_hero[0] = 'Mirana'
its_hero[0] = 'Morphling'
print my_hero,your_hero,its_hero
my_hero[1][1]=100.00                   # 先更改一个对象的值
print my_hero,your_hero,its_hero       #  可以看出值的情况不对，my_hero<jupyter_output>["Kel'Thuzad", ['Base_Damage', 65.0]] ['Mirana', ['Base_Damage', 65.0]] ['Morphling', ['Base_Damage', 65.0]]
["Kel'Thuzad", ['Base_Damage', 100.0]] ['Mirana', ['Base_Damage', 100.0]] ['Morphling', ['Base_Damage', 100.0]]<jupyter_text>为什么相互影响了呢？<jupyter_code>print [id(x[0]) for x in unit,my_hero,your_hero,its_hero]
print [id(x[1]) for x in unit,my_hero,your_hero,its_hero]<jupyter_output>[4297703024, 4371530688, 4371530928, 4371530784]
[4361686984, 4361686984, 4361686984, 4361686984]<jupyter_text>* 第一个对象是不可变的（字符串），而且还重新被赋值* 而第二个对象是可变的（一个列表），而且修改的是第二个对象里面的内容，第二个对象本身指向的地址不变  3.2 资深玩家的选择：深拷贝<jupyter_code>import copy
unit = ['name',['Base_Damage',[65.00]]]
my_hero = copy.deepcopy(unit)
your_hero = copy.deepcopy(unit)

my_hero[0] = 'Kel\'Thuzad'
your_hero[0] = 'Mirana'
my_hero[1][1][0] = 100.00           

print my_hero,your_hero<jupyter_output>["Kel'Thuzad", ['Base_Damage', [100.0]]] ['Mirana', ['Base_Damage', [65.0]]]<jupyter_text>用id( )验证一下<jupyter_code>print [id(x) for x in my_hero]
print [id(x) for x in your_hero]<jupyter_output>[4371530880, 4361851032]
[4371531024, 4361851248]<jupyter_text>3.3 不想Debug太烦？ * 规避修改复杂可变类型内容，维护唯一拷贝* 规避使用可变类型* 理解Clojure  4 异常处理：Try-Except-Else-Finally **会犯错的是人，能原谅人的是……*** try* except* finally Python允许程序在运行当中检测错误。每检测到一个错误，Python解释器就引发一个异常并报出详细的错误信息：<jupyter_code>y = 6
x = 5
x,y = y,x
1/0<jupyter_output><empty_output><jupyter_text>* 我们执行了一个除零操作（这显然是非法的），报出了"ZeroDivisionError: integer division or modulo by zero"* 在使用Python编写程序时，认真查看报错信息* 建议多使用Ipython notebook 完成小代码块  4.1 基本用法：try-except Exception 如果你需要添加错误检测和异常处理，需要把你想要书写的代码组封装在try-except语句中。<jupyter_code>try:
    x = 1/0
    y = range(10)[10]
except Exception:
    print "Wow, such cute error"<jupyter_output>Wow, such cute error<jupyter_text>4.2 笔下无错，心中有错 常见的python中的异常，举例来说：* 有上文中已经出现的除零错误（ZeroDivisionError）* 尝试访问未声明的变量（NameError）* 语法错误    （Syntax Error）* 请求索引超过索引范围  （IndexError，常见于切片操作中）* 输入/输出错误  （IOError）<jupyter_code>try:
    x = 1/0
    y = range(10)[10] 
except ZeroDivisionError,e1:
    print "Wow, such cute divisor"
except IndexError,e2:
    print "Wow, such cute index"
    
print e1
try:
    x = 1/2
    y = range(10)[10] 
except ZeroDivisionError,e1:
    print "Wow, such cute divisor"
except IndexError,e2:
    print "Wow, such cute index"
    
print e2<jupyter_output>Wow, such cute index
list index out of range<jupyter_text>4.3 异常处理：完全体 通过try-except-else-finally来感受异常处理的完全体吧！* try 下面是可能有异常的代码块* except 下面是对异常的处理* else 下面是在并没有异常的时候执行的代码块* finally 下面是收尾工作，无论是否有异常都执行并用另一种方式记录异常。<jupyter_code>import sys

try:
    x = 1/0
    y = range(10)[-1]
except Exception,error:
    x = 0
    y = 9
    print 'X,Y is corrected.'
    info = sys.exc_info()
else:
    print 'Catch no exceptions. Great!'
finally:
    z = x + y
    print z**2 + x**2 + y**2
    print 'Finished'
    
print '\n',error,'\n',info[0],'\n',info[1],'\n',info[2],info[2].tb_lineno<jupyter_output>X,Y is corrected.
162
Finished

integer division or modulo by zero 
<type 'exceptions.ZeroDivisionError'> 
integer division or modulo by zero 
<traceback object at 0x1047b9a28> 4
{'fraction_non_alphanumeric': 0.17479423868312757, 'fraction_numerical': 0.07376543209876543, 'mean_word_length': 7.047185430463577, 'pattern_counts': {'":': 4, '<': 93, '<?xml version=': 0, '>': 90, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 17, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '25', 'dir': 'jupyter-structured-clean-dedup', 'id': '332035', 'license': 'MIT', 'n_tokens_mistral': 5343, 'n_tokens_neox': 5174, 'n_words': 748, 'path': 'Series_0_Python_Tutorials/S0EP3_Coding_Pythonically.ipynb', 'repo_name': 'shadowimp/python-', 'size': '9748'}