cross教学_crossing the river to school课件

cross教学_crossing the river to school课件一个很弱智的猜数字小游戏In [1]:fromrandomimportrandintnum=randint(1,100)print(‘guesswhatIthink?’)answer=int(input())while(answer!=num):ifanswer<num:print(‘toosmall?’)elifa…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

一个很弱智的猜数字小游戏

In [1]:
from random import randint

num = randint(1, 100)
print('guess what I think?')
answer = int(input())
while(answer!=num):
    if answer<num:
        print('too small?')
    elif answer>num:
        print('too big?')
    elif answer==num:
        break
    answer = int(input())
print('equal')

guess what I think?
50
too big?
25
too big?
10
too small?
15
too small?
17
too small?
19
equal

range 列表

In [2]:
sum = 0
for _ in range(1,101) :
    sum = sum + _
print(sum)

5050

print的简单用法

In [3]:
print("this is the\
 same line")

print('''
"What's your name?" I asked.
"I'm Han Meimei."
''')

num = 18
print ('My age is %d' % num)
print ('Price is %.2f' % 4.6765)

this is the same line

"What's your name?" I asked.
"I'm Han Meimei."

My age is 18
Price is 4.68

for嵌套

In [4]:
for i in range(0, 5):
    for j in range(0, i+1):
        print ('*',end=' ')
    print('\t')

* 	
* * 	
* * * 	
* * * * 	
* * * * * 	

字符串拼接 bool值

In [5]:
print ('%s is easy to %d' % ('Python',100))
bool(None)

Python is easy to 100

Out[5]:
False

函数定义

In [6]:
def sayHello(someone):
   print( someone + ' say hello world!')

sayHello('bzz')

def plus(num1, num2):
   print (num1+num2)

plus(1,5)

bzz say hello world!
6

函数实现弱智小游戏

In [7]:
def isEqual(num1, num2):
    if num1<num2:
        print ('too small')
        return False;
    elif num1>num2:
        print ('too big')
        return False;
    else :
        print ('bingo')
        return True

from random import randint

num = randint(1, 100)
print ('Guess what I think?')
bingo = False
while bingo == False:
    answer = int(input())
    bingo = isEqual(answer, num)

Guess what I think?
50
too small
80
too big
70
too big
65
too big
63
too big
55
too small
60
too big
58
too big
57
bingo

print(list(range(1,10))) 可以在python3shell下通过,但无法在jupyter notebook 中通过,目前无解

In [8]:
print(list(range(1,10)))

[1, 2, 3, 4, 5, 6, 7, 8, 9]

调用numpy 显示list

In [9]:
import numpy as np
a=np.arange(1,10)
print(a)

[1 2 3 4 5 6 7 8 9]

操作list

In [10]:
l = [365, 'everyday', 0.618, True]
print (l[1])
#修改list中的元素
l[0] = 123
print (l)
#向list中添加元素
l.append(1024)
print (l)
#删除list中的元素
del l[0]
print (l)

everyday
[123, 'everyday', 0.618, True]
[123, 'everyday', 0.618, True, 1024]
['everyday', 0.618, True, 1024]

点球游戏1

In [11]:
from random import choice
print ('Choose one side to shoot:')
print ('left, center, right')
you = input()
print ('You kicked ' + you)
direction = ['left', 'center', 'right']
com = choice(direction)
print ('Computer saved :' + com)
if you != com:
   print ('Goal!')
else:
   print ('Oops...')

Choose one side to shoot:
left, center, right
left
You kicked left
Computer saved :right
Goal!

list切片

  • list有两类常用操作:索引(index)和切片(slice)。
  • 上是索引,现使用切片
  • 切片操作符是在[]内提供一对可选数字,用 : 分割。冒号前的数表示切片的开始位置,冒号后的数字表示切片到哪里结束。同样,计数从0开始。 注意,开始位置包含在切片中,而结束位置不包括。

切片的语法表达式为:[start_index : end_index : step],其中: start_index表示起始索引end_index表示结束索引 step表示步长,步长不能为0,且默认值为1 切片操作是指按照步长,截取从起始索引到结束索引,但不包含结束索引(也就是结束索引减1)的所有元素。

python3支持切片操作的数据类型有list、tuple、string、unicode、range 切片返回的结果类型与原对象类型一致 切片不会改变原对象,而是重新生成了一个新的对象

In [12]:
l = ['a', 'b', 'c', 'd', 'e', 'f']
print(l[-1]) # "-" 表示倒数
print(l[-4])
print(l[0:4])

print(l[1:])
print(l[:3])
print(l[:])
print(l[1:-1])

f
c
['a', 'b', 'c', 'd']
['b', 'c', 'd', 'e', 'f']
['a', 'b', 'c']
['a', 'b', 'c', 'd', 'e', 'f']
['b', 'c', 'd', 'e']

点球游戏2

In [13]:
from random import choice

score_you = 0
score_com = 0
direction = ['left', 'center', 'right']

for i in range(5):
    print ('==== Round %d - You Kick! ====' % (i+1))
    print ('选一边射门')#Choose one side to shoot:
    print ('left, center, right')
    you = input()
    print ('You kicked ' + you)
    com = choice(direction)
    print ('Computer saved ' + com)
    if you != com:
        print ('Goal!')
        score_you += 1
    else:
        print ('Oops...')
        print ('Score: %d(you) - %d(com)\n' % (score_you, score_com))

    print ('==== Round %d - You Save! ====' % (i+1))
    print ('选一边守门:')
    print ('left, center, right')
    you = input()
    print ('You saved ' + you)
    com = choice(direction)
    print ('Computer kicked ' + com)
    if you == com:
        print ('Saved!')
    else:
        print ('Oops...')
        score_com += 1
    print ('Score: %d(you) - %d(com)\n' % (score_you, score_com))

==== Round 1 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 1 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 1(you) - 1(com)

==== Round 2 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved center
Goal!
==== Round 2 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked left
Saved!
Score: 2(you) - 1(com)

==== Round 3 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 3 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 3(you) - 2(com)

==== Round 4 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved left
Oops...
Score: 3(you) - 2(com)

==== Round 4 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 3(you) - 3(com)

==== Round 5 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 5 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked left
Saved!
Score: 4(you) - 3(com)

字符串的分割

In [14]:
sentence = 'I am an Englist sentence'
print(sentence.split())

# 指定参数分割 
section = 'Hi! I am the one! Bye!'
print(section.split('!')) # ! 所有都被分割 空格也是

print('_a!a a .'.split('a'))

['I', 'am', 'an', 'Englist', 'sentence']
['Hi', ' I am the one', ' Bye', '']
['_', '!', ' ', ' .']

点球游戏 加上胜负判断

In [15]:
from random import choice score = [0, 0] direction = ['left', 'center', 'right'] def kick(): print ('==== You Kick! ====') print ('Choose one side to shoot:') print ('left, center, right') you = input() print ('You kicked ' + you) com = choice(direction) print ('Computer saved ' + com) if you != com: print ('Goal!') score[0] += 1 else: print ('Oops...') print ('Score: %d(you) - %d(com)\n' % (score[0], score[1])) print ('==== You Save! ====') print ('Choose one side to save:') print ('left, center, right') you = input() print ('You saved ' + you) com = choice(direction) print ('Computer kicked ' + com) if you == com: print ('Saved!') else: print ('Oops...') score[1] += 1 print ('Score: %d(you) - %d(com)\n' % (score[0], score[1])) for i in range(5): print ('==== Round %d ====' % (i+1)) kick() while(score[0] == score[1]): i += 1 print ('==== Round %d ====' % (i+1)) kick() if score[0] > score[1]: print( 'You Win!') else: print ('You Lose.') 

==== Round 1 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 0(you) - 0(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 0(you) - 1(com) ==== Round 2 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved right Goal! Score: 1(you) - 1(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 1(you) - 2(com) ==== Round 3 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 1(you) - 2(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 1(you) - 3(com) ==== Round 4 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 1(you) - 3(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked left Saved! Score: 1(you) - 3(com) ==== Round 5 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved center Goal! Score: 2(you) - 3(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 2(you) - 4(com) You Lose. 

连接list

  • join和昨天说的split正好相反:split是把一个字符串分割成很多字符串组成的list,而join则是把一个list中的所有字符串连接成一个字符串。
  • join的格式有些奇怪,它不是list的方法,而是字符串的方法。首先你需要有一个字符串作为list中所有元素的连接符,然后再调用这个连接符的join方法,join的参数是被连接的list:

In [16]:
s = ';' li = ['apple', 'pear', 'orange'] fruit = s.join(li) print (fruit) print(';'.join(['apple', 'pear', 'orange'])) print(''.join(['hello', 'world'])) # 无缝连接 

apple;pear;orange apple;pear;orange helloworld 

字符串的索引和切片

join方法也可以对字符串使用,作用就是用连接符把字符串中的每个字符重新连接成一个新字符串

In [17]:
word = 'helloworld' for c in word: print (c,end='.') print('\t') print('0.1.2.3.4.5.6.7.8.9.') print (word[0]) print (word[-2]) print (word[5:7]) print (word[:-5]) print (word[:]) newword = ','.join(word) print(newword) 

h.e.l.l.o.w.o.r.l.d. 0.1.2.3.4.5.6.7.8.9. h l wo hello helloworld h,e,l,l,o,w,o,r,l,d 

读文件

In [18]:
f = open('data.txt') data1 = f.read() f = open('data.txt') data2 = f.readline() data3 = f.readlines() print(data1) print('--------------') print(data2) print('--------------') print(data3) f.close #释放资源 

sfd affffffff ~?! -------------- sfd -------------- ['affffffff\n', '~?!'] 

Out[18]:
<function TextIOWrapper.close()>

In [21]:
f = open('output.txt')#, 'w' data1 = f.read() f = open('data.txt') data2 = f.readline() data3 = f.readlines() print(data1) print('--------------') print(data2) print('--------------') print(data3) f.close #释放资源 

50 50 50 -------------- sfd -------------- ['affffffff\n', '~?!'] 

Out[21]:
<function TextIOWrapper.close()>

处理文件中的数据

In [22]:
f = open('scores.txt') lines = f.readlines() f.close() print(lines) 

['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] 

In [23]:
import os # 调用os后, f = open('results.txt','w') , 有此文件则打开,否则新建 results = [] for line in lines: data = line.split() #print(data) sum = 0 for score in data[1:]: sum += int(score) result = '%s\t: %d\n' % (data[0], sum) results.append(result) f = open('result.txt','w') f.writelines(results) f.close() 

break

如果在循环条件仍然满足或序列没有遍历完的时候,想要强行跳出循环,就需要用到break语句。

In [24]:
for i in range(10): a = input() if a == 'EOF': break 

2154 EOF 

continue

break是彻底地跳出循环,而continue只是略过本次循环的余下内容,直接进入下一次循环

In [25]:
f = open('scores.txt') lines = f.readlines() f.close() print(lines) import os # 调用os后, f = open('results.txt','w') , 有此文件则打开,否则新建 results = [] for line in lines: data = line.split() #print(data) sum = 0 for score in data[1:]: point = int(score) if point < 60: continue sum += point result = '%s\t: %d\n' % (data[0], sum) results.append(result) f = open('result.txt','w') f.writelines(results) f.close() 

['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] 

异常处理

In [26]:
#print (int('0.5')) import os try: #f = open('non-exist.txt') f = open('scores.txt') lines = f.readlines() f.close() print("Open success!",end = ' ') print(lines) except: print( 'File not exists.') print( 'Done') 

Open success! ['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] Done 

查天气 网络模块

In [7]:
import urllib3 http = urllib3.PoolManager() r = http.request('GET','http://www.baidu.com') print(r.status) print(r.data) 

200 b'<!DOCTYPE html><!--STATUS OK-->\r\n<html>\r\n<head>\r\n\t<meta http-equiv="content-type" content="text/html;charset=utf-8">\r\n\t<meta http-equiv="X-UA-Compatible" content="IE=Edge">\r\n\t<link rel="dns-prefetch" href="//s1.bdstatic.com"/>\r\n\t<link rel="dns-prefetch" href="//t1.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t2.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t3.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t10.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t11.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t12.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//b1.bdstatic.com"/>\r\n\t<title>\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93</title>\r\n\t<link href="http://s1.bdstatic.com/r/www/cache/static/home/css/index.css" rel="stylesheet" type="text/css" />\r\n\t<!--[if lte IE 8]><style index="index" >#content{height:480px\\9}#m{top:260px\\9}</style><![endif]-->\r\n\t<!--[if IE 8]><style index="index" >#u1 a.mnav,#u1 a.mnav:visited{font-family:simsun}</style><![endif]-->\r\n\t<script>var hashMatch = document.location.href.match(/#+(.*wd=[^&].+)/);if (hashMatch && hashMatch[0] && hashMatch[1]) {document.location.replace("http://"+location.host+"/s?"+hashMatch[1]);}var ns_c = function(){};</script>\r\n\t<script>function h(obj){obj.style.behavior=\'url(#default#homepage)\';var a = obj.setHomePage(\'//www.baidu.com/\');}</script>\r\n\t<noscript><meta http-equiv="refresh" content="0; url=/baidu.html?from=noscript"/></noscript>\r\n\t<script>window._ASYNC_START=new Date().getTime();</script>\r\n</head>\r\n<body link="#0000cc"><div id="wrapper" style="display:none;"><div id="u"><a href="//www.baidu.com/gaoji/preferences.html" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'setting\',\'login\':\'0\'})">\xe6\x90\x9c\xe7\xb4\xa2\xe8\xae\xbe\xe7\xbd\xae</a>|<a id="btop" href="/" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'index\',\'login\':\'0\'})">\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5</a>|<a id="lb" href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" οnclick="return false;" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'login\'})">\xe7\x99\xbb\xe5\xbd\x95</a><a href="https://passport.baidu.com/v2/?reg&regType=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'reg\'})" target="_blank" class="reg">\xe6\xb3\xa8\xe5\x86\x8c</a></div><div id="head"><div class="s_nav"><a href="/" class="s_logo" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'logo\'})"><img src="//www.baidu.com/img/baidu_jgylogo3.gif" width="117" height="38" border="0" alt="\xe5\x88\xb0\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5" title="\xe5\x88\xb0\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5"></a><div class="s_tab" id="s_tab"><a href="http://news.baidu.com/ns?cl=2&rn=20&tn=news&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'news\'})">\xe6\x96\xb0\xe9\x97\xbb</a>&#12288;<b>\xe7\xbd\x91\xe9\xa1\xb5</b>&#12288;<a href="http://tieba.baidu.com/f?kw=&fr=wwwt" wdfield="kw" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'tieba\'})">\xe8\xb4\xb4\xe5\x90\xa7</a>&#12288;<a href="http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'zhidao\'})">\xe7\x9f\xa5\xe9\x81\x93</a>&#12288;<a href="http://music.baidu.com/search?fr=ps&key=" wdfield="key" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'music\'})">\xe9\x9f\xb3\xe4\xb9\x90</a>&#12288;<a href="http://image.baidu.com/i?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'pic\'})">\xe5\x9b\xbe\xe7\x89\x87</a>&#12288;<a href="http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'video\'})">\xe8\xa7\x86\xe9\xa2\x91</a>&#12288;<a href="http://map.baidu.com/m?word=&fr=ps01000" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'map\'})">\xe5\x9c\xb0\xe5\x9b\xbe</a>&#12288;<a href="http://wenku.baidu.com/search?word=&lm=0&od=0" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'wenku\'})">\xe6\x96\x87\xe5\xba\x93</a>&#12288;<a href="//www.baidu.com/more/" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'more\'})">\xe6\x9b\xb4\xe5\xa4\x9a\xc2\xbb</a></div></div><form id="form" name="f" action="/s" class="fm" ><input type="hidden" name="ie" value="utf-8"><input type="hidden" name="f" value="8"><input type="hidden" name="rsv_bp" value="1"><span class="bg s_ipt_wr"><input name="wd" id="kw" class="s_ipt" value="" maxlength="100"></span><span class="bg s_btn_wr"><input type="submit" id="su" value="\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b" class="bg s_btn" οnmοusedοwn="this.className=\'bg s_btn s_btn_h\'" οnmοuseοut="this.className=\'bg s_btn\'"></span><span class="tools"><span id="mHolder"><div id="mCon"><span>\xe8\xbe\x93\xe5\x85\xa5\xe6\xb3\x95</span></div><ul id="mMenu"><li><a href="javascript:;" name="ime_hw">\xe6\x89\x8b\xe5\x86\x99</a></li><li><a href="javascript:;" name="ime_py">\xe6\x8b\xbc\xe9\x9f\xb3</a></li><li class="ln"></li><li><a href="javascript:;" name="ime_cl">\xe5\x85\xb3\xe9\x97\xad</a></li></ul></span><span class="shouji"><strong>\xe6\x8e\xa8\xe8\x8d\x90&nbsp;:&nbsp;</strong><a href="http://w.x.baidu.com/go/mini/8/10000020" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'bdbrowser\'})">\xe7\x99\xbe\xe5\xba\xa6\xe6\xb5\x8f\xe8\xa7\x88\xe5\x99\xa8\xef\xbc\x8c\xe6\x89\x93\xe5\xbc\x80\xe7\xbd\x91\xe9\xa1\xb5\xe5\xbf\xab2\xe7\xa7\x92\xef\xbc\x81</a></span></span></form></div><div id="content"><div id="u1"><a href="http://news.baidu.com" name="tj_trnews" class="mnav">\xe6\x96\xb0\xe9\x97\xbb</a><a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a><a href="http://map.baidu.com" name="tj_trmap" class="mnav">\xe5\x9c\xb0\xe5\x9b\xbe</a><a href="http://v.baidu.com" name="tj_trvideo" class="mnav">\xe8\xa7\x86\xe9\xa2\x91</a><a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">\xe8\xb4\xb4\xe5\x90\xa7</a><a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login" id="lb" οnclick="return false;">\xe7\x99\xbb\xe5\xbd\x95</a><a href="//www.baidu.com/gaoji/preferences.html" name="tj_settingicon" id="pf">\xe8\xae\xbe\xe7\xbd\xae</a><a href="//www.baidu.com/more/" name="tj_briicon" id="bri">\xe6\x9b\xb4\xe5\xa4\x9a\xe4\xba\xa7\xe5\x93\x81</a></div><div id="m"><p id="lg"><img src="//www.baidu.com/img/bd_logo.png" width="270" height="129"></p><p id="nv"><a href="http://news.baidu.com">\xe6\x96\xb0&nbsp;\xe9\x97\xbb</a>\xe3\x80\x80<b>\xe7\xbd\x91&nbsp;\xe9\xa1\xb5</b>\xe3\x80\x80<a href="http://tieba.baidu.com">\xe8\xb4\xb4&nbsp;\xe5\x90\xa7</a>\xe3\x80\x80<a href="http://zhidao.baidu.com">\xe7\x9f\xa5&nbsp;\xe9\x81\x93</a>\xe3\x80\x80<a href="http://music.baidu.com">\xe9\x9f\xb3&nbsp;\xe4\xb9\x90</a>\xe3\x80\x80<a href="http://image.baidu.com">\xe5\x9b\xbe&nbsp;\xe7\x89\x87</a>\xe3\x80\x80<a href="http://v.baidu.com">\xe8\xa7\x86&nbsp;\xe9\xa2\x91</a>\xe3\x80\x80<a href="http://map.baidu.com">\xe5\x9c\xb0&nbsp;\xe5\x9b\xbe</a></p><div id="fm"><form id="form1" name="f1" action="/s" class="fm"><span class="bg s_ipt_wr"><input type="text" name="wd" id="kw1" maxlength="100" class="s_ipt"></span><input type="hidden" name="rsv_bp" value="0"><input type=hidden name=ch value=""><input type=hidden name=tn value="baidu"><input type=hidden name=bar value=""><input type="hidden" name="rsv_spt" value="3"><input type="hidden" name="ie" value="utf-8"><span class="bg s_btn_wr"><input type="submit" value="\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b" id="su1" class="bg s_btn" οnmοusedοwn="this.className=\'bg s_btn s_btn_h\'" οnmοuseοut="this.className=\'bg s_btn\'"></span></form><span class="tools"><span id="mHolder1"><div id="mCon1"><span>\xe8\xbe\x93\xe5\x85\xa5\xe6\xb3\x95</span></div></span></span><ul id="mMenu1"><div class="mMenu1-tip-arrow"><em></em><ins></ins></div><li><a href="javascript:;" name="ime_hw">\xe6\x89\x8b\xe5\x86\x99</a></li><li><a href="javascript:;" name="ime_py">\xe6\x8b\xbc\xe9\x9f\xb3</a></li><li class="ln"></li><li><a href="javascript:;" name="ime_cl">\xe5\x85\xb3\xe9\x97\xad</a></li></ul></div><p id="lk"><a href="http://baike.baidu.com">\xe7\x99\xbe\xe7\xa7\x91</a>\xe3\x80\x80<a href="http://wenku.baidu.com">\xe6\x96\x87\xe5\xba\x93</a>\xe3\x80\x80<a href="http://www.hao123.com">hao123</a><span>&nbsp;|&nbsp;<a href="//www.baidu.com/more/">\xe6\x9b\xb4\xe5\xa4\x9a&gt;&gt;</a></span></p><p id="lm"></p></div></div><div id="ftCon"><div id="ftConw"><p id="lh"><a id="seth" onClick="h(this)" href="/" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'homepage\',\'pos\':0})">\xe6\x8a\x8a\xe7\x99\xbe\xe5\xba\xa6\xe8\xae\xbe\xe4\xb8\xba\xe4\xb8\xbb\xe9\xa1\xb5</a><a id="setf" href="//www.baidu.com/cache/sethelp/index.html" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'favorites\',\'pos\':0})" target="_blank">\xe6\x8a\x8a\xe7\x99\xbe\xe5\xba\xa6\xe8\xae\xbe\xe4\xb8\xba\xe4\xb8\xbb\xe9\xa1\xb5</a><a οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'tj_about\'})" href="http://home.baidu.com">\xe5\x85\xb3\xe4\xba\x8e\xe7\x99\xbe\xe5\xba\xa6</a><a οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'tj_about_en\'})" href="http://ir.baidu.com">About Baidu</a></p><p id="cp">&copy;2018&nbsp;Baidu&nbsp;<a href="/duty/" name="tj_duty">\xe4\xbd\xbf\xe7\x94\xa8\xe7\x99\xbe\xe5\xba\xa6\xe5\x89\x8d\xe5\xbf\x85\xe8\xaf\xbb</a>&nbsp;\xe4\xba\xacICP\xe8\xaf\x81030173\xe5\x8f\xb7&nbsp;<img src="http://s1.bdstatic.com/r/www/cache/static/global/img/gs_237f015b.gif"></p></div></div><div id="wrapper_wrapper"></div></div><div class="c-tips-container" id="c-tips-container"></div>\r\n<script>window.__async_strategy=2;</script>\r\n<script>var bds={se:{},su:{urdata:[],urSendClick:function(){}},util:{},use:{},comm : {domain:"http://www.baidu.com",ubsurl : "http://sclick.baidu.com/w.gif",tn:"baidu",queryEnc:"",queryId:"",inter:"",templateName:"baidu",sugHost : "http://suggestion.baidu.com/su",query : "",qid : "",cid : "",sid : "",indexSid : "",stoken : "",serverTime : "",user : "",username : "",loginAction : [],useFavo : "",pinyin : "",favoOn : "",curResultNum:"",rightResultExist:false,protectNum:0,zxlNum:0,pageNum:1,pageSize:10,newindex:0,async:1,maxPreloadThread:5,maxPreloadTimes:10,preloadMouseMoveDistance:5,switchAddMask:false,isDebug:false,ishome : 1},_base64:{domain : "http://b1.bdstatic.com/",b64Exp : -1,pdc : 0}};var name,navigate,al_arr=[];var selfOpen = window.open;eval("var open = selfOpen;");var isIE=navigator.userAgent.indexOf("MSIE")!=-1&&!window.opera;var E = bds.ecom= {};bds.se.mon = {\'loadedItems\':[],\'load\':function(){},\'srvt\':-1};try {bds.se.mon.srvt = parseInt(document.cookie.match(new RegExp("(^| )BDSVRTM=([^;]*)(;|$)"))[2]);document.cookie="BDSVRTM=;expires=Sat, 01 Jan 2000 00:00:00 GMT"; }catch(e){}</script>\r\n<script>if(!location.hash.match(/[^a-zA-Z0-9]wd=/)){document.getElementById("ftCon").style.display=\'block\';document.getElementById("u1").style.display=\'block\';document.getElementById("content").style.display=\'block\';document.getElementById("wrapper").style.display=\'block\';setTimeout(function(){try{document.getElementById("kw1").focus();document.getElementById("kw1").parentNode.className += \' iptfocus\';}catch(e){}},0);}</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/jquery/jquery-1.10.2.min_f2fb5194.js"></script>\r\n<script>(function(){var index_content = $(\'#content\');var index_foot= $(\'#ftCon\');var index_css= $(\'head [index]\');var index_u= $(\'#u1\');var result_u= $(\'#u\');var wrapper=$("#wrapper");window.index_on=function(){index_css.insertAfter("meta:eq(0)");result_common_css.remove();result_aladdin_css.remove();result_sug_css.remove();index_content.show();index_foot.show();index_u.show();result_u.hide();wrapper.show();if(bds.su&&bds.su.U&&bds.su.U.homeInit){bds.su.U.homeInit();}setTimeout(function(){try{$(\'#kw1\').get(0).focus();window.sugIndex.start();}catch(e){}},0);if(typeof initIndex==\'function\'){initIndex();}};window.index_off=function(){index_css.remove();index_content.hide();index_foot.hide();index_u.hide();result_u.show();result_aladdin_css.insertAfter("meta:eq(0)");result_common_css.insertAfter("meta:eq(0)");result_sug_css.insertAfter("meta:eq(0)");wrapper.show();};})();</script>\r\n<script>window.__switch_add_mask=1;</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/global/js/instant_search_newi_redirect1_20bf4036.js"></script>\r\n<script>initPreload();$("#u,#u1").delegate("#lb",\'click\',function(){try{bds.se.login.open();}catch(e){}});if(navigator.cookieEnabled){document.cookie="NOJS=;expires=Sat, 01 Jan 2000 00:00:00 GMT";}</script>\r\n<script>$(function(){for(i=0;i<3;i++){u($($(\'.s_ipt_wr\')[i]),$($(\'.s_ipt\')[i]),$($(\'.s_btn_wr\')[i]),$($(\'.s_btn\')[i]));}function u(iptwr,ipt,btnwr,btn){if(iptwr && ipt){iptwr.on(\'mouseover\',function(){iptwr.addClass(\'ipthover\');}).on(\'mouseout\',function(){iptwr.removeClass(\'ipthover\');}).on(\'click\',function(){ipt.focus();});ipt.on(\'focus\',function(){iptwr.addClass(\'iptfocus\');}).on(\'blur\',function(){iptwr.removeClass(\'iptfocus\');}).on(\'render\',function(e){var $s = iptwr.parent().find(\'.bdsug\');var l = $s.find(\'li\').length;if(l>=5){$s.addClass(\'bdsugbg\');}else{$s.removeClass(\'bdsugbg\');}});}if(btnwr && btn){btnwr.on(\'mouseover\',function(){btn.addClass(\'btnhover\');}).on(\'mouseout\',function(){btn.removeClass(\'btnhover\');});}}});</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/home/js/bri_7f1fa703.js"></script>\r\n<script>(function(){var _init=false;window.initIndex=function(){if(_init){return;}_init=true;var w=window,d=document,n=navigator,k=d.f1.wd,a=d.getElementById("nv").getElementsByTagName("a"),isIE=n.userAgent.indexOf("MSIE")!=-1&&!window.opera;(function(){if(/q=([^&]+)/.test(location.search)){k.value=decodeURIComponent(RegExp["\\x241"])}})();(function(){var u = G("u1").getElementsByTagName("a"), nv = G("nv").getElementsByTagName("a"), lk = G("lk").getElementsByTagName("a"), un = "";var tj_nv = ["news","tieba","zhidao","mp3","img","video","map"];var tj_lk = ["baike","wenku","hao123","more"];un = bds.comm.user == "" ? "" : bds.comm.user;function _addTJ(obj){addEV(obj, "mousedown", function(e){var e = e || window.event;var target = e.target || e.srcElement;if(target.name){ns_c({\'fm\':\'behs\',\'tab\':target.name,\'un\':encodeURIComponent(un)});}});}for(var i = 0; i < u.length; i++){_addTJ(u[i]);}for(var i = 0; i < nv.length; i++){nv[i].name = \'tj_\' + tj_nv[i];}for(var i = 0; i < lk.length; i++){lk[i].name = \'tj_\' + tj_lk[i];}})();(function() {var links = {\'tj_news\': [\'word\', \'http://news.baidu.com/ns?tn=news&cl=2&rn=20&ct=1&ie=utf-8\'],\'tj_tieba\': [\'kw\', \'http://tieba.baidu.com/f?ie=utf-8\'],\'tj_zhidao\': [\'word\', \'http://zhidao.baidu.com/search?pn=0&rn=10&lm=0\'],\'tj_mp3\': [\'key\', \'http://music.baidu.com/search?fr=ps&ie=utf-8\'],\'tj_img\': [\'word\', \'http://image.baidu.com/i?ct=201326592&cl=2&nc=1&lm=-1&st=-1&tn=baiduimage&istype=2&fm=&pv=&z=0&ie=utf-8\'],\'tj_video\': [\'word\', \'http://video.baidu.com/v?ct=301989888&s=25&ie=utf-8\'],\'tj_map\': [\'wd\', \'http://map.baidu.com/?newmap=1&ie=utf-8&s=s\'],\'tj_baike\': [\'word\', \'http://baike.baidu.com/search/word?pic=1&sug=1&enc=utf8\'],\'tj_wenku\': [\'word\', \'http://wenku.baidu.com/search?ie=utf-8\']};var domArr = [G(\'nv\'), G(\'lk\'),G(\'cp\')],kw = G(\'kw1\');for (var i = 0, l = domArr.length; i < l; i++) {domArr[i].onmousedown = function(e) {e = e || window.event;var target = e.target || e.srcElement,name = target.getAttribute(\'name\'),items = links[name],reg = new RegExp(\'^\\\\s+|\\\\s+\\x24\'),key = kw.value.replace(reg, \'\');if (items) {if (key.length > 0) {var wd = items[0], url = items[1],url = url + ( name === \'tj_map\' ? encodeURIComponent(\'&\' + wd + \'=\' + key) : ( ( url.indexOf(\'?\') > 0 ? \'&\' : \'?\' ) + wd + \'=\' + encodeURIComponent(key) ) );target.href = url;} else {target.href = target.href.match(new RegExp(\'^http:\\/\\/.+\\.baidu\\.com\'))[0];}}name && ns_c({\'fm\': \'behs\',\'tab\': name,\'query\': encodeURIComponent(key),\'un\': encodeURIComponent(bds.comm.user || \'\') });};}})();};if(window.pageState==0){initIndex();}})();document.cookie = \'IS_STATIC=1;expires=\' + new Date(new Date().getTime() + 10*60*1000).toGMTString();</script>\r\n</body></html>\r\n' 

面向对象

In [4]:
s = 'how are you' #s被赋值后就是一个字符串类型的对象 l = s.split() #split是字符串的方法,这个方法返回一个list类型的对象 #l是一个list类型的对象 #通过dir()方法可以查看一个类/变量的所有属性: print(dir(s)) print('---------') print(dir(list)) 

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] --------- ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 

  • 关键字class加上类名用来创建一个类。之后缩进的代码块是这个类的内部。在这里,我们用pass语句,表示一个空的代码块

In [6]:
class MyClass: print('bzz') pass mc = MyClass() print (mc) #mc是__main__模块中MyClass来的一个实例(instance) 

bzz <__main__.MyClass object at 0x0000025C1069EF98> 

In [12]:
# 给这个类加上一些域: # 给MyClass类增加了一个类变量name,并把它的值设为'Sam'。然后又增加了一个类方法sayHi # 调用类变量的方法是“对象.变量名”。你可以得到它的值,也可以改变它的值。 # 类方法和我们之前定义的函数区别在于,第一个参数必须为self。 # 而在调用类方法的时候,通过“对象.方法名()”格式进行调用, # 而不需要额外提供self这个参数的值。self在类方法中的值,就是你调用的这个对象本身 class MyClass: name = 'Sam' def sayHi(self): print ('Hello %s' % self.name) mc = MyClass() print (mc.name) MyClass.name = 'Mike' print(MyClass().name) mc.name = 'Lily' mc.sayHi() 

Sam Mike Hello Lily 

  • 假设我们有一辆汽车,我们知道它的速度(60km/h),以及A、B两地的距离(100km)。要算出开着这辆车从A地到B地花费的时间。

In [13]:
#面向过程的方法: speed = 60.0 distance = 100.0 time = distance / speed print (time) #面向对象的方法: class Car: speed = 0 def drive(self, distance): time = distance / self.speed print (time) car = Car() car.speed = 60.0 car.drive(100.0) 

1.6666666666666667 1.6666666666666667 

  • 如果我们让题目再稍稍复杂一点。假设我们又有了一辆更好的跑车,它的速度是150km/h,然后我们除了想从A到B,还要从B到C(距离200km)。要求分别知道这两种车在这两段路上需要多少时间。

In [16]:
#面向过程的方法: speed1 = 60.0 distance1 = 100.0 time1 = distance1 / speed1 print (time1) distance2 = 200.0 time2 = distance2 / speed1 print (time2) speed2 = 150.0 time3 = distance1 / speed2 print (time3) time4 = distance2 / speed2 print (time4) print('--------------') #面向对象的方法: class Car: speed = 0 def drive(self, distance): time = distance / self.speed print (time) car1 = Car() car1.speed = 60.0 car1.drive(100.0) car1.drive(200.0) car2 = Car() car2.speed = 150.0 car2.drive(100.0) car2.drive(200.0) 

1.6666666666666667 3.3333333333333335 0.6666666666666666 1.3333333333333333 -------------- 1.6666666666666667 3.3333333333333335 0.6666666666666666 1.3333333333333333 

仍然是从A地到B地,这次除了有汽车,我们还有了一辆自行车! 自行车和汽车有着相同的属性:速度(speed)。还有一个相同的方法(drive),来输出行驶/骑行一段距离所花的时间。但这次我们要给汽车增加一个属性:每公里油耗(fuel)。而在汽车行驶一段距离的方法中,除了要输出所花的时间外,还要输出所需的油量。

面向过程的方法,你可能需要写两个函数,然后把数据作为参数传递进去,在调用的时候要搞清应该使用哪个函数和哪些数据。有了面向对象,你可以把相关的数据和方法封装在一起,并且可以把不同类中的相同功能整合起来。这就需要用到面向对象中的另一个重要概念:继承。

我们要使用的方法是,创建一个叫做Vehicle的类,表示某种车,它包含了汽车和自行车所共有的东西:速度,行驶的方法。然后让Car类和Bike类都继承这个Vehicle类,即作为它的子类。在每个子类中,可以分别添加各自独有的属性。

In [20]:
# Vehicle类被称为基本类或超类,Car类和Bike类被成为导出类或子类 class Vehicle: def __init__(self,speed): self.speed = speed def drive(self,distance): print('need %f hour(s)'%(distance/self.speed)) class Bike(Vehicle): pass class Car(Vehicle): def __init__(self,speed,fuel): Vehicle.__init__(self,speed) self.fuel = fuel def drive(self,distance): Vehicle.drive(self,distance) print('need %f fuels'%(distance*self.fuel)) b = Bike(15.0) c = Car(80.0,0.012) b.drive(100) c.drive(100) ''' 解释一下代码: __init__函数会在类被创建的时候自动调用,用来初始化类。它的参数,要在创建类的时候提供。 于是我们通过提供一个数值来初始化speed的值。 注意:__init__是python的内置方法,类似的函数名前后是两个下英文划线,如果写错了, 则不会起到原本应有的作用。 class定义后面的括号里表示这个类继承于哪个类。 Bike(Vehicle)就是说Bike是继承自Vehicle中的子类。Vehicle中的属性和方法,Bike都会有。 因为Bike不需要有额外的功能,所以用pass在类中保留空块,什么都不用写。 Car类中,我们又重新定义了__init__和drive函数,这样会覆盖掉它继承自Vehicle的同名函数。 但我们依然可以通过“Vehicle.函数名”来调用它的超类方法。 以此来获得它作为Vehicle所具有的功能。注意,因为是通过类名调用方法, 而不是像之前一样通过对象来调用,所以这里必须提供self的参数值。 在调用超类的方法之后,我们又给Car增加了一个fuel属性,并且在drive中多输出一行信息。 ''' 

need 6.666667 hour(s) need 1.250000 hour(s) need 1.200000 fuels 

Out[20]:
'\n解释一下代码:\n\n__init__函数会在类被创建的时候自动调用,用来初始化类。它的参数,要在创建类的时候提供。\n于是我们通过提供一个数值来初始化speed的值。\n\n注意:__init__是python的内置方法,类似的函数名前后是两个下英文划线,如果写错了,\n则不会起到原本应有的作用。\n\nclass定义后面的括号里表示这个类继承于哪个类。\nBike(Vehicle)就是说Bike是继承自Vehicle中的子类。Vehicle中的属性和方法,Bike都会有。\n因为Bike不需要有额外的功能,所以用pass在类中保留空块,什么都不用写。\n\nCar类中,我们又重新定义了__init__和drive函数,这样会覆盖掉它继承自Vehicle的同名函数。\n但我们依然可以通过“Vehicle.函数名”来调用它的超类方法。\n以此来获得它作为Vehicle所具有的功能。注意,因为是通过类名调用方法,\n而不是像之前一样通过对象来调用,所以这里必须提供self的参数值。\n在调用超类的方法之后,我们又给Car增加了一个fuel属性,并且在drive中多输出一行信息。\n\n\n'

and-or

In [21]:
a = "heaven" b = "hell" c = True and a or b print (c) d = False and a or b print (d) 

heaven hell 

结果很奇怪是不是?

表达式从左往右运算,1和”heaven”做and的结果是”heaven”,再与”hell”做or的结果是”heaven”;0和”heaven”做and的结果是0,再与”hell”做or的结果是”hell”。

抛开绕人的and和or的逻辑,你只需记住,在一个bool and a or b语句中,当bool条件为真时,结果是a;当bool条件为假时,结果是b。

有学过c/c++的同学应该会发现,这和bool?a:b表达式很像。

有了它,原本需要一个if-else语句表述的逻辑:

if a > 0:

print “big”

else:

print “small”

就可以直接写成:

print (a > 0) and “big” or “small”

然而不幸的是,如果直接这么用,有一天你会踩到坑的。和c语言中的?:表达式不同,这里的and or语句是利用了python中的逻辑运算实现的。当a本身是个假值(如0,””)时,结果就不会像你期望的那样。 比如: a = “”

b = “hell”

c = True and a or b

print c

得到的结果不是””而是”hell”。因为””和”hell”做or的结果是”hell”。

所以,and-or真正的技巧在于,确保a的值不会为假。最常用的方式是使 a 成为 [a] 、 b 成为 [b],然后使用返回值列表的第一个元素:

a = “”

b = “hell”

c = (True and [a] or [b])[0]

print c

由于[a]是一个非空列表,所以它决不会为假。即使a是0或者”或者其它假值,列表[a]也为真,因为它有一个元素。

在两个常量值进行选择时,and-or会让你的代码更简单。但如果你觉得这个技巧带来的副作用已经让你头大了,没关系,用if-else可以做相同的事情。不过在python的某些情况下,你可能没法使用if语句,比如lambda函数中,这时候你可能就需要and-or的帮助了。

什么是lambda函数?呵呵,这是python的高阶玩法,暂且按住不表,以后有机会再说。

In [25]:
a = "" b = "hell" c = (True and [a] or [b])[0] print (c) 

 

元组

In [31]:
#上一次pygame的课中有这样一行代码: #x, y = pygame.mouse.get_pos() # 元组(tuple)也是一种序列,和我们用了很多次的list类似, # 只是元组中的元素在创建之后就不能被修改。 # 如: postion = (1, 2) geeks = ('Sheldon', 'Leonard', 'Rajesh', 'Howard') # 都是元组的实例。它有和list同样的索引、切片、遍历等操作(参见25~27课): print (postion[0]) print('------------') for _ in geeks: print (_) print('------------') print (geeks[1:3]) #其实我们之前一直在用元组,就是在print语句中: print('------------') print ('%s is %d years old' % ('Mike', 23)) #('Mike', 23)就是一个元组。这是元组最常见的用处。 #再来看一下元组作为函数返回值的例子: def get_pos(n): return (n/2, n*2) #得到这个函数的返回值有两种形式,一种是根据返回值元组中元素的个数提供变量: x, y = get_pos(50) print (x) print (y) print('------------') #这就是我们在开头那句代码中使用的方式。 #还有一种方法是用一个变量记录返回的元组: pos = get_pos(50) print (pos[0]) print (pos[1]) 

1 ------------ Sheldon Leonard Rajesh Howard ------------ ('Leonard', 'Rajesh') ------------ Mike is 23 years old 25.0 100 ------------ 25.0 100 

数学运算

In [40]:
import math print(math.pi) print(math.e) print(math.ceil(5.4)) print(math.floor(5.4)) print(math.pow(3,2)) print(math.log(4)) print(math.log(100,10)) print(math.sqrt(9)) print(math.fabs(-34)) #math.sin .cos .tan .asin .acos .atan 弧度单位 #math.degrees(x) 弧度转角度 #math.radians(x) 角度转弧度 

3.141592653589793 2.718281828459045 6 5 9.0 1.3862943611198906 2.0 3.0 34.0 

正则表达式

什么是正则表达式?在回答这个问题之前,先来看看为什么要有正则表达式。

在编程处理文本的过程中,经常会需要按照某种规则去查找一些特定的字符串。比如知道一个网页上的图片都是叫做’image/8554278135.jpg’之类的名字,只是那串数字不一样;又或者在一堆人员电子档案中,你要把他们的电话号码全部找出来,整理成通讯录。诸如此类工作,如果手工去做,当量大的时候那简直就是悲剧。但你知道这些字符信息有一定的规律,可不可以利用这些规律,让程序自动来做这些无聊的事情?答案是肯定的。这时候,你就需要一种描述这些规律的方法,正则表达式就是干这事的。

正则表达式就是记录文本规则的代码。

所以正则表达式并不是python中特有的功能,它是一种通用的方法。python中的正则表达式库,所做的事情是利用正则表达式来搜索文本。要使用它,你必须会自己用正则表达式来描述文本规则。之前多次有同学表示查找文本的事情经常会遇上,希望能介绍一下正则表达式。既然如此,我们就从正则表达式的基本规则开始说起。

1.

首先说一种最简单的正则表达式,它没有特殊的符号,只有基本的字母或数字。它满足的匹配规则就是完全匹配。例如:有个正则表达式是“hi”,那么它就可以匹配出文本中所有含有hi的字符。

来看如下的一段文字:

Hi, I am Shirley Hilton. I am his wife.

如果我们用“hi”这个正则表达式去匹配这段文字,将会得到两个结果。因为是完全匹配,所以每个结果都是“hi”。这两个“hi”分别来自“Shirley”和“his”。默认情况下正则表达式是严格区分大小写的,所以“Hi”和“Hilton”中的“Hi”被忽略了。

为了验证正则表达式匹配的结果,你可以用以下这段代码做实验:

In [6]:
import re text = "Hi, I am Shirley Hilton. I am his wife.hi" m = re.findall(r"[Hh]i", text) if m: print (m) else: print ('not match') 

['Hi', 'hi', 'Hi', 'hi', 'hi'] 

暂时先不解释这其中代码的具体含义,你只要去更改text和findall中的字符串,就可以用它来检测正则表达式的实际效果。

2.

如果我们只想找到“hi”这个单词,而不把包含它的单词也算在内,那就可以使用“\bhi\b”这个正则表达式。在以前的字符串处理中,我们已经见过类似“\n”这种特殊字符。在正则表达式中,这种字符更多,以后足以让你眼花缭乱。

“\b”在正则表达式中表示单词的开头或结尾,空格、标点、换行都算是单词的分割。而“\b”自身又不会匹配任何字符,它代表的只是一个位置。所以单词前后的空格标点之类不会出现在结果里。

在前面那个例子里,“\bhi\b”匹配不到任何结果。但“\bhi”的话就可以匹配到1个“hi”,出自“his”。用这种方法,你可以找出一段话中所有单词“Hi”,想一下要怎么写。

3.

最后再说一下[]这个符号。在正则表达式中,[]表示满足括号中任一字符。比如“[hi]”,它就不是匹配“hi”了,而是匹配“h”或者“i”。

在前面例子中,如果把正则表达式改为“[Hh]i”,就可以既匹配“Hi”,又匹配“hi”了。

1.r”hi”

这里字符串前面加了r,是raw的意思,它表示对字符串不进行转义。为什么要加这个?你可以试试print “\bhi”和r”\bhi”的区别。

print “\bhi”

hi

print r”\bhi”

\bhi

可以看到,不加r的话,\b就没有了。因为python的字符串碰到“\”就会转义它后面的字符。如果你想在字符串里打“\”,则必须要打“\”。

print “\bhi”

\bhi

这样的话,我们的正则表达式里就会多出很多“\”,让本来就已经复杂的字符串混乱得像五仁月饼一般。但加上了“r”,就表示不要去转义字符串中的任何字符,保持它的原样。

2.re.findall(r”hi”, text)

re是python里的正则表达式模块。findall是其中一个方法,用来按照提供的正则表达式,去匹配文本中的所有符合条件的字符串。返回结果是一个包含所有匹配的list。

3.今天主要说两个符号“.”和“*”,顺带说下“\S”和“?”。

“.”在正则表达式中表示除换行符以外的任意字符。在上节课提供的那段例子文本中:

Hi, I am Shirley Hilton. I am his wife.

如果我们用“i.”去匹配,就会得到

[‘i,’, ‘ir’, ‘il’, ‘is’, ‘if’]

你若是暴力一点,也可以直接用“.”去匹配,看看会得到什么。

与“.”类似的一个符号是“\S”,它表示的是不是空白符的任意字符。注意是大写字符S。

4.在很多搜索中,会用“?”表示任意一个字符, 表示任意数量连续字符,这种被称为通配符。但在正则表达式中,任意字符是用 “ . ” 表示,而 则不是表示字符,而是表示数量:它表示前面的字符可以重复任意多次(包括0次),只要满足这样的条件,都会被表达式匹配上。

结合前面的“.”,用“I.e”去匹配,想一下会得到什么结果?

[‘I am Shirley Hilton. I am his wife’]

是不是跟你想的有些不一样?也许你会以为是

[‘I am Shirle’, ‘I am his wife’]

这是因为“”在匹配时,会匹配尽可能长的结果。如果你想让他匹配到最短的就停止,需要用“.?”。如“I.*?e”,就会得到第二种结果。这种匹配方式被称为懒惰匹配,而原本尽可能长的方式被称为贪婪匹配。

最后留一道习题:

从下面一段文本中,匹配出所有s开头,e结尾的单词。

site sea sue sweet see case sse ssee loses

先来公布上一课习题的答案:

\bs\S*e\b

有的同学给出的答案是”\bs.*?e\b”。测试一下就会发现,有奇怪的’sea sue’和’sweet see’混进来了。既然是单词,我们就不要空格,所以需要用”\S”而不是”.”

昨天有位同学在论坛上说,用正则表达式匹配出了文件中的手机号。这样现学现用很不错。匹配的规则是”1.*?\n”,在这个文件的条件下,是可行的。但这规则不够严格,且依赖于手机号结尾有换行符。今天我来讲讲其他的方法。

匹配手机号,其实就是找出一串连续的数字。更进一步,是11位,以1开头的数字。

还记得正则第1讲里提到的[]符号吗?它表示其中任意一个字符。所以要匹配数字,我们可以用

[0123456789]

由于它们是连续的字符,有一种简化的写法:[0-9]。类似的还有[a-zA-Z]的用法。

还有另一种表示数字的方法:

\d

要表示任意长度的数字,就可以用

[0-9]*

或者

\d*

但要注意的是,表示的任意长度包括0,也就是没有数字的空字符也会被匹配出来。一个与类似的符号+,表示的则是1个或更长。

所以要匹配出所有的数字串,应当用

[0-9]+

或者

\d+

如果要限定长度,就用{}代替+,大括号里写上你想要的长度。比如11位的数字:

\d{11}

想要再把第一位限定为1,就在前面加上1,后面去掉一位:

1\d{10}

OK. 总结一下今天提到的符号:

[0-9]

\d

+

{}

现在你可以去一个混杂着各种数据的文件里,抓出里面的手机号,或是其他你感兴趣的数字了。

1.

我们已经了解了正则表达式中的一些特殊符号,如\b、\d、.、\S等等。这些具有特殊意义的专用字符被称作“元字符”。常用的元字符还有:

\w – 匹配字母或数字或下划线或汉字(我试验下了,发现3.x版本可以匹配汉字,但2.x版本不可以)

\s – 匹配任意的空白符

^ – 匹配字符串的开始

$ – 匹配字符串的结束

2.

\S其实就是\s的反义,任意不是空白符的字符。同理,还有:

\W – 匹配任意不是字母,数字,下划线,汉字的字符

\D – 匹配任意非数字的字符

\B – 匹配不是单词开头或结束的位置

[a]的反义是[^a],表示除a以外的任意字符。[^abcd]就是除abcd以外的任意字符。

3.

之前我们用过*、+、{}来表示字符的重复。其他重复的方式还有:

? – 重复零次或一次

{n,} – 重复n次或更多次

{n,m} – 重复n到m次

正则表达式不只是用来从一大段文字中抓取信息,很多时候也被用来判断输入的文本是否符合规范,或进行分类。来点例子看看:

^\w{4,12}$

这个表示一段4到12位的字符,包括字母或数字或下划线或汉字,可以用来作为用户注册时检测用户名的规则。(但汉字在python2.x里面可能会有问题)

\d{15,18}

表示15到18位的数字,可以用来检测身份证号码

^1\d*x?

以1开头的一串数字,数字结尾有字母x,也可以没有。有的话就带上x。

另外再说一下之前提到的转义字符\。如果我们确实要匹配.或者字符本身,而不是要它们所代表的元字符,那就需要用.或\。\本身也需要用\。

比如”\d+.\d+”可以匹配出123.456这样的结果。

留一道稍稍有难度的习题:

写一个正则表达式,能匹配出多种格式的电话号码,包括

(021)88776543

010-55667890

02584453362

0571 66345673

来说上次的习题:

(021)88776543

010-55667890

02584453362

0571 66345673

一个可以匹配出所有结果的表达式是

(?0\d{2,3}[) -]?\d{7,8}

解释一下:

(?

()在正则表达式里也有着特殊的含义,所以要匹配字符”(“,需要用”(“。?表示这个括号是可有可无的。

0\d{2,3}

区号,0xx或者0xxx

[) -]?

在区号之后跟着的可能是”)”、” “、”-“,也可能什么也没有。

\d{7,8}

7或8位的电话号码

可是,这个表达式虽然能匹配出所有正确的数据(一般情况下,这样已经足够),但理论上也会匹配到错误的数据。因为()应当是成对出现的,表达式中对于左右两个括号并没有做关联处理,例如(02188776543这样的数据也是符合条件的。

我们可以用正则表达式中的“|”符号解决这种问题。“|”相当于python中“or”的作用,它连接的两个表达式,只要满足其中之一,就会被算作匹配成功。

于是我们可以把()的情况单独分离出来:

(0\d{2,3})\d{7,8}

其他情况:

0\d{2,3}[ -]?\d{7,8}

合并:

(0\d{2,3})\d{7,8}|0\d{2,3}[ -]?\d{7,8}

使用“|”时,要特别提醒注意的是不同条件之间的顺序。匹配时,会按照从左往右的顺序,一旦匹配成功就停止验证后面的规则。假设要匹配的电话号码还有可能是任意长度的数字(如一些特殊的服务号码),你应该把

|\d+

这个条件加在表达式的最后。如果放在最前面,某些数据就可能会被优先匹配为这一条件。你可以写个测试用例体会一下两种结果的不同。

关于正则表达式,我们已经讲了5篇,介绍了正则表达式最最皮毛的一些用法。接下来,这个话题要稍稍告一段落。推荐一篇叫做《正则表达式30分钟入门教程》的文章(直接百度一下就能找到,我也会转到论坛上),想要对正则表达式进一步学习的同学可以参考。这篇教程是个标题党,里面涉及了正则表达式较多的内容,30分钟绝对看不完。

random模块的作用是产生随机数。之前的小游戏中用到过random中的randint:

import random

num = random.randint(1,100)

random.randint(a, b)可以生成一个a到b间的随机整数,包括a和b。

a、b都必须是整数,且必须b≥a。当等于的时候,比如:

random.randint(3, 3)

的结果就永远是3

除了randint,random模块中比较常用的方法还有:

random.random()

生成一个0到1之间的随机浮点数,包括0但不包括1,也就是[0.0, 1.0)。

random.uniform(a, b)

生成a、b之间的随机浮点数。不过与randint不同的是,a、b无需是整数,也不用考虑大小。

random.uniform(1.5, 3)

random.uniform(3, 1.5)

这两种参数都是可行的。

random.uniform(1.5, 1.5)永远得到1.5。

random.choice(seq)

从序列中随机选取一个元素。seq需要是一个序列,比如list、元组、字符串。

random.choice([1, 2, 3, 5, 8, 13]) #list

random.choice(‘hello’) #字符串

random.choice([‘hello’, ‘world’]) #字符串组成的list

random.choice((1, 2, 3)) #元组

都是可行的用法。

random.randrange(start, stop, step)

生成一个从start到stop(不包括stop),间隔为step的一个随机数。start、stop、step都要为整数,且start<stop。

比如:

random.randrange(1, 9, 2)

就是从[1, 3, 5, 7]中随机选取一个。

start和step都可以不提供参数,默认是从0开始,间隔为1。但如果需要指定step,则必须指定start。

random.randrange(4) #[0, 1, 2, 3]

random.randrange(1, 4) #[1, 2, 3]

random.randrange(start, stop, step)其实在效果上等同于

random.choice(range(start, stop, step))

random.sample(population, k)

从population序列中,随机获取k个元素,生成一个新序列。sample不改变原来序列。

random.shuffle(x)

把序列x中的元素顺序打乱。shuffle直接改变原有的序列。

以上是random中常见的几个方法。如果你在程序中需要其中某一个方法,也可以这样写:

from random import randint

randint(1, 10)

另外,有些编程基础的同学可能知道,在随机数中有个seed的概念,需要一个真实的随机数,比如此刻的时间、鼠标的位置等等,以此为基础产生伪随机数。在python中,默认用系统时间作为seed。你也可以手动调用random.seed(x)来指定seed。

Python中有一个time模块

它提供了一些与时间相关的方法。利用time,可以简单地计算出程序运行的时间。对于一些比较复杂、耗时较多的程序,可以通过这种方法了解程序中哪里是效率的瓶颈,从而有针对性地进行优化。

在计算机领域有一个特殊的时间,叫做epoch,它表示的时间是1970-01-01 00:00:00 UTC。

Python中time模块的一个方法

time.time()

返回的就是从epoch到当前的秒数(不考虑闰秒)。这个值被称为unix时间戳。

于是我们可以用这个方法得到程序开始和结束所用的时间,进而算出运行的时间:

In [9]:
import time starttime = time.time() print ('start:%f' % starttime) for i in range(10): print (i) endtime = time.time() print ('end:%f' % endtime) print ('total time:%f' % (endtime-starttime)) 

start:1530929854.164775 0 1 2 3 4 5 6 7 8 9 end:1530929854.165777 total time:0.001002 

顺便再说下time中的另一个很有用的方法:

time.sleep(secs)

它可以让程序暂停secs秒。例如:

In [12]:
import time print (1) time.sleep(2) print (2) 

1 2 

今天我就来讲讲代码遇到问题时的一些简单处理方法。

  1. 读错误信息

来看如下一个例程:

import random

a = 0

for i in range(5):

b = random.choice(range(5))
a += i / b

print a

这个程序中,i从0循环到4,每次循环中,b是0到4中的一个随机数。把i/b的结果累加到a上,最后输出结果。

运行这段程序,有时候会输出结果,有时候却跳出错误信息:

Traceback (most recent call last):

File “C:\Users\Crossin\Desktop\py\test.py”, line 5, in

a += i / b

ZeroDivisionError: integer division or modulo by zero

有些同学看见一段英文提示就慌了。其实没那么复杂,python的错误提示做得还是很标准的。

它告诉我们错误发生在test.py文件中的第6行

a += i / b

这一句上。

这个错误是“ZeroDivisionError”,也就是除零错。

“integer division or modulo by zero”,整数被0除或者被0模(取余数)。

因为0不能作为除数,所以当b随机到0的时候,就会引发这个错误。

知道了原因,就可以顺利地解决掉这个bug。

以后在写代码的时候,如果遇到了错误,先别急着去改代码。试着去读一读错误提示,看看里面都说了些啥。

  1. 输出调试信息

我们在所有课程的最开始就教了输出函数“print”。它是编程中最简单的调试手段。有的时候,仅从错误提示仍然无法判断出程序错误的原因,或者没有发生错误,但程序的结果就是不对。这种情况下,通过输出程序过程中的一些状态,可以帮助分析程序。

把前面那个程序改造一下,加入一些与程序功能无关的输出语句:

import random

a = 0

for i in range(5):

print 'i: %d' % i 
b = random.choice(range(5))
print 'b: %d' % b
a += i / b
print 'a: %d' % a
print

print a

运行后的输出结果(每次结果都会不一样):

i: 0

b: 3

a: 0

i: 1

b: 3

a: 0

i: 2

b: 3

a: 0

i: 3

b: 0

Traceback (most recent call last):

File “C:\Users\Crossin\Desktop\py\test.py”, line 7, in

a += i / b

ZeroDivisionError: integer division or modulo by zero

当b的值为0时,发生了除零错。这次可以更清晰地看出程序出错时的状态。

在真实开发中,程序的结构可能会非常复杂。通过输出调试信息,可以有效地缩小范围、定位错误发生的位置,确认错误发生时的场景,进而找出错误原因。

序列化 pickle

  • python3 在字符方面和 python2 区别较大

In [30]:
import pickle test_data = ['Save me!'.encode('utf8'), 123.456, True] f = open('test.data', 'wb+') pickle.dump(test_data, f) f.close() 

In [32]:
import pickle f = open('test.data','rb') test_data = pickle.load(f) f.close() print (test_data) 

[b'Save me!', 123.456, True] 

如果你想保存多个对象,一种方法是把这些对象先全部放在一个序列中,在对这个序列进行存储:

a = 123

b = “hello”

c = 0.618

data = (a, b, c)

pickle.dump(data, f)

另一种方法就是依次保存和提取:

pickle.dump(a, f)

pickle.dump(b, f)

pickle.dump(c, f)

x = pickle.load(f)

y = pickle.load(f)

z = pickle.load(f)

dump 方法可以增加一个可选的参数,来指定用二进制来存储:

pickle.dump(data, f, True)

而 load 方法会自动检测数据是二进制还是文本格式,无需手动指定。

【特别说明】python3中,通过pickle对数据进行存储时,必须用二进制(b)模式读写文件。

Python 还提供了另一个模块 cPickle,它的功能及用法和 pickle 模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle快1000倍)。因此你可以把上述代码中的 pickle 全部替换为 cPickle,从而提高运行速度(尽管在这个小程序中影响微乎其微)。

列表解析(List Comprehension)

In [33]:
list_1 = [1, 2, 3, 5, 8, 13, 22] list_2 = [] for i in list_1: if i % 2 == 0: list_2.append(i) print (list_2) 

[2, 8, 22] 

In [34]:
list_1 = [1, 2, 3, 5, 8, 13, 22] list_2 = [i for i in list_1 if i % 2 == 0] print (list_2) 

[2, 8, 22] 

函数的参数传递

我们曾经讲过 Python 中函数的参数传递(见第21课)。最基本的方式是:

定义:

def func(arg1, arg2):

print arg1, arg2

调用:

func(3, 7)

我们把函数定义时的参数名(arg1、arg2)称为形参,调用时提供的参数(3、7)称为实参。

这种方式是根据调用时提供参数的位置进行匹配,要求实参与行参的数量相等,默认按位置匹配参数。调用时,少参数或者多参数都会引起错误。这是最常用的一种函数定义方式。

在调用时,也可以根据形参的名称指定实参。如:

func(arg2=3, arg1=7)

但同样,必须提供所有的参数。看看和func(3, 7)的运行结果有什么不同。

Python 语言还提供了其他一些更灵活的参数传递方式,如:

func2(a=1, b=2, c=3)

func3(*args)

func4(**kargs)

今天我们先说说func2这种方式。

这种方式可以理解为,在一般函数定义的基础上,增加了参数的默认值。这样定义的函数可以和原来一样使用,而当你没有提供足够的参数时,会用默认值作为参数的值。

例如:

定义

In [2]:
def func(arg1=1, arg2=2, arg3=3): print (arg1, arg2, arg3) 

In [3]:
# 调用: func(2, 3, 4) func(5, 6) func(7) 

2 3 4 5 6 3 7 2 3 

输出为

2 3 4

5 6 3

7 2 3

提供的参数会按顺序先匹配前面位置的参数,后面未匹配到的参数使用默认值。

也可以指定其中的部分参数,如:

In [4]:
func(arg2=8) func(arg3=9, arg1=10) 

1 8 3 10 2 9 

输出为

1 8 3

10 2 9

In [5]:
#或者混合起来用: func(11, arg3=12) 

11 2 12 

输出为

11 2 12

但要注意,没有指定参数名的参数必须在所有指定参数名的参数前面,且参数不能重复。以下的调用都是错误的:

func(arg1=13, 14)

func(15, arg1=16)

定义参数默认值的函数可以在调用时更加简洁。大量 Python 模块中的方法都运用了这一方式,让使用者在调用时可以提供尽可能少的参数。

接着上一次的内容,来介绍一种更加灵活的参数传递方式:

def func(*args)

这种方式的厉害之处在于,它可以接受任意数量的参数。来看具体例子:

In [7]:
def calcSum(*args): sum = 0 for i in args: sum += i print (sum) 

In [9]:
# 调用 calcSum(1,2,3) calcSum(123,456) calcSum() 

6 579 0 

输出:

6

579

0

在变量前加上星号前缀(*),调用时的参数会存储在一个 tuple(元组)对象中,赋值给形参。在函数内部,需要对参数进行处理时,只要对这个 tuple 类型的形参(这里是 args)进行操作就可以了。因此,函数在定义时并不需要指明参数个数,就可以处理任意参数个数的情况。

不过有一点需要注意,tuple 是有序的,所以 args 中元素的顺序受到赋值时的影响。如:

In [14]:
def printAll(*args): for i in args: print (i,end=' ') print() 

In [15]:
#调用: printAll(1,2,3) printAll(3,2,1) 

1 2 3 3 2 1 

输出:

1 2 3

3 2 1

虽然3个参数在总体上是相同的,但由于调用的顺序不一样,结果也是不同的。

还有一种参数传递方式,既可以按参数名传递参数,不受位置的限制,又可以像 tuple 传递一样不受数量限制。这个我将在下次课中做介绍。

今天来说说最为灵活的一种参数传递方式:

func(**kargs)

上次说的 func(*args) 方式是把参数作为 tuple 传入函数内部。而 func(**kargs) 则是把参数以键值对字典的形式传入。

示例:

In [16]:
def printAll(**kargs): for k in kargs: print (k, ':', kargs[k]) printAll(a=1, b=2, c=3) printAll(x=4, y=5) 

a : 1 b : 2 c : 3 x : 4 y : 5 

输出:

a : 1

c : 3

b : 2

y : 5

x : 4

字典是无序的,所以在输出的时候,并不一定按照提供参数的顺序。同样在调用时,参数的顺序无所谓,只要对应合适的形参名就可以了。于是,采用这种参数传递的方法,可以不受参数数量、位置的限制。

当然,这还不够。Python 的函数调用方式非常灵活,前面所说的几种参数调用方式,可以混合在一起使用。看下面这个例子:

In [18]:
def func(x, y=5, *a, **b): print (x, y, a, b) func(1) func(1,2) func(1,2,3) func(1,2,3,4) func(x=1) func(x=1,y=1) func(x=1,y=1,a=1) func(x=1,y=1,a=1,b=1) func(1,y=1) func(1,2,3,4,a=1) func(1,2,3,4,k=1,t=2,o=3) 

1 5 () {} 1 2 () {} 1 2 (3,) {} 1 2 (3, 4) {} 1 5 () {} 1 1 () {} 1 1 () {'a': 1} 1 1 () {'a': 1, 'b': 1} 1 1 () {} 1 2 (3, 4) {'a': 1} 1 2 (3, 4) {'k': 1, 't': 2, 'o': 3} 

输出:

1 5 () {}

1 2 () {}

1 2 (3,) {}

1 2 (3, 4) {}

1 5 () {}

1 1 () {}

1 1 () {‘a’: 1}

1 1 () {‘a’: 1, ‘b’: 1}

1 1 () {}

1 2 (3, 4) {‘a’: 1}

1 2 (3, 4) {‘k’: 1, ‘t’: 2, ‘o’: 3}

在混合使用时,首先要注意函数的写法,必须遵守:

带有默认值的形参(arg=)须在无默认值的形参(arg)之后;

元组参数(*args)须在带有默认值的形参(arg=)之后;

字典参数(*kargs)须在元组参数(args)之后。

可以省略某种类型的参数,但仍需保证此顺序规则。

调用时也需要遵守:

指定参数名称的参数要在无指定参数名称的参数之后;

不可以重复传递,即按顺序提供某参数之后,又指定名称传递。

而在函数被调用时,参数的传递过程为:

1.按顺序把无指定参数的实参赋值给形参;

2.把指定参数名称(arg=v)的实参赋值给对应的形参;

3.将多余的无指定参数的实参打包成一个 tuple 传递给元组参数(*args);

4.将多余的指定参数名的实参打包成一个 dict 传递给字典参数(**kargs)。

是不是乍一看有点绕?没关系,赶紧打开你的编辑器,自行体会一下不同调用方式的用法。然后在未来的编程实践中慢慢熟悉吧。

lambda 表达式

Python 是一门简洁的语言,lambda 表达式则充分体现了 Python 这一特点。

lambda 表达可以被看做是一种匿名函数。它可以让你快速定义一个极度简单的单行函数。譬如这样一个实现三个数相加的函数:

In [19]:
def sum(a, b, c): return a + b + c print (sum(1, 2, 3)) print (sum(4, 5, 6)) 

6 15 

In [20]:
# 如果使用 lambda 表达式来实现: sum = lambda a, b, c: a + b + c print (sum(1, 2, 3)) print (sum(4, 5, 6)) 

6 15 

两种方法的结果是相同的。

lambda 表达式的语法格式:

lambda 参数列表: 表达式

定义 lambda 表达式时,参数列表周围没有括号,返回值前没有 return 关键字,也没有函数名称。

它的写法比 def 更加简洁。但是,它的主体只能是一个表达式,不可以是代码块,甚至不能是命令(print 不能用在 lambda 表达式中)。所以 lambda 表达式能表达的逻辑很有限。

lambda 表达式创建了一个函数对象,可以把这个对象赋值给一个变量进行调用,就像上面的例子中一样。

来看一个复杂一点的例子,把 lambda 表达式用在 def 函数定义中:

In [21]:
def fn(x): return lambda y: x + y a = fn(2) print (a(3)) 

5 

这里,fn 函数的返回值是一个 lambda 表达式,也就等于是一个函数对象。当以参数2来调用 fn 时,得到的结果就是:

lambda y: 2 + y

a = fn(2) 就相当于:

a = lambda y: 2 + y

所以 a(3) 的结果就是5。

lambda 表达式其实只是一种编码风格,这种写法更加 pythonic。这并不意味着你一定要使用它。事实上,任何可以使用 lambda 表达式的地方,都可以通过普通的 def 函数定义来替代。在一些需要重复使用同一函数的地方,def 可以避免重复定义函数。况且 def 函数更加通用,某些情况可以带来更好地代码可读性。

而对于像 filter、sort 这种需要内嵌函数的方法,lambda 表达式就会显得比较合适。这个我以后会再单独介绍。

当然对于初学者来说,了解 lambda 表达式还有一个重要作用就是,看懂别人写的代码。

变量的作用域

在写代码的时候,免不了要使用变量。但程序中的一个变量并不一定是在哪里都可以被使用,根据情况不同,会有不同的“有效范围”。看这样一段代码:

In [22]:
def func(x): print ('X in the beginning of func(x): ', x) x = 2 print ('X in the end of func(x): ', x) x = 50 func(x) print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 2 X after calling func(x): 50 

变量 x 在函数内部被重新赋值。但在调用了函数之后,x 的值仍然是50。为什么?

这就得说一下变量的“作用域”:

当函数内部定义了一个变量,无论是作为函数的形参,或是另外定义的变量,它都只在这个函数的内部起作用。函数外即使有和它名称相同的变量,也没有什么关联。这个函数体就是这个变量的作用域。像这样在函数内部定义的变量被称为“局部变量”。

要注意的是,作用域是从变量被定义的位置开始。像这样的写法是有问题的:

In [24]:
def func(): print (y) y = 2 print (y) func() 

--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-24-5af4faf299fd> in <module>()  7 print (y)  8 ----> 9 func() <ipython-input-24-5af4faf299fd> in func()  1 def func():  2 ----> 3 print (y)  4  5 y = 2 UnboundLocalError: local variable 'y' referenced before assignment

因为在 y = 2 之前,y 并不存在,调用 y 的值就会出错。

回到开始那个例子:

在函数 func 外部,定义的变量 x,赋值为 50,作为参数传给了函数 func。而在函数 func 内部,变量 x 是形参,它的作用域是整个函数体内部。它与外面的那个 x 没有关系。只不过它的初始值是由外面那个 x 传递过来的。

所以,虽然函数体内部的 x 被重新赋值为 2,也不会影响外面那个 x 的值。

不过有时候,我们希望能够在函数内部去改变一些变量的值,并且这些变量在函数外部同样被使用到。怎么办?

一种方法是,用 return 把改变后的变量值作为函数返回值传递出来,赋值给对应的变量。比如开始的那个例子,可以在函数结尾加上

return x

然后把调用改为

x = func(x)

还有一种方法,就是使用“全局变量”。

在 Python 的函数定义中,可以给变量名前加上 global 关键字,这样其作用域就不再局限在函数块中,而是全局的作用域。

In [25]:
#通过 global 改写开始的例子: def func(): global x print ('X in the beginning of func(x): ', x) x = 2 print ('X in the end of func(x): ', x) x = 50 func() print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 2 X after calling func(x): 2 

函数 func 不再提供参数调用。而是通过 global x 告诉程序:这个 x 是一个全局变量。于是函数中的 x 和外部的 x 就成为了同一个变量。这一次,当 x 在函数 func 内部被重新赋值后,外部的 x 也随之改变。

前面讲的局部变量和全局变量是 Python 中函数作用域最基本的情况。实际上,还有一些略复杂的情况,比如:

In [26]:
def func(): print ('X in the beginning of func(x): ', x) # x = 2 print ('X in the end of func(x): ', x) x = 50 func() print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 50 X after calling func(x): 50 

程序可以正常运行。虽然没有指明 global,函数内部还是使用到了外部定义的变量。然而一旦加上

x = 2

这句,程序就会报错。因为这时候,x 成为一个局部变量,它的作用域从定义处开始,到函数体末尾结束。

建议在写代码的过程中,显式地通过 global 来使用全局变量,避免在函数中直接使用外部变量。

map 函数

  • python2 和 python3 中 map返回值得类型不一样

来看两个问题:

  1. 假设有一个数列,如何把其中每一个元素都翻倍?

  2. 假设有两个数列,如何求和?

第一个问题,普通程序员大概会这么写:

In [27]:
lst_1 = [1,2,3,4,5,6] lst_2 = [] for item in lst_1: lst_2.append(item * 2) print (lst_2) 

[2, 4, 6, 8, 10, 12] 

In [29]:
#Python 程序员大概会这么写: lst_1 = [1,2,3,4,5,6] lst_2 = [i * 2 for i in lst_1] print (lst_2) 

[2, 4, 6, 8, 10, 12] 

这是我在《【Python 第66课】列表综合》里说到的方法,微信中回复 66 可以查看。

今天来说另一种 Python 程序员常用的写法 — map:

In [53]:
lst_1 = [1,2,3,4,5,6] def double_func(x): return x * 2 lst_2 = map(double_func, lst_1) print (list(lst_2)) 

[2, 4, 6, 8, 10, 12] 

map 是 Python 自带的内置函数,它的作用是把一个函数应用在一个(或多个)序列上,把列表中的每一项作为函数输入进行计算,再把计算的结果以列表的形式返回。

map 的第一个参数是一个函数,之后的参数是序列,可以是 list、tuple。

所以刚刚那个问题也可以写成:

In [52]:
lst_1 = (1,2,3,4,5,6) lst_2 = map(lambda x: x * 2, lst_1) print (list(lst_2)) 

[2, 4, 6, 8, 10, 12] 

这里原数据改为了元组,函数用 lambda 表达式替代。可参考《【Python 第70课】lambda 表达式》,微信中回复 70。

map 中的函数可以对多个序列进行操作。最开始提出的第二个问题,除了通常的 for 循环写法,如果用列表综合的方法比较难实现,但用 map 就比较方便:

In [51]:
lst_1 = [1,2,3,4,5,6] lst_2 = [1,3,5,7,9,11] lst_3 = map(lambda x, y: x + y, lst_1, lst_2) print (list(lst_3)) 

[2, 5, 8, 11, 14, 17] 

map 中的函数会从对应的列表中依次取出元素,作为参数使用,同样将结果以列表的形式返回。所以要注意的是,函数的参数个数要与 map 中提供的序列组数相同,即函数有几个参数,就得有几组数据。

对于每组数据中的元素个数,如果有某组数据少于其他组,map 会以 None 来补全这组参数。

此外,当 map 中的函数为 None 时,结果将会直接返回参数组成的列表。如果只有一组序列,会返回元素相同的列表,如果有多组数列,将会返回每组数列中,对应元素构成的元组所组成的列表。听上去很绕口是不是……代码试试看就明白了:

In [50]:
def f(x, y): return (x, y) lst_1 = [1,2,3,4,5,6] lst_2 = [1,3,5,7,9,11] lst_3 = list(map(f, lst_1, lst_2)) print (lst_3) 

[(1, 1), (2, 3), (3, 5), (4, 7), (5, 9), (6, 11)] 

In [40]:
def f(x, y): return (x, y) l1 = [ 0, 1, 2, 3, 4, 5, 6 ] l2 = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] list(map(f, l1, l2)) 

Out[40]:
[(0, 'Sun'), (1, 'Mon'), (2, 'Tue'), (3, 'Wed'), (4, 'Thu'), (5, 'Fri'), (6, 'Sat')]

reduce 函数

  • python3中需要 from functools import reduce

上次说了 Python 中一个比较有意思的内置函数 map,今天再来介绍另一个类似的函数:reduce

map 可以看作是把一个序列根据某种规则,映射到另一个序列。reduce 做的事情就是把一个序列根据某种规则,归纳为一个输出。

上栗子。以前我们给过一个习题,求1累加到100的和。寻常的做法大概是这样:

In [56]:
sum = 0 for i in range(1, 101): sum += i print (sum) 

5050

In [59]:
#如果用 reduce 函数,就可以写成: from functools import reduce lst = range(1, 101) def add(x, y): return x + y print (reduce(add, lst)) 

5050

解释一下:

reduce(function, iterable[, initializer])

第一个参数是作用在序列上的方法,第二个参数是被作用的序列,这与 map 一致。另外有一个可选参数,是初始值。

function 需要是一个接收2个参数,并有返回值的函数。它会从序列 iterable 里从左到右依次取出元素,进行计算。每次计算的结果,会作为下次计算的第一个参数。

提供初始值 initializer 时,它会作为第一次计算的第一个参数。否则,就先计算序列中的前两个值。

如果把刚才的 lst 换成 [1,2,3,4,5],那 reduce(add, lst) 就相当于 ((((1+2)+3)+4)+5)。

同样,可以用 lambda 函数:

reduce((lambda x, y: x + y), xrange(1, 101))

所以,在对于一个序列进行某种统计操作的时候,比如求和,或者诸如统计序列中元素的出现个数等(可尝试下如何用 reduce 做到),可以选择使用 reduce 来实现。相对可以使代码更简洁。

我觉得,写代码的可读性是很重要的事情,简洁易懂的代码,既容易让别人看懂,也便于自己以后的维护。同时,较少的代码也意味着比较高的开发效率和较少的出错可能。应尽量避免写混乱冗长的代码。当然,也不用为了一味追求代码的精简,总是想方设法把代码写在一行里。那就又走了另一个极端,同样也缺乏可读性。而至于是否使用类似 map、reduce 这样的方法,也是根据需要和个人习惯,我认为并没有一定的规则限制。

多线程

很多人使用 python 编写“爬虫”程序,抓取网上的数据。 举个例子,通过豆瓣的 API 抓取 30 部影片的信息:

Python3 多线程 http://www.runoob.com/python3/python3-multithreading.html

In [62]:
import urllib3, time import urllib time_start = time.time() data = [] for i in range(30): print ('request movie:', i) id = 1764796 + i http = urllib3.PoolManager() r = http.request('url','https://api.douban.com/v2/movie/subject/%d' % id) data.append(r) print (i, time.time() - time_start) print ('data:', len(data)) 

request movie: 0 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

0 1.0452296733856201 request movie: 1 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

1 1.4376976490020752 request movie: 2 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

2 2.036301851272583 request movie: 3 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

3 2.424480676651001 request movie: 4 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

4 3.1788370609283447 request movie: 5 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

5 3.515458583831787 request movie: 6 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

6 3.929321050643921 request movie: 7 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

7 4.4893105030059814 request movie: 8 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

8 4.876185178756714 request movie: 9 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

9 5.189667701721191 request movie: 10 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

10 5.549666404724121 request movie: 11 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

11 5.911073446273804 request movie: 12 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

12 6.593060493469238 request movie: 13 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

13 6.948549032211304 request movie: 14 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

14 7.268184423446655 request movie: 15 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

15 7.610193967819214 request movie: 16 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

16 8.079214572906494 request movie: 17 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

17 8.54995846748352 request movie: 18 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

18 8.875677585601807 request movie: 19 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

19 9.214396715164185 request movie: 20 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

20 9.786171436309814 request movie: 21 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

21 10.36324691772461 request movie: 22 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

22 10.938879013061523 request movie: 23 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

23 11.297513961791992 request movie: 24 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

24 11.634414911270142 request movie: 25 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

25 11.952378273010254 request movie: 26 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

26 12.278428792953491 request movie: 27 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

27 12.637410163879395 request movie: 28 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

28 12.983117580413818 request movie: 29 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

29 13.632150173187256 data: 30 

程序里用了 time.time() 来计算抓取花费的时间。运行一遍,大约需要十几秒(根据网络情况会有差异)。

如果我们想用这套代码抓取几万部电影,就算中间不出什么状况,估计也得花上好几个小时。

然而想一下,我们抓一部电影信息的过程是独立,并不依赖于其他电影的结果。因此没必要排好队一部一部地按顺序来。那么有没有什么办法可以同时抓取好几部电影?

答案就是:多线程。

来说一种简单的多线程方法:

python 里有一个 thread 模块,其中提供了一个函数:

start_new_thread(function, args[, kwargs])

function 是开发者定义的线程函数,

args 是传递给线程函数的参数,必须是tuple类型,

kwargs 是可选参数。

调用 start_new_thread 之后,会创建一个新的线程,来执行 function 函数。而代码原本的主线程将继续往下执行,不再等待 function 的返回。通常情况,线程在 function 执行完毕后结束。

改写一下前面的代码,将抓取的部分放在一个函数中:

In [65]:
import urllib3, time, _thread def get_content(i): id = 1764796 + i http = urllib3.PoolManager() r = http.request('url','https://api.douban.com/v2/movie/subject/%d' % id) data.append(r) print (i, time.time() - time_start) print ('data:', len(data)) time_start = time.time() data = [] for i in range(30): print ('request movie:', i) _thread.start_new_thread(get_content, (i,)) input('press ENTER to exit...\n') 

request movie: 0 request movie: 1 request movie: 2 request movie: 3 request movie: 4 request movie: 5 request movie: 6 request movie: 7 request movie: 8 request movie: 9 request movie: 10 request movie: 11 request movie: 12 request movie: 13 request movie: 14 request movie: 15 request movie: 16 request movie: 17 request movie: 18 request movie: 19 request movie: 20 request movie: 21 request movie: 22 request movie: 23 request movie: 24 request movie: 25 request movie: 26 request movie: 27 request movie: 28 request movie: 29 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

5 0.7017581462860107 data: 1 10 0.7559306621551514 data: 2 24 0.7629213333129883 data: 3 1 0.7649266719818115 data: 4 6 0.7935028076171875 data: 5 14 0.803107500076294 data: 6 23 0.8040831089019775 data: 7 15 0.8114683628082275 data: 8 253 0.8258225917816162 data: 10 0.826324462890625 data: 10 261328 0.8268251419067383 data: 13 0.8273270130157471 data: 13 0.8268251419067383 data: 13 811 0.845090389251709 data: 15 0.8446097373962402 data: 15 1718 16 0.883171558380127 data: 0.8815431594848633 data: 18 18 0.880507230758667 data: 18 21 0.9177229404449463 data: 19 2 0.9450147151947021 data: 20 4 0.9600613117218018 data: 21 0 0.9701051712036133 data: 22 20 0.9744563102722168 data: 23 27 0.9754600524902344 data: 24 79 1.0218162536621094 data: 26 1.0213446617126465 data: 26 19 1.0371334552764893 data: 27 12 1.0552606582641602 data: 28 29 1.0806910991668701 data: 29 22 1.1721751689910889 data: 30 press ENTER to exit... 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

Out[65]:
''

因为主线程不在等待函数返回结果,所以在代码最后,增加了 raw_input,避免程序提前退出。

从输出结果可以看出:

在程序刚开始运行时,已经发送所有请求

收到的请求并不是按发送顺序,先收到就先显示

总共用时两秒多

data 里同样记录了所有30条结果

所以,对于这种耗时长,但又独立的任务,使用多线程可以大大提高运行效率。但在代码层面,可能额外需要做一些处理,保证结果正确。如上例中,如果需要电影信息按 id 排列,就要另行排序。

多线程通常会用在网络收发数据、文件读写、用户交互等待之类的操作上,以避免程序阻塞,提升用户体验或提高执行效率。

多线程的实现方法不止这一种。另外多线程也会带来一些单线程程序中不会出现的问题。这里只是简单地开个头。

一个很弱智的猜数字小游戏

In [1]:
from random import randint

num = randint(1, 100)
print('guess what I think?')
answer = int(input())
while(answer!=num):
    if answer<num:
        print('too small?')
    elif answer>num:
        print('too big?')
    elif answer==num:
        break
    answer = int(input())
print('equal')

guess what I think?
50
too big?
25
too big?
10
too small?
15
too small?
17
too small?
19
equal

range 列表

In [2]:
sum = 0
for _ in range(1,101) :
    sum = sum + _
print(sum)

5050

print的简单用法

In [3]:
print("this is the\
 same line")

print('''
"What's your name?" I asked.
"I'm Han Meimei."
''')

num = 18
print ('My age is %d' % num)
print ('Price is %.2f' % 4.6765)

this is the same line

"What's your name?" I asked.
"I'm Han Meimei."

My age is 18
Price is 4.68

for嵌套

In [4]:
for i in range(0, 5):
    for j in range(0, i+1):
        print ('*',end=' ')
    print('\t')

* 	
* * 	
* * * 	
* * * * 	
* * * * * 	

字符串拼接 bool值

In [5]:
print ('%s is easy to %d' % ('Python',100))
bool(None)

Python is easy to 100

Out[5]:
False

函数定义

In [6]:
def sayHello(someone):
   print( someone + ' say hello world!')

sayHello('bzz')

def plus(num1, num2):
   print (num1+num2)

plus(1,5)

bzz say hello world!
6

函数实现弱智小游戏

In [7]:
def isEqual(num1, num2):
    if num1<num2:
        print ('too small')
        return False;
    elif num1>num2:
        print ('too big')
        return False;
    else :
        print ('bingo')
        return True

from random import randint

num = randint(1, 100)
print ('Guess what I think?')
bingo = False
while bingo == False:
    answer = int(input())
    bingo = isEqual(answer, num)

Guess what I think?
50
too small
80
too big
70
too big
65
too big
63
too big
55
too small
60
too big
58
too big
57
bingo

print(list(range(1,10))) 可以在python3shell下通过,但无法在jupyter notebook 中通过,目前无解

In [8]:
print(list(range(1,10)))

[1, 2, 3, 4, 5, 6, 7, 8, 9]

调用numpy 显示list

In [9]:
import numpy as np
a=np.arange(1,10)
print(a)

[1 2 3 4 5 6 7 8 9]

操作list

In [10]:
l = [365, 'everyday', 0.618, True]
print (l[1])
#修改list中的元素
l[0] = 123
print (l)
#向list中添加元素
l.append(1024)
print (l)
#删除list中的元素
del l[0]
print (l)

everyday
[123, 'everyday', 0.618, True]
[123, 'everyday', 0.618, True, 1024]
['everyday', 0.618, True, 1024]

点球游戏1

In [11]:
from random import choice
print ('Choose one side to shoot:')
print ('left, center, right')
you = input()
print ('You kicked ' + you)
direction = ['left', 'center', 'right']
com = choice(direction)
print ('Computer saved :' + com)
if you != com:
   print ('Goal!')
else:
   print ('Oops...')

Choose one side to shoot:
left, center, right
left
You kicked left
Computer saved :right
Goal!

list切片

  • list有两类常用操作:索引(index)和切片(slice)。
  • 上是索引,现使用切片
  • 切片操作符是在[]内提供一对可选数字,用 : 分割。冒号前的数表示切片的开始位置,冒号后的数字表示切片到哪里结束。同样,计数从0开始。 注意,开始位置包含在切片中,而结束位置不包括。

切片的语法表达式为:[start_index : end_index : step],其中: start_index表示起始索引end_index表示结束索引 step表示步长,步长不能为0,且默认值为1 切片操作是指按照步长,截取从起始索引到结束索引,但不包含结束索引(也就是结束索引减1)的所有元素。

python3支持切片操作的数据类型有list、tuple、string、unicode、range 切片返回的结果类型与原对象类型一致 切片不会改变原对象,而是重新生成了一个新的对象

In [12]:
l = ['a', 'b', 'c', 'd', 'e', 'f']
print(l[-1]) # "-" 表示倒数
print(l[-4])
print(l[0:4])

print(l[1:])
print(l[:3])
print(l[:])
print(l[1:-1])

f
c
['a', 'b', 'c', 'd']
['b', 'c', 'd', 'e', 'f']
['a', 'b', 'c']
['a', 'b', 'c', 'd', 'e', 'f']
['b', 'c', 'd', 'e']

点球游戏2

In [13]:
from random import choice

score_you = 0
score_com = 0
direction = ['left', 'center', 'right']

for i in range(5):
    print ('==== Round %d - You Kick! ====' % (i+1))
    print ('选一边射门')#Choose one side to shoot:
    print ('left, center, right')
    you = input()
    print ('You kicked ' + you)
    com = choice(direction)
    print ('Computer saved ' + com)
    if you != com:
        print ('Goal!')
        score_you += 1
    else:
        print ('Oops...')
        print ('Score: %d(you) - %d(com)\n' % (score_you, score_com))

    print ('==== Round %d - You Save! ====' % (i+1))
    print ('选一边守门:')
    print ('left, center, right')
    you = input()
    print ('You saved ' + you)
    com = choice(direction)
    print ('Computer kicked ' + com)
    if you == com:
        print ('Saved!')
    else:
        print ('Oops...')
        score_com += 1
    print ('Score: %d(you) - %d(com)\n' % (score_you, score_com))

==== Round 1 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 1 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 1(you) - 1(com)

==== Round 2 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved center
Goal!
==== Round 2 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked left
Saved!
Score: 2(you) - 1(com)

==== Round 3 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 3 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 3(you) - 2(com)

==== Round 4 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved left
Oops...
Score: 3(you) - 2(com)

==== Round 4 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked center
Oops...
Score: 3(you) - 3(com)

==== Round 5 - You Kick! ====
选一边射门
left, center, right
left
You kicked left
Computer saved right
Goal!
==== Round 5 - You Save! ====
选一边守门:
left, center, right
left
You saved left
Computer kicked left
Saved!
Score: 4(you) - 3(com)

字符串的分割

In [14]:
sentence = 'I am an Englist sentence'
print(sentence.split())

# 指定参数分割 
section = 'Hi! I am the one! Bye!'
print(section.split('!')) # ! 所有都被分割 空格也是

print('_a!a a .'.split('a'))

['I', 'am', 'an', 'Englist', 'sentence']
['Hi', ' I am the one', ' Bye', '']
['_', '!', ' ', ' .']

点球游戏 加上胜负判断

In [15]:
from random import choice score = [0, 0] direction = ['left', 'center', 'right'] def kick(): print ('==== You Kick! ====') print ('Choose one side to shoot:') print ('left, center, right') you = input() print ('You kicked ' + you) com = choice(direction) print ('Computer saved ' + com) if you != com: print ('Goal!') score[0] += 1 else: print ('Oops...') print ('Score: %d(you) - %d(com)\n' % (score[0], score[1])) print ('==== You Save! ====') print ('Choose one side to save:') print ('left, center, right') you = input() print ('You saved ' + you) com = choice(direction) print ('Computer kicked ' + com) if you == com: print ('Saved!') else: print ('Oops...') score[1] += 1 print ('Score: %d(you) - %d(com)\n' % (score[0], score[1])) for i in range(5): print ('==== Round %d ====' % (i+1)) kick() while(score[0] == score[1]): i += 1 print ('==== Round %d ====' % (i+1)) kick() if score[0] > score[1]: print( 'You Win!') else: print ('You Lose.') 

==== Round 1 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 0(you) - 0(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 0(you) - 1(com) ==== Round 2 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved right Goal! Score: 1(you) - 1(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 1(you) - 2(com) ==== Round 3 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 1(you) - 2(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 1(you) - 3(com) ==== Round 4 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved left Oops... Score: 1(you) - 3(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked left Saved! Score: 1(you) - 3(com) ==== Round 5 ==== ==== You Kick! ==== Choose one side to shoot: left, center, right left You kicked left Computer saved center Goal! Score: 2(you) - 3(com) ==== You Save! ==== Choose one side to save: left, center, right left You saved left Computer kicked right Oops... Score: 2(you) - 4(com) You Lose. 

连接list

  • join和昨天说的split正好相反:split是把一个字符串分割成很多字符串组成的list,而join则是把一个list中的所有字符串连接成一个字符串。
  • join的格式有些奇怪,它不是list的方法,而是字符串的方法。首先你需要有一个字符串作为list中所有元素的连接符,然后再调用这个连接符的join方法,join的参数是被连接的list:

In [16]:
s = ';' li = ['apple', 'pear', 'orange'] fruit = s.join(li) print (fruit) print(';'.join(['apple', 'pear', 'orange'])) print(''.join(['hello', 'world'])) # 无缝连接 

apple;pear;orange apple;pear;orange helloworld 

字符串的索引和切片

join方法也可以对字符串使用,作用就是用连接符把字符串中的每个字符重新连接成一个新字符串

In [17]:
word = 'helloworld' for c in word: print (c,end='.') print('\t') print('0.1.2.3.4.5.6.7.8.9.') print (word[0]) print (word[-2]) print (word[5:7]) print (word[:-5]) print (word[:]) newword = ','.join(word) print(newword) 

h.e.l.l.o.w.o.r.l.d. 0.1.2.3.4.5.6.7.8.9. h l wo hello helloworld h,e,l,l,o,w,o,r,l,d 

读文件

In [18]:
f = open('data.txt') data1 = f.read() f = open('data.txt') data2 = f.readline() data3 = f.readlines() print(data1) print('--------------') print(data2) print('--------------') print(data3) f.close #释放资源 

sfd affffffff ~?! -------------- sfd -------------- ['affffffff\n', '~?!'] 

Out[18]:
<function TextIOWrapper.close()>

In [21]:
f = open('output.txt')#, 'w' data1 = f.read() f = open('data.txt') data2 = f.readline() data3 = f.readlines() print(data1) print('--------------') print(data2) print('--------------') print(data3) f.close #释放资源 

50 50 50 -------------- sfd -------------- ['affffffff\n', '~?!'] 

Out[21]:
<function TextIOWrapper.close()>

处理文件中的数据

In [22]:
f = open('scores.txt') lines = f.readlines() f.close() print(lines) 

['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] 

In [23]:
import os # 调用os后, f = open('results.txt','w') , 有此文件则打开,否则新建 results = [] for line in lines: data = line.split() #print(data) sum = 0 for score in data[1:]: sum += int(score) result = '%s\t: %d\n' % (data[0], sum) results.append(result) f = open('result.txt','w') f.writelines(results) f.close() 

break

如果在循环条件仍然满足或序列没有遍历完的时候,想要强行跳出循环,就需要用到break语句。

In [24]:
for i in range(10): a = input() if a == 'EOF': break 

2154 EOF 

continue

break是彻底地跳出循环,而continue只是略过本次循环的余下内容,直接进入下一次循环

In [25]:
f = open('scores.txt') lines = f.readlines() f.close() print(lines) import os # 调用os后, f = open('results.txt','w') , 有此文件则打开,否则新建 results = [] for line in lines: data = line.split() #print(data) sum = 0 for score in data[1:]: point = int(score) if point < 60: continue sum += point result = '%s\t: %d\n' % (data[0], sum) results.append(result) f = open('result.txt','w') f.writelines(results) f.close() 

['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] 

异常处理

In [26]:
#print (int('0.5')) import os try: #f = open('non-exist.txt') f = open('scores.txt') lines = f.readlines() f.close() print("Open success!",end = ' ') print(lines) except: print( 'File not exists.') print( 'Done') 

Open success! ['刘备 23 35 44 47 51\n', '关羽 60 77 68\n', '张飞 97 99 89 91\n', '诸葛亮 100'] Done 

查天气 网络模块

In [7]:
import urllib3 http = urllib3.PoolManager() r = http.request('GET','http://www.baidu.com') print(r.status) print(r.data) 

200 b'<!DOCTYPE html><!--STATUS OK-->\r\n<html>\r\n<head>\r\n\t<meta http-equiv="content-type" content="text/html;charset=utf-8">\r\n\t<meta http-equiv="X-UA-Compatible" content="IE=Edge">\r\n\t<link rel="dns-prefetch" href="//s1.bdstatic.com"/>\r\n\t<link rel="dns-prefetch" href="//t1.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t2.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t3.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t10.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t11.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//t12.baidu.com"/>\r\n\t<link rel="dns-prefetch" href="//b1.bdstatic.com"/>\r\n\t<title>\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93</title>\r\n\t<link href="http://s1.bdstatic.com/r/www/cache/static/home/css/index.css" rel="stylesheet" type="text/css" />\r\n\t<!--[if lte IE 8]><style index="index" >#content{height:480px\\9}#m{top:260px\\9}</style><![endif]-->\r\n\t<!--[if IE 8]><style index="index" >#u1 a.mnav,#u1 a.mnav:visited{font-family:simsun}</style><![endif]-->\r\n\t<script>var hashMatch = document.location.href.match(/#+(.*wd=[^&].+)/);if (hashMatch && hashMatch[0] && hashMatch[1]) {document.location.replace("http://"+location.host+"/s?"+hashMatch[1]);}var ns_c = function(){};</script>\r\n\t<script>function h(obj){obj.style.behavior=\'url(#default#homepage)\';var a = obj.setHomePage(\'//www.baidu.com/\');}</script>\r\n\t<noscript><meta http-equiv="refresh" content="0; url=/baidu.html?from=noscript"/></noscript>\r\n\t<script>window._ASYNC_START=new Date().getTime();</script>\r\n</head>\r\n<body link="#0000cc"><div id="wrapper" style="display:none;"><div id="u"><a href="//www.baidu.com/gaoji/preferences.html" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'setting\',\'login\':\'0\'})">\xe6\x90\x9c\xe7\xb4\xa2\xe8\xae\xbe\xe7\xbd\xae</a>|<a id="btop" href="/" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'index\',\'login\':\'0\'})">\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5</a>|<a id="lb" href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" οnclick="return false;" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'login\'})">\xe7\x99\xbb\xe5\xbd\x95</a><a href="https://passport.baidu.com/v2/?reg&regType=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" οnmοusedοwn="return user_c({\'fm\':\'set\',\'tab\':\'reg\'})" target="_blank" class="reg">\xe6\xb3\xa8\xe5\x86\x8c</a></div><div id="head"><div class="s_nav"><a href="/" class="s_logo" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'logo\'})"><img src="//www.baidu.com/img/baidu_jgylogo3.gif" width="117" height="38" border="0" alt="\xe5\x88\xb0\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5" title="\xe5\x88\xb0\xe7\x99\xbe\xe5\xba\xa6\xe9\xa6\x96\xe9\xa1\xb5"></a><div class="s_tab" id="s_tab"><a href="http://news.baidu.com/ns?cl=2&rn=20&tn=news&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'news\'})">\xe6\x96\xb0\xe9\x97\xbb</a>&#12288;<b>\xe7\xbd\x91\xe9\xa1\xb5</b>&#12288;<a href="http://tieba.baidu.com/f?kw=&fr=wwwt" wdfield="kw" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'tieba\'})">\xe8\xb4\xb4\xe5\x90\xa7</a>&#12288;<a href="http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'zhidao\'})">\xe7\x9f\xa5\xe9\x81\x93</a>&#12288;<a href="http://music.baidu.com/search?fr=ps&key=" wdfield="key" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'music\'})">\xe9\x9f\xb3\xe4\xb9\x90</a>&#12288;<a href="http://image.baidu.com/i?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'pic\'})">\xe5\x9b\xbe\xe7\x89\x87</a>&#12288;<a href="http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&word=" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'video\'})">\xe8\xa7\x86\xe9\xa2\x91</a>&#12288;<a href="http://map.baidu.com/m?word=&fr=ps01000" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'map\'})">\xe5\x9c\xb0\xe5\x9b\xbe</a>&#12288;<a href="http://wenku.baidu.com/search?word=&lm=0&od=0" wdfield="word" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'wenku\'})">\xe6\x96\x87\xe5\xba\x93</a>&#12288;<a href="//www.baidu.com/more/" οnmοusedοwn="return c({\'fm\':\'tab\',\'tab\':\'more\'})">\xe6\x9b\xb4\xe5\xa4\x9a\xc2\xbb</a></div></div><form id="form" name="f" action="/s" class="fm" ><input type="hidden" name="ie" value="utf-8"><input type="hidden" name="f" value="8"><input type="hidden" name="rsv_bp" value="1"><span class="bg s_ipt_wr"><input name="wd" id="kw" class="s_ipt" value="" maxlength="100"></span><span class="bg s_btn_wr"><input type="submit" id="su" value="\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b" class="bg s_btn" οnmοusedοwn="this.className=\'bg s_btn s_btn_h\'" οnmοuseοut="this.className=\'bg s_btn\'"></span><span class="tools"><span id="mHolder"><div id="mCon"><span>\xe8\xbe\x93\xe5\x85\xa5\xe6\xb3\x95</span></div><ul id="mMenu"><li><a href="javascript:;" name="ime_hw">\xe6\x89\x8b\xe5\x86\x99</a></li><li><a href="javascript:;" name="ime_py">\xe6\x8b\xbc\xe9\x9f\xb3</a></li><li class="ln"></li><li><a href="javascript:;" name="ime_cl">\xe5\x85\xb3\xe9\x97\xad</a></li></ul></span><span class="shouji"><strong>\xe6\x8e\xa8\xe8\x8d\x90&nbsp;:&nbsp;</strong><a href="http://w.x.baidu.com/go/mini/8/10000020" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'bdbrowser\'})">\xe7\x99\xbe\xe5\xba\xa6\xe6\xb5\x8f\xe8\xa7\x88\xe5\x99\xa8\xef\xbc\x8c\xe6\x89\x93\xe5\xbc\x80\xe7\xbd\x91\xe9\xa1\xb5\xe5\xbf\xab2\xe7\xa7\x92\xef\xbc\x81</a></span></span></form></div><div id="content"><div id="u1"><a href="http://news.baidu.com" name="tj_trnews" class="mnav">\xe6\x96\xb0\xe9\x97\xbb</a><a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a><a href="http://map.baidu.com" name="tj_trmap" class="mnav">\xe5\x9c\xb0\xe5\x9b\xbe</a><a href="http://v.baidu.com" name="tj_trvideo" class="mnav">\xe8\xa7\x86\xe9\xa2\x91</a><a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">\xe8\xb4\xb4\xe5\x90\xa7</a><a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F" name="tj_login" id="lb" οnclick="return false;">\xe7\x99\xbb\xe5\xbd\x95</a><a href="//www.baidu.com/gaoji/preferences.html" name="tj_settingicon" id="pf">\xe8\xae\xbe\xe7\xbd\xae</a><a href="//www.baidu.com/more/" name="tj_briicon" id="bri">\xe6\x9b\xb4\xe5\xa4\x9a\xe4\xba\xa7\xe5\x93\x81</a></div><div id="m"><p id="lg"><img src="//www.baidu.com/img/bd_logo.png" width="270" height="129"></p><p id="nv"><a href="http://news.baidu.com">\xe6\x96\xb0&nbsp;\xe9\x97\xbb</a>\xe3\x80\x80<b>\xe7\xbd\x91&nbsp;\xe9\xa1\xb5</b>\xe3\x80\x80<a href="http://tieba.baidu.com">\xe8\xb4\xb4&nbsp;\xe5\x90\xa7</a>\xe3\x80\x80<a href="http://zhidao.baidu.com">\xe7\x9f\xa5&nbsp;\xe9\x81\x93</a>\xe3\x80\x80<a href="http://music.baidu.com">\xe9\x9f\xb3&nbsp;\xe4\xb9\x90</a>\xe3\x80\x80<a href="http://image.baidu.com">\xe5\x9b\xbe&nbsp;\xe7\x89\x87</a>\xe3\x80\x80<a href="http://v.baidu.com">\xe8\xa7\x86&nbsp;\xe9\xa2\x91</a>\xe3\x80\x80<a href="http://map.baidu.com">\xe5\x9c\xb0&nbsp;\xe5\x9b\xbe</a></p><div id="fm"><form id="form1" name="f1" action="/s" class="fm"><span class="bg s_ipt_wr"><input type="text" name="wd" id="kw1" maxlength="100" class="s_ipt"></span><input type="hidden" name="rsv_bp" value="0"><input type=hidden name=ch value=""><input type=hidden name=tn value="baidu"><input type=hidden name=bar value=""><input type="hidden" name="rsv_spt" value="3"><input type="hidden" name="ie" value="utf-8"><span class="bg s_btn_wr"><input type="submit" value="\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b" id="su1" class="bg s_btn" οnmοusedοwn="this.className=\'bg s_btn s_btn_h\'" οnmοuseοut="this.className=\'bg s_btn\'"></span></form><span class="tools"><span id="mHolder1"><div id="mCon1"><span>\xe8\xbe\x93\xe5\x85\xa5\xe6\xb3\x95</span></div></span></span><ul id="mMenu1"><div class="mMenu1-tip-arrow"><em></em><ins></ins></div><li><a href="javascript:;" name="ime_hw">\xe6\x89\x8b\xe5\x86\x99</a></li><li><a href="javascript:;" name="ime_py">\xe6\x8b\xbc\xe9\x9f\xb3</a></li><li class="ln"></li><li><a href="javascript:;" name="ime_cl">\xe5\x85\xb3\xe9\x97\xad</a></li></ul></div><p id="lk"><a href="http://baike.baidu.com">\xe7\x99\xbe\xe7\xa7\x91</a>\xe3\x80\x80<a href="http://wenku.baidu.com">\xe6\x96\x87\xe5\xba\x93</a>\xe3\x80\x80<a href="http://www.hao123.com">hao123</a><span>&nbsp;|&nbsp;<a href="//www.baidu.com/more/">\xe6\x9b\xb4\xe5\xa4\x9a&gt;&gt;</a></span></p><p id="lm"></p></div></div><div id="ftCon"><div id="ftConw"><p id="lh"><a id="seth" onClick="h(this)" href="/" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'homepage\',\'pos\':0})">\xe6\x8a\x8a\xe7\x99\xbe\xe5\xba\xa6\xe8\xae\xbe\xe4\xb8\xba\xe4\xb8\xbb\xe9\xa1\xb5</a><a id="setf" href="//www.baidu.com/cache/sethelp/index.html" οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'favorites\',\'pos\':0})" target="_blank">\xe6\x8a\x8a\xe7\x99\xbe\xe5\xba\xa6\xe8\xae\xbe\xe4\xb8\xba\xe4\xb8\xbb\xe9\xa1\xb5</a><a οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'tj_about\'})" href="http://home.baidu.com">\xe5\x85\xb3\xe4\xba\x8e\xe7\x99\xbe\xe5\xba\xa6</a><a οnmοusedοwn="return ns_c({\'fm\':\'behs\',\'tab\':\'tj_about_en\'})" href="http://ir.baidu.com">About Baidu</a></p><p id="cp">&copy;2018&nbsp;Baidu&nbsp;<a href="/duty/" name="tj_duty">\xe4\xbd\xbf\xe7\x94\xa8\xe7\x99\xbe\xe5\xba\xa6\xe5\x89\x8d\xe5\xbf\x85\xe8\xaf\xbb</a>&nbsp;\xe4\xba\xacICP\xe8\xaf\x81030173\xe5\x8f\xb7&nbsp;<img src="http://s1.bdstatic.com/r/www/cache/static/global/img/gs_237f015b.gif"></p></div></div><div id="wrapper_wrapper"></div></div><div class="c-tips-container" id="c-tips-container"></div>\r\n<script>window.__async_strategy=2;</script>\r\n<script>var bds={se:{},su:{urdata:[],urSendClick:function(){}},util:{},use:{},comm : {domain:"http://www.baidu.com",ubsurl : "http://sclick.baidu.com/w.gif",tn:"baidu",queryEnc:"",queryId:"",inter:"",templateName:"baidu",sugHost : "http://suggestion.baidu.com/su",query : "",qid : "",cid : "",sid : "",indexSid : "",stoken : "",serverTime : "",user : "",username : "",loginAction : [],useFavo : "",pinyin : "",favoOn : "",curResultNum:"",rightResultExist:false,protectNum:0,zxlNum:0,pageNum:1,pageSize:10,newindex:0,async:1,maxPreloadThread:5,maxPreloadTimes:10,preloadMouseMoveDistance:5,switchAddMask:false,isDebug:false,ishome : 1},_base64:{domain : "http://b1.bdstatic.com/",b64Exp : -1,pdc : 0}};var name,navigate,al_arr=[];var selfOpen = window.open;eval("var open = selfOpen;");var isIE=navigator.userAgent.indexOf("MSIE")!=-1&&!window.opera;var E = bds.ecom= {};bds.se.mon = {\'loadedItems\':[],\'load\':function(){},\'srvt\':-1};try {bds.se.mon.srvt = parseInt(document.cookie.match(new RegExp("(^| )BDSVRTM=([^;]*)(;|$)"))[2]);document.cookie="BDSVRTM=;expires=Sat, 01 Jan 2000 00:00:00 GMT"; }catch(e){}</script>\r\n<script>if(!location.hash.match(/[^a-zA-Z0-9]wd=/)){document.getElementById("ftCon").style.display=\'block\';document.getElementById("u1").style.display=\'block\';document.getElementById("content").style.display=\'block\';document.getElementById("wrapper").style.display=\'block\';setTimeout(function(){try{document.getElementById("kw1").focus();document.getElementById("kw1").parentNode.className += \' iptfocus\';}catch(e){}},0);}</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/jquery/jquery-1.10.2.min_f2fb5194.js"></script>\r\n<script>(function(){var index_content = $(\'#content\');var index_foot= $(\'#ftCon\');var index_css= $(\'head [index]\');var index_u= $(\'#u1\');var result_u= $(\'#u\');var wrapper=$("#wrapper");window.index_on=function(){index_css.insertAfter("meta:eq(0)");result_common_css.remove();result_aladdin_css.remove();result_sug_css.remove();index_content.show();index_foot.show();index_u.show();result_u.hide();wrapper.show();if(bds.su&&bds.su.U&&bds.su.U.homeInit){bds.su.U.homeInit();}setTimeout(function(){try{$(\'#kw1\').get(0).focus();window.sugIndex.start();}catch(e){}},0);if(typeof initIndex==\'function\'){initIndex();}};window.index_off=function(){index_css.remove();index_content.hide();index_foot.hide();index_u.hide();result_u.show();result_aladdin_css.insertAfter("meta:eq(0)");result_common_css.insertAfter("meta:eq(0)");result_sug_css.insertAfter("meta:eq(0)");wrapper.show();};})();</script>\r\n<script>window.__switch_add_mask=1;</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/global/js/instant_search_newi_redirect1_20bf4036.js"></script>\r\n<script>initPreload();$("#u,#u1").delegate("#lb",\'click\',function(){try{bds.se.login.open();}catch(e){}});if(navigator.cookieEnabled){document.cookie="NOJS=;expires=Sat, 01 Jan 2000 00:00:00 GMT";}</script>\r\n<script>$(function(){for(i=0;i<3;i++){u($($(\'.s_ipt_wr\')[i]),$($(\'.s_ipt\')[i]),$($(\'.s_btn_wr\')[i]),$($(\'.s_btn\')[i]));}function u(iptwr,ipt,btnwr,btn){if(iptwr && ipt){iptwr.on(\'mouseover\',function(){iptwr.addClass(\'ipthover\');}).on(\'mouseout\',function(){iptwr.removeClass(\'ipthover\');}).on(\'click\',function(){ipt.focus();});ipt.on(\'focus\',function(){iptwr.addClass(\'iptfocus\');}).on(\'blur\',function(){iptwr.removeClass(\'iptfocus\');}).on(\'render\',function(e){var $s = iptwr.parent().find(\'.bdsug\');var l = $s.find(\'li\').length;if(l>=5){$s.addClass(\'bdsugbg\');}else{$s.removeClass(\'bdsugbg\');}});}if(btnwr && btn){btnwr.on(\'mouseover\',function(){btn.addClass(\'btnhover\');}).on(\'mouseout\',function(){btn.removeClass(\'btnhover\');});}}});</script>\r\n<script type="text/javascript" src="http://s1.bdstatic.com/r/www/cache/static/home/js/bri_7f1fa703.js"></script>\r\n<script>(function(){var _init=false;window.initIndex=function(){if(_init){return;}_init=true;var w=window,d=document,n=navigator,k=d.f1.wd,a=d.getElementById("nv").getElementsByTagName("a"),isIE=n.userAgent.indexOf("MSIE")!=-1&&!window.opera;(function(){if(/q=([^&]+)/.test(location.search)){k.value=decodeURIComponent(RegExp["\\x241"])}})();(function(){var u = G("u1").getElementsByTagName("a"), nv = G("nv").getElementsByTagName("a"), lk = G("lk").getElementsByTagName("a"), un = "";var tj_nv = ["news","tieba","zhidao","mp3","img","video","map"];var tj_lk = ["baike","wenku","hao123","more"];un = bds.comm.user == "" ? "" : bds.comm.user;function _addTJ(obj){addEV(obj, "mousedown", function(e){var e = e || window.event;var target = e.target || e.srcElement;if(target.name){ns_c({\'fm\':\'behs\',\'tab\':target.name,\'un\':encodeURIComponent(un)});}});}for(var i = 0; i < u.length; i++){_addTJ(u[i]);}for(var i = 0; i < nv.length; i++){nv[i].name = \'tj_\' + tj_nv[i];}for(var i = 0; i < lk.length; i++){lk[i].name = \'tj_\' + tj_lk[i];}})();(function() {var links = {\'tj_news\': [\'word\', \'http://news.baidu.com/ns?tn=news&cl=2&rn=20&ct=1&ie=utf-8\'],\'tj_tieba\': [\'kw\', \'http://tieba.baidu.com/f?ie=utf-8\'],\'tj_zhidao\': [\'word\', \'http://zhidao.baidu.com/search?pn=0&rn=10&lm=0\'],\'tj_mp3\': [\'key\', \'http://music.baidu.com/search?fr=ps&ie=utf-8\'],\'tj_img\': [\'word\', \'http://image.baidu.com/i?ct=201326592&cl=2&nc=1&lm=-1&st=-1&tn=baiduimage&istype=2&fm=&pv=&z=0&ie=utf-8\'],\'tj_video\': [\'word\', \'http://video.baidu.com/v?ct=301989888&s=25&ie=utf-8\'],\'tj_map\': [\'wd\', \'http://map.baidu.com/?newmap=1&ie=utf-8&s=s\'],\'tj_baike\': [\'word\', \'http://baike.baidu.com/search/word?pic=1&sug=1&enc=utf8\'],\'tj_wenku\': [\'word\', \'http://wenku.baidu.com/search?ie=utf-8\']};var domArr = [G(\'nv\'), G(\'lk\'),G(\'cp\')],kw = G(\'kw1\');for (var i = 0, l = domArr.length; i < l; i++) {domArr[i].onmousedown = function(e) {e = e || window.event;var target = e.target || e.srcElement,name = target.getAttribute(\'name\'),items = links[name],reg = new RegExp(\'^\\\\s+|\\\\s+\\x24\'),key = kw.value.replace(reg, \'\');if (items) {if (key.length > 0) {var wd = items[0], url = items[1],url = url + ( name === \'tj_map\' ? encodeURIComponent(\'&\' + wd + \'=\' + key) : ( ( url.indexOf(\'?\') > 0 ? \'&\' : \'?\' ) + wd + \'=\' + encodeURIComponent(key) ) );target.href = url;} else {target.href = target.href.match(new RegExp(\'^http:\\/\\/.+\\.baidu\\.com\'))[0];}}name && ns_c({\'fm\': \'behs\',\'tab\': name,\'query\': encodeURIComponent(key),\'un\': encodeURIComponent(bds.comm.user || \'\') });};}})();};if(window.pageState==0){initIndex();}})();document.cookie = \'IS_STATIC=1;expires=\' + new Date(new Date().getTime() + 10*60*1000).toGMTString();</script>\r\n</body></html>\r\n' 

面向对象

In [4]:
s = 'how are you' #s被赋值后就是一个字符串类型的对象 l = s.split() #split是字符串的方法,这个方法返回一个list类型的对象 #l是一个list类型的对象 #通过dir()方法可以查看一个类/变量的所有属性: print(dir(s)) print('---------') print(dir(list)) 

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] --------- ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 

  • 关键字class加上类名用来创建一个类。之后缩进的代码块是这个类的内部。在这里,我们用pass语句,表示一个空的代码块

In [6]:
class MyClass: print('bzz') pass mc = MyClass() print (mc) #mc是__main__模块中MyClass来的一个实例(instance) 

bzz <__main__.MyClass object at 0x0000025C1069EF98> 

In [12]:
# 给这个类加上一些域: # 给MyClass类增加了一个类变量name,并把它的值设为'Sam'。然后又增加了一个类方法sayHi # 调用类变量的方法是“对象.变量名”。你可以得到它的值,也可以改变它的值。 # 类方法和我们之前定义的函数区别在于,第一个参数必须为self。 # 而在调用类方法的时候,通过“对象.方法名()”格式进行调用, # 而不需要额外提供self这个参数的值。self在类方法中的值,就是你调用的这个对象本身 class MyClass: name = 'Sam' def sayHi(self): print ('Hello %s' % self.name) mc = MyClass() print (mc.name) MyClass.name = 'Mike' print(MyClass().name) mc.name = 'Lily' mc.sayHi() 

Sam Mike Hello Lily 

  • 假设我们有一辆汽车,我们知道它的速度(60km/h),以及A、B两地的距离(100km)。要算出开着这辆车从A地到B地花费的时间。

In [13]:
#面向过程的方法: speed = 60.0 distance = 100.0 time = distance / speed print (time) #面向对象的方法: class Car: speed = 0 def drive(self, distance): time = distance / self.speed print (time) car = Car() car.speed = 60.0 car.drive(100.0) 

1.6666666666666667 1.6666666666666667 

  • 如果我们让题目再稍稍复杂一点。假设我们又有了一辆更好的跑车,它的速度是150km/h,然后我们除了想从A到B,还要从B到C(距离200km)。要求分别知道这两种车在这两段路上需要多少时间。

In [16]:
#面向过程的方法: speed1 = 60.0 distance1 = 100.0 time1 = distance1 / speed1 print (time1) distance2 = 200.0 time2 = distance2 / speed1 print (time2) speed2 = 150.0 time3 = distance1 / speed2 print (time3) time4 = distance2 / speed2 print (time4) print('--------------') #面向对象的方法: class Car: speed = 0 def drive(self, distance): time = distance / self.speed print (time) car1 = Car() car1.speed = 60.0 car1.drive(100.0) car1.drive(200.0) car2 = Car() car2.speed = 150.0 car2.drive(100.0) car2.drive(200.0) 

1.6666666666666667 3.3333333333333335 0.6666666666666666 1.3333333333333333 -------------- 1.6666666666666667 3.3333333333333335 0.6666666666666666 1.3333333333333333 

仍然是从A地到B地,这次除了有汽车,我们还有了一辆自行车! 自行车和汽车有着相同的属性:速度(speed)。还有一个相同的方法(drive),来输出行驶/骑行一段距离所花的时间。但这次我们要给汽车增加一个属性:每公里油耗(fuel)。而在汽车行驶一段距离的方法中,除了要输出所花的时间外,还要输出所需的油量。

面向过程的方法,你可能需要写两个函数,然后把数据作为参数传递进去,在调用的时候要搞清应该使用哪个函数和哪些数据。有了面向对象,你可以把相关的数据和方法封装在一起,并且可以把不同类中的相同功能整合起来。这就需要用到面向对象中的另一个重要概念:继承。

我们要使用的方法是,创建一个叫做Vehicle的类,表示某种车,它包含了汽车和自行车所共有的东西:速度,行驶的方法。然后让Car类和Bike类都继承这个Vehicle类,即作为它的子类。在每个子类中,可以分别添加各自独有的属性。

In [20]:
# Vehicle类被称为基本类或超类,Car类和Bike类被成为导出类或子类 class Vehicle: def __init__(self,speed): self.speed = speed def drive(self,distance): print('need %f hour(s)'%(distance/self.speed)) class Bike(Vehicle): pass class Car(Vehicle): def __init__(self,speed,fuel): Vehicle.__init__(self,speed) self.fuel = fuel def drive(self,distance): Vehicle.drive(self,distance) print('need %f fuels'%(distance*self.fuel)) b = Bike(15.0) c = Car(80.0,0.012) b.drive(100) c.drive(100) ''' 解释一下代码: __init__函数会在类被创建的时候自动调用,用来初始化类。它的参数,要在创建类的时候提供。 于是我们通过提供一个数值来初始化speed的值。 注意:__init__是python的内置方法,类似的函数名前后是两个下英文划线,如果写错了, 则不会起到原本应有的作用。 class定义后面的括号里表示这个类继承于哪个类。 Bike(Vehicle)就是说Bike是继承自Vehicle中的子类。Vehicle中的属性和方法,Bike都会有。 因为Bike不需要有额外的功能,所以用pass在类中保留空块,什么都不用写。 Car类中,我们又重新定义了__init__和drive函数,这样会覆盖掉它继承自Vehicle的同名函数。 但我们依然可以通过“Vehicle.函数名”来调用它的超类方法。 以此来获得它作为Vehicle所具有的功能。注意,因为是通过类名调用方法, 而不是像之前一样通过对象来调用,所以这里必须提供self的参数值。 在调用超类的方法之后,我们又给Car增加了一个fuel属性,并且在drive中多输出一行信息。 ''' 

need 6.666667 hour(s) need 1.250000 hour(s) need 1.200000 fuels 

Out[20]:
'\n解释一下代码:\n\n__init__函数会在类被创建的时候自动调用,用来初始化类。它的参数,要在创建类的时候提供。\n于是我们通过提供一个数值来初始化speed的值。\n\n注意:__init__是python的内置方法,类似的函数名前后是两个下英文划线,如果写错了,\n则不会起到原本应有的作用。\n\nclass定义后面的括号里表示这个类继承于哪个类。\nBike(Vehicle)就是说Bike是继承自Vehicle中的子类。Vehicle中的属性和方法,Bike都会有。\n因为Bike不需要有额外的功能,所以用pass在类中保留空块,什么都不用写。\n\nCar类中,我们又重新定义了__init__和drive函数,这样会覆盖掉它继承自Vehicle的同名函数。\n但我们依然可以通过“Vehicle.函数名”来调用它的超类方法。\n以此来获得它作为Vehicle所具有的功能。注意,因为是通过类名调用方法,\n而不是像之前一样通过对象来调用,所以这里必须提供self的参数值。\n在调用超类的方法之后,我们又给Car增加了一个fuel属性,并且在drive中多输出一行信息。\n\n\n'

and-or

In [21]:
a = "heaven" b = "hell" c = True and a or b print (c) d = False and a or b print (d) 

heaven hell 

结果很奇怪是不是?

表达式从左往右运算,1和”heaven”做and的结果是”heaven”,再与”hell”做or的结果是”heaven”;0和”heaven”做and的结果是0,再与”hell”做or的结果是”hell”。

抛开绕人的and和or的逻辑,你只需记住,在一个bool and a or b语句中,当bool条件为真时,结果是a;当bool条件为假时,结果是b。

有学过c/c++的同学应该会发现,这和bool?a:b表达式很像。

有了它,原本需要一个if-else语句表述的逻辑:

if a > 0:

print “big”

else:

print “small”

就可以直接写成:

print (a > 0) and “big” or “small”

然而不幸的是,如果直接这么用,有一天你会踩到坑的。和c语言中的?:表达式不同,这里的and or语句是利用了python中的逻辑运算实现的。当a本身是个假值(如0,””)时,结果就不会像你期望的那样。 比如: a = “”

b = “hell”

c = True and a or b

print c

得到的结果不是””而是”hell”。因为””和”hell”做or的结果是”hell”。

所以,and-or真正的技巧在于,确保a的值不会为假。最常用的方式是使 a 成为 [a] 、 b 成为 [b],然后使用返回值列表的第一个元素:

a = “”

b = “hell”

c = (True and [a] or [b])[0]

print c

由于[a]是一个非空列表,所以它决不会为假。即使a是0或者”或者其它假值,列表[a]也为真,因为它有一个元素。

在两个常量值进行选择时,and-or会让你的代码更简单。但如果你觉得这个技巧带来的副作用已经让你头大了,没关系,用if-else可以做相同的事情。不过在python的某些情况下,你可能没法使用if语句,比如lambda函数中,这时候你可能就需要and-or的帮助了。

什么是lambda函数?呵呵,这是python的高阶玩法,暂且按住不表,以后有机会再说。

In [25]:
a = "" b = "hell" c = (True and [a] or [b])[0] print (c) 

 

元组

In [31]:
#上一次pygame的课中有这样一行代码: #x, y = pygame.mouse.get_pos() # 元组(tuple)也是一种序列,和我们用了很多次的list类似, # 只是元组中的元素在创建之后就不能被修改。 # 如: postion = (1, 2) geeks = ('Sheldon', 'Leonard', 'Rajesh', 'Howard') # 都是元组的实例。它有和list同样的索引、切片、遍历等操作(参见25~27课): print (postion[0]) print('------------') for _ in geeks: print (_) print('------------') print (geeks[1:3]) #其实我们之前一直在用元组,就是在print语句中: print('------------') print ('%s is %d years old' % ('Mike', 23)) #('Mike', 23)就是一个元组。这是元组最常见的用处。 #再来看一下元组作为函数返回值的例子: def get_pos(n): return (n/2, n*2) #得到这个函数的返回值有两种形式,一种是根据返回值元组中元素的个数提供变量: x, y = get_pos(50) print (x) print (y) print('------------') #这就是我们在开头那句代码中使用的方式。 #还有一种方法是用一个变量记录返回的元组: pos = get_pos(50) print (pos[0]) print (pos[1]) 

1 ------------ Sheldon Leonard Rajesh Howard ------------ ('Leonard', 'Rajesh') ------------ Mike is 23 years old 25.0 100 ------------ 25.0 100 

数学运算

In [40]:
import math print(math.pi) print(math.e) print(math.ceil(5.4)) print(math.floor(5.4)) print(math.pow(3,2)) print(math.log(4)) print(math.log(100,10)) print(math.sqrt(9)) print(math.fabs(-34)) #math.sin .cos .tan .asin .acos .atan 弧度单位 #math.degrees(x) 弧度转角度 #math.radians(x) 角度转弧度 

3.141592653589793 2.718281828459045 6 5 9.0 1.3862943611198906 2.0 3.0 34.0 

正则表达式

什么是正则表达式?在回答这个问题之前,先来看看为什么要有正则表达式。

在编程处理文本的过程中,经常会需要按照某种规则去查找一些特定的字符串。比如知道一个网页上的图片都是叫做’image/8554278135.jpg’之类的名字,只是那串数字不一样;又或者在一堆人员电子档案中,你要把他们的电话号码全部找出来,整理成通讯录。诸如此类工作,如果手工去做,当量大的时候那简直就是悲剧。但你知道这些字符信息有一定的规律,可不可以利用这些规律,让程序自动来做这些无聊的事情?答案是肯定的。这时候,你就需要一种描述这些规律的方法,正则表达式就是干这事的。

正则表达式就是记录文本规则的代码。

所以正则表达式并不是python中特有的功能,它是一种通用的方法。python中的正则表达式库,所做的事情是利用正则表达式来搜索文本。要使用它,你必须会自己用正则表达式来描述文本规则。之前多次有同学表示查找文本的事情经常会遇上,希望能介绍一下正则表达式。既然如此,我们就从正则表达式的基本规则开始说起。

1.

首先说一种最简单的正则表达式,它没有特殊的符号,只有基本的字母或数字。它满足的匹配规则就是完全匹配。例如:有个正则表达式是“hi”,那么它就可以匹配出文本中所有含有hi的字符。

来看如下的一段文字:

Hi, I am Shirley Hilton. I am his wife.

如果我们用“hi”这个正则表达式去匹配这段文字,将会得到两个结果。因为是完全匹配,所以每个结果都是“hi”。这两个“hi”分别来自“Shirley”和“his”。默认情况下正则表达式是严格区分大小写的,所以“Hi”和“Hilton”中的“Hi”被忽略了。

为了验证正则表达式匹配的结果,你可以用以下这段代码做实验:

In [6]:
import re text = "Hi, I am Shirley Hilton. I am his wife.hi" m = re.findall(r"[Hh]i", text) if m: print (m) else: print ('not match') 

['Hi', 'hi', 'Hi', 'hi', 'hi'] 

暂时先不解释这其中代码的具体含义,你只要去更改text和findall中的字符串,就可以用它来检测正则表达式的实际效果。

2.

如果我们只想找到“hi”这个单词,而不把包含它的单词也算在内,那就可以使用“\bhi\b”这个正则表达式。在以前的字符串处理中,我们已经见过类似“\n”这种特殊字符。在正则表达式中,这种字符更多,以后足以让你眼花缭乱。

“\b”在正则表达式中表示单词的开头或结尾,空格、标点、换行都算是单词的分割。而“\b”自身又不会匹配任何字符,它代表的只是一个位置。所以单词前后的空格标点之类不会出现在结果里。

在前面那个例子里,“\bhi\b”匹配不到任何结果。但“\bhi”的话就可以匹配到1个“hi”,出自“his”。用这种方法,你可以找出一段话中所有单词“Hi”,想一下要怎么写。

3.

最后再说一下[]这个符号。在正则表达式中,[]表示满足括号中任一字符。比如“[hi]”,它就不是匹配“hi”了,而是匹配“h”或者“i”。

在前面例子中,如果把正则表达式改为“[Hh]i”,就可以既匹配“Hi”,又匹配“hi”了。

1.r”hi”

这里字符串前面加了r,是raw的意思,它表示对字符串不进行转义。为什么要加这个?你可以试试print “\bhi”和r”\bhi”的区别。

print “\bhi”

hi

print r”\bhi”

\bhi

可以看到,不加r的话,\b就没有了。因为python的字符串碰到“\”就会转义它后面的字符。如果你想在字符串里打“\”,则必须要打“\”。

print “\bhi”

\bhi

这样的话,我们的正则表达式里就会多出很多“\”,让本来就已经复杂的字符串混乱得像五仁月饼一般。但加上了“r”,就表示不要去转义字符串中的任何字符,保持它的原样。

2.re.findall(r”hi”, text)

re是python里的正则表达式模块。findall是其中一个方法,用来按照提供的正则表达式,去匹配文本中的所有符合条件的字符串。返回结果是一个包含所有匹配的list。

3.今天主要说两个符号“.”和“*”,顺带说下“\S”和“?”。

“.”在正则表达式中表示除换行符以外的任意字符。在上节课提供的那段例子文本中:

Hi, I am Shirley Hilton. I am his wife.

如果我们用“i.”去匹配,就会得到

[‘i,’, ‘ir’, ‘il’, ‘is’, ‘if’]

你若是暴力一点,也可以直接用“.”去匹配,看看会得到什么。

与“.”类似的一个符号是“\S”,它表示的是不是空白符的任意字符。注意是大写字符S。

4.在很多搜索中,会用“?”表示任意一个字符, 表示任意数量连续字符,这种被称为通配符。但在正则表达式中,任意字符是用 “ . ” 表示,而 则不是表示字符,而是表示数量:它表示前面的字符可以重复任意多次(包括0次),只要满足这样的条件,都会被表达式匹配上。

结合前面的“.”,用“I.e”去匹配,想一下会得到什么结果?

[‘I am Shirley Hilton. I am his wife’]

是不是跟你想的有些不一样?也许你会以为是

[‘I am Shirle’, ‘I am his wife’]

这是因为“”在匹配时,会匹配尽可能长的结果。如果你想让他匹配到最短的就停止,需要用“.?”。如“I.*?e”,就会得到第二种结果。这种匹配方式被称为懒惰匹配,而原本尽可能长的方式被称为贪婪匹配。

最后留一道习题:

从下面一段文本中,匹配出所有s开头,e结尾的单词。

site sea sue sweet see case sse ssee loses

先来公布上一课习题的答案:

\bs\S*e\b

有的同学给出的答案是”\bs.*?e\b”。测试一下就会发现,有奇怪的’sea sue’和’sweet see’混进来了。既然是单词,我们就不要空格,所以需要用”\S”而不是”.”

昨天有位同学在论坛上说,用正则表达式匹配出了文件中的手机号。这样现学现用很不错。匹配的规则是”1.*?\n”,在这个文件的条件下,是可行的。但这规则不够严格,且依赖于手机号结尾有换行符。今天我来讲讲其他的方法。

匹配手机号,其实就是找出一串连续的数字。更进一步,是11位,以1开头的数字。

还记得正则第1讲里提到的[]符号吗?它表示其中任意一个字符。所以要匹配数字,我们可以用

[0123456789]

由于它们是连续的字符,有一种简化的写法:[0-9]。类似的还有[a-zA-Z]的用法。

还有另一种表示数字的方法:

\d

要表示任意长度的数字,就可以用

[0-9]*

或者

\d*

但要注意的是,表示的任意长度包括0,也就是没有数字的空字符也会被匹配出来。一个与类似的符号+,表示的则是1个或更长。

所以要匹配出所有的数字串,应当用

[0-9]+

或者

\d+

如果要限定长度,就用{}代替+,大括号里写上你想要的长度。比如11位的数字:

\d{11}

想要再把第一位限定为1,就在前面加上1,后面去掉一位:

1\d{10}

OK. 总结一下今天提到的符号:

[0-9]

\d

+

{}

现在你可以去一个混杂着各种数据的文件里,抓出里面的手机号,或是其他你感兴趣的数字了。

1.

我们已经了解了正则表达式中的一些特殊符号,如\b、\d、.、\S等等。这些具有特殊意义的专用字符被称作“元字符”。常用的元字符还有:

\w – 匹配字母或数字或下划线或汉字(我试验下了,发现3.x版本可以匹配汉字,但2.x版本不可以)

\s – 匹配任意的空白符

^ – 匹配字符串的开始

$ – 匹配字符串的结束

2.

\S其实就是\s的反义,任意不是空白符的字符。同理,还有:

\W – 匹配任意不是字母,数字,下划线,汉字的字符

\D – 匹配任意非数字的字符

\B – 匹配不是单词开头或结束的位置

[a]的反义是[^a],表示除a以外的任意字符。[^abcd]就是除abcd以外的任意字符。

3.

之前我们用过*、+、{}来表示字符的重复。其他重复的方式还有:

? – 重复零次或一次

{n,} – 重复n次或更多次

{n,m} – 重复n到m次

正则表达式不只是用来从一大段文字中抓取信息,很多时候也被用来判断输入的文本是否符合规范,或进行分类。来点例子看看:

^\w{4,12}$

这个表示一段4到12位的字符,包括字母或数字或下划线或汉字,可以用来作为用户注册时检测用户名的规则。(但汉字在python2.x里面可能会有问题)

\d{15,18}

表示15到18位的数字,可以用来检测身份证号码

^1\d*x?

以1开头的一串数字,数字结尾有字母x,也可以没有。有的话就带上x。

另外再说一下之前提到的转义字符\。如果我们确实要匹配.或者字符本身,而不是要它们所代表的元字符,那就需要用.或\。\本身也需要用\。

比如”\d+.\d+”可以匹配出123.456这样的结果。

留一道稍稍有难度的习题:

写一个正则表达式,能匹配出多种格式的电话号码,包括

(021)88776543

010-55667890

02584453362

0571 66345673

来说上次的习题:

(021)88776543

010-55667890

02584453362

0571 66345673

一个可以匹配出所有结果的表达式是

(?0\d{2,3}[) -]?\d{7,8}

解释一下:

(?

()在正则表达式里也有着特殊的含义,所以要匹配字符”(“,需要用”(“。?表示这个括号是可有可无的。

0\d{2,3}

区号,0xx或者0xxx

[) -]?

在区号之后跟着的可能是”)”、” “、”-“,也可能什么也没有。

\d{7,8}

7或8位的电话号码

可是,这个表达式虽然能匹配出所有正确的数据(一般情况下,这样已经足够),但理论上也会匹配到错误的数据。因为()应当是成对出现的,表达式中对于左右两个括号并没有做关联处理,例如(02188776543这样的数据也是符合条件的。

我们可以用正则表达式中的“|”符号解决这种问题。“|”相当于python中“or”的作用,它连接的两个表达式,只要满足其中之一,就会被算作匹配成功。

于是我们可以把()的情况单独分离出来:

(0\d{2,3})\d{7,8}

其他情况:

0\d{2,3}[ -]?\d{7,8}

合并:

(0\d{2,3})\d{7,8}|0\d{2,3}[ -]?\d{7,8}

使用“|”时,要特别提醒注意的是不同条件之间的顺序。匹配时,会按照从左往右的顺序,一旦匹配成功就停止验证后面的规则。假设要匹配的电话号码还有可能是任意长度的数字(如一些特殊的服务号码),你应该把

|\d+

这个条件加在表达式的最后。如果放在最前面,某些数据就可能会被优先匹配为这一条件。你可以写个测试用例体会一下两种结果的不同。

关于正则表达式,我们已经讲了5篇,介绍了正则表达式最最皮毛的一些用法。接下来,这个话题要稍稍告一段落。推荐一篇叫做《正则表达式30分钟入门教程》的文章(直接百度一下就能找到,我也会转到论坛上),想要对正则表达式进一步学习的同学可以参考。这篇教程是个标题党,里面涉及了正则表达式较多的内容,30分钟绝对看不完。

random模块的作用是产生随机数。之前的小游戏中用到过random中的randint:

import random

num = random.randint(1,100)

random.randint(a, b)可以生成一个a到b间的随机整数,包括a和b。

a、b都必须是整数,且必须b≥a。当等于的时候,比如:

random.randint(3, 3)

的结果就永远是3

除了randint,random模块中比较常用的方法还有:

random.random()

生成一个0到1之间的随机浮点数,包括0但不包括1,也就是[0.0, 1.0)。

random.uniform(a, b)

生成a、b之间的随机浮点数。不过与randint不同的是,a、b无需是整数,也不用考虑大小。

random.uniform(1.5, 3)

random.uniform(3, 1.5)

这两种参数都是可行的。

random.uniform(1.5, 1.5)永远得到1.5。

random.choice(seq)

从序列中随机选取一个元素。seq需要是一个序列,比如list、元组、字符串。

random.choice([1, 2, 3, 5, 8, 13]) #list

random.choice(‘hello’) #字符串

random.choice([‘hello’, ‘world’]) #字符串组成的list

random.choice((1, 2, 3)) #元组

都是可行的用法。

random.randrange(start, stop, step)

生成一个从start到stop(不包括stop),间隔为step的一个随机数。start、stop、step都要为整数,且start<stop。

比如:

random.randrange(1, 9, 2)

就是从[1, 3, 5, 7]中随机选取一个。

start和step都可以不提供参数,默认是从0开始,间隔为1。但如果需要指定step,则必须指定start。

random.randrange(4) #[0, 1, 2, 3]

random.randrange(1, 4) #[1, 2, 3]

random.randrange(start, stop, step)其实在效果上等同于

random.choice(range(start, stop, step))

random.sample(population, k)

从population序列中,随机获取k个元素,生成一个新序列。sample不改变原来序列。

random.shuffle(x)

把序列x中的元素顺序打乱。shuffle直接改变原有的序列。

以上是random中常见的几个方法。如果你在程序中需要其中某一个方法,也可以这样写:

from random import randint

randint(1, 10)

另外,有些编程基础的同学可能知道,在随机数中有个seed的概念,需要一个真实的随机数,比如此刻的时间、鼠标的位置等等,以此为基础产生伪随机数。在python中,默认用系统时间作为seed。你也可以手动调用random.seed(x)来指定seed。

Python中有一个time模块

它提供了一些与时间相关的方法。利用time,可以简单地计算出程序运行的时间。对于一些比较复杂、耗时较多的程序,可以通过这种方法了解程序中哪里是效率的瓶颈,从而有针对性地进行优化。

在计算机领域有一个特殊的时间,叫做epoch,它表示的时间是1970-01-01 00:00:00 UTC。

Python中time模块的一个方法

time.time()

返回的就是从epoch到当前的秒数(不考虑闰秒)。这个值被称为unix时间戳。

于是我们可以用这个方法得到程序开始和结束所用的时间,进而算出运行的时间:

In [9]:
import time starttime = time.time() print ('start:%f' % starttime) for i in range(10): print (i) endtime = time.time() print ('end:%f' % endtime) print ('total time:%f' % (endtime-starttime)) 

start:1530929854.164775 0 1 2 3 4 5 6 7 8 9 end:1530929854.165777 total time:0.001002 

顺便再说下time中的另一个很有用的方法:

time.sleep(secs)

它可以让程序暂停secs秒。例如:

In [12]:
import time print (1) time.sleep(2) print (2) 

1 2 

今天我就来讲讲代码遇到问题时的一些简单处理方法。

  1. 读错误信息

来看如下一个例程:

import random

a = 0

for i in range(5):

b = random.choice(range(5))
a += i / b

print a

这个程序中,i从0循环到4,每次循环中,b是0到4中的一个随机数。把i/b的结果累加到a上,最后输出结果。

运行这段程序,有时候会输出结果,有时候却跳出错误信息:

Traceback (most recent call last):

File “C:\Users\Crossin\Desktop\py\test.py”, line 5, in

a += i / b

ZeroDivisionError: integer division or modulo by zero

有些同学看见一段英文提示就慌了。其实没那么复杂,python的错误提示做得还是很标准的。

它告诉我们错误发生在test.py文件中的第6行

a += i / b

这一句上。

这个错误是“ZeroDivisionError”,也就是除零错。

“integer division or modulo by zero”,整数被0除或者被0模(取余数)。

因为0不能作为除数,所以当b随机到0的时候,就会引发这个错误。

知道了原因,就可以顺利地解决掉这个bug。

以后在写代码的时候,如果遇到了错误,先别急着去改代码。试着去读一读错误提示,看看里面都说了些啥。

  1. 输出调试信息

我们在所有课程的最开始就教了输出函数“print”。它是编程中最简单的调试手段。有的时候,仅从错误提示仍然无法判断出程序错误的原因,或者没有发生错误,但程序的结果就是不对。这种情况下,通过输出程序过程中的一些状态,可以帮助分析程序。

把前面那个程序改造一下,加入一些与程序功能无关的输出语句:

import random

a = 0

for i in range(5):

print 'i: %d' % i 
b = random.choice(range(5))
print 'b: %d' % b
a += i / b
print 'a: %d' % a
print

print a

运行后的输出结果(每次结果都会不一样):

i: 0

b: 3

a: 0

i: 1

b: 3

a: 0

i: 2

b: 3

a: 0

i: 3

b: 0

Traceback (most recent call last):

File “C:\Users\Crossin\Desktop\py\test.py”, line 7, in

a += i / b

ZeroDivisionError: integer division or modulo by zero

当b的值为0时,发生了除零错。这次可以更清晰地看出程序出错时的状态。

在真实开发中,程序的结构可能会非常复杂。通过输出调试信息,可以有效地缩小范围、定位错误发生的位置,确认错误发生时的场景,进而找出错误原因。

序列化 pickle

  • python3 在字符方面和 python2 区别较大

In [30]:
import pickle test_data = ['Save me!'.encode('utf8'), 123.456, True] f = open('test.data', 'wb+') pickle.dump(test_data, f) f.close() 

In [32]:
import pickle f = open('test.data','rb') test_data = pickle.load(f) f.close() print (test_data) 

[b'Save me!', 123.456, True] 

如果你想保存多个对象,一种方法是把这些对象先全部放在一个序列中,在对这个序列进行存储:

a = 123

b = “hello”

c = 0.618

data = (a, b, c)

pickle.dump(data, f)

另一种方法就是依次保存和提取:

pickle.dump(a, f)

pickle.dump(b, f)

pickle.dump(c, f)

x = pickle.load(f)

y = pickle.load(f)

z = pickle.load(f)

dump 方法可以增加一个可选的参数,来指定用二进制来存储:

pickle.dump(data, f, True)

而 load 方法会自动检测数据是二进制还是文本格式,无需手动指定。

【特别说明】python3中,通过pickle对数据进行存储时,必须用二进制(b)模式读写文件。

Python 还提供了另一个模块 cPickle,它的功能及用法和 pickle 模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle快1000倍)。因此你可以把上述代码中的 pickle 全部替换为 cPickle,从而提高运行速度(尽管在这个小程序中影响微乎其微)。

列表解析(List Comprehension)

In [33]:
list_1 = [1, 2, 3, 5, 8, 13, 22] list_2 = [] for i in list_1: if i % 2 == 0: list_2.append(i) print (list_2) 

[2, 8, 22] 

In [34]:
list_1 = [1, 2, 3, 5, 8, 13, 22] list_2 = [i for i in list_1 if i % 2 == 0] print (list_2) 

[2, 8, 22] 

函数的参数传递

我们曾经讲过 Python 中函数的参数传递(见第21课)。最基本的方式是:

定义:

def func(arg1, arg2):

print arg1, arg2

调用:

func(3, 7)

我们把函数定义时的参数名(arg1、arg2)称为形参,调用时提供的参数(3、7)称为实参。

这种方式是根据调用时提供参数的位置进行匹配,要求实参与行参的数量相等,默认按位置匹配参数。调用时,少参数或者多参数都会引起错误。这是最常用的一种函数定义方式。

在调用时,也可以根据形参的名称指定实参。如:

func(arg2=3, arg1=7)

但同样,必须提供所有的参数。看看和func(3, 7)的运行结果有什么不同。

Python 语言还提供了其他一些更灵活的参数传递方式,如:

func2(a=1, b=2, c=3)

func3(*args)

func4(**kargs)

今天我们先说说func2这种方式。

这种方式可以理解为,在一般函数定义的基础上,增加了参数的默认值。这样定义的函数可以和原来一样使用,而当你没有提供足够的参数时,会用默认值作为参数的值。

例如:

定义

In [2]:
def func(arg1=1, arg2=2, arg3=3): print (arg1, arg2, arg3) 

In [3]:
# 调用: func(2, 3, 4) func(5, 6) func(7) 

2 3 4 5 6 3 7 2 3 

输出为

2 3 4

5 6 3

7 2 3

提供的参数会按顺序先匹配前面位置的参数,后面未匹配到的参数使用默认值。

也可以指定其中的部分参数,如:

In [4]:
func(arg2=8) func(arg3=9, arg1=10) 

1 8 3 10 2 9 

输出为

1 8 3

10 2 9

In [5]:
#或者混合起来用: func(11, arg3=12) 

11 2 12 

输出为

11 2 12

但要注意,没有指定参数名的参数必须在所有指定参数名的参数前面,且参数不能重复。以下的调用都是错误的:

func(arg1=13, 14)

func(15, arg1=16)

定义参数默认值的函数可以在调用时更加简洁。大量 Python 模块中的方法都运用了这一方式,让使用者在调用时可以提供尽可能少的参数。

接着上一次的内容,来介绍一种更加灵活的参数传递方式:

def func(*args)

这种方式的厉害之处在于,它可以接受任意数量的参数。来看具体例子:

In [7]:
def calcSum(*args): sum = 0 for i in args: sum += i print (sum) 

In [9]:
# 调用 calcSum(1,2,3) calcSum(123,456) calcSum() 

6 579 0 

输出:

6

579

0

在变量前加上星号前缀(*),调用时的参数会存储在一个 tuple(元组)对象中,赋值给形参。在函数内部,需要对参数进行处理时,只要对这个 tuple 类型的形参(这里是 args)进行操作就可以了。因此,函数在定义时并不需要指明参数个数,就可以处理任意参数个数的情况。

不过有一点需要注意,tuple 是有序的,所以 args 中元素的顺序受到赋值时的影响。如:

In [14]:
def printAll(*args): for i in args: print (i,end=' ') print() 

In [15]:
#调用: printAll(1,2,3) printAll(3,2,1) 

1 2 3 3 2 1 

输出:

1 2 3

3 2 1

虽然3个参数在总体上是相同的,但由于调用的顺序不一样,结果也是不同的。

还有一种参数传递方式,既可以按参数名传递参数,不受位置的限制,又可以像 tuple 传递一样不受数量限制。这个我将在下次课中做介绍。

今天来说说最为灵活的一种参数传递方式:

func(**kargs)

上次说的 func(*args) 方式是把参数作为 tuple 传入函数内部。而 func(**kargs) 则是把参数以键值对字典的形式传入。

示例:

In [16]:
def printAll(**kargs): for k in kargs: print (k, ':', kargs[k]) printAll(a=1, b=2, c=3) printAll(x=4, y=5) 

a : 1 b : 2 c : 3 x : 4 y : 5 

输出:

a : 1

c : 3

b : 2

y : 5

x : 4

字典是无序的,所以在输出的时候,并不一定按照提供参数的顺序。同样在调用时,参数的顺序无所谓,只要对应合适的形参名就可以了。于是,采用这种参数传递的方法,可以不受参数数量、位置的限制。

当然,这还不够。Python 的函数调用方式非常灵活,前面所说的几种参数调用方式,可以混合在一起使用。看下面这个例子:

In [18]:
def func(x, y=5, *a, **b): print (x, y, a, b) func(1) func(1,2) func(1,2,3) func(1,2,3,4) func(x=1) func(x=1,y=1) func(x=1,y=1,a=1) func(x=1,y=1,a=1,b=1) func(1,y=1) func(1,2,3,4,a=1) func(1,2,3,4,k=1,t=2,o=3) 

1 5 () {} 1 2 () {} 1 2 (3,) {} 1 2 (3, 4) {} 1 5 () {} 1 1 () {} 1 1 () {'a': 1} 1 1 () {'a': 1, 'b': 1} 1 1 () {} 1 2 (3, 4) {'a': 1} 1 2 (3, 4) {'k': 1, 't': 2, 'o': 3} 

输出:

1 5 () {}

1 2 () {}

1 2 (3,) {}

1 2 (3, 4) {}

1 5 () {}

1 1 () {}

1 1 () {‘a’: 1}

1 1 () {‘a’: 1, ‘b’: 1}

1 1 () {}

1 2 (3, 4) {‘a’: 1}

1 2 (3, 4) {‘k’: 1, ‘t’: 2, ‘o’: 3}

在混合使用时,首先要注意函数的写法,必须遵守:

带有默认值的形参(arg=)须在无默认值的形参(arg)之后;

元组参数(*args)须在带有默认值的形参(arg=)之后;

字典参数(*kargs)须在元组参数(args)之后。

可以省略某种类型的参数,但仍需保证此顺序规则。

调用时也需要遵守:

指定参数名称的参数要在无指定参数名称的参数之后;

不可以重复传递,即按顺序提供某参数之后,又指定名称传递。

而在函数被调用时,参数的传递过程为:

1.按顺序把无指定参数的实参赋值给形参;

2.把指定参数名称(arg=v)的实参赋值给对应的形参;

3.将多余的无指定参数的实参打包成一个 tuple 传递给元组参数(*args);

4.将多余的指定参数名的实参打包成一个 dict 传递给字典参数(**kargs)。

是不是乍一看有点绕?没关系,赶紧打开你的编辑器,自行体会一下不同调用方式的用法。然后在未来的编程实践中慢慢熟悉吧。

lambda 表达式

Python 是一门简洁的语言,lambda 表达式则充分体现了 Python 这一特点。

lambda 表达可以被看做是一种匿名函数。它可以让你快速定义一个极度简单的单行函数。譬如这样一个实现三个数相加的函数:

In [19]:
def sum(a, b, c): return a + b + c print (sum(1, 2, 3)) print (sum(4, 5, 6)) 

6 15 

In [20]:
# 如果使用 lambda 表达式来实现: sum = lambda a, b, c: a + b + c print (sum(1, 2, 3)) print (sum(4, 5, 6)) 

6 15 

两种方法的结果是相同的。

lambda 表达式的语法格式:

lambda 参数列表: 表达式

定义 lambda 表达式时,参数列表周围没有括号,返回值前没有 return 关键字,也没有函数名称。

它的写法比 def 更加简洁。但是,它的主体只能是一个表达式,不可以是代码块,甚至不能是命令(print 不能用在 lambda 表达式中)。所以 lambda 表达式能表达的逻辑很有限。

lambda 表达式创建了一个函数对象,可以把这个对象赋值给一个变量进行调用,就像上面的例子中一样。

来看一个复杂一点的例子,把 lambda 表达式用在 def 函数定义中:

In [21]:
def fn(x): return lambda y: x + y a = fn(2) print (a(3)) 

5 

这里,fn 函数的返回值是一个 lambda 表达式,也就等于是一个函数对象。当以参数2来调用 fn 时,得到的结果就是:

lambda y: 2 + y

a = fn(2) 就相当于:

a = lambda y: 2 + y

所以 a(3) 的结果就是5。

lambda 表达式其实只是一种编码风格,这种写法更加 pythonic。这并不意味着你一定要使用它。事实上,任何可以使用 lambda 表达式的地方,都可以通过普通的 def 函数定义来替代。在一些需要重复使用同一函数的地方,def 可以避免重复定义函数。况且 def 函数更加通用,某些情况可以带来更好地代码可读性。

而对于像 filter、sort 这种需要内嵌函数的方法,lambda 表达式就会显得比较合适。这个我以后会再单独介绍。

当然对于初学者来说,了解 lambda 表达式还有一个重要作用就是,看懂别人写的代码。

变量的作用域

在写代码的时候,免不了要使用变量。但程序中的一个变量并不一定是在哪里都可以被使用,根据情况不同,会有不同的“有效范围”。看这样一段代码:

In [22]:
def func(x): print ('X in the beginning of func(x): ', x) x = 2 print ('X in the end of func(x): ', x) x = 50 func(x) print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 2 X after calling func(x): 50 

变量 x 在函数内部被重新赋值。但在调用了函数之后,x 的值仍然是50。为什么?

这就得说一下变量的“作用域”:

当函数内部定义了一个变量,无论是作为函数的形参,或是另外定义的变量,它都只在这个函数的内部起作用。函数外即使有和它名称相同的变量,也没有什么关联。这个函数体就是这个变量的作用域。像这样在函数内部定义的变量被称为“局部变量”。

要注意的是,作用域是从变量被定义的位置开始。像这样的写法是有问题的:

In [24]:
def func(): print (y) y = 2 print (y) func() 

--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-24-5af4faf299fd> in <module>()  7 print (y)  8 ----> 9 func() <ipython-input-24-5af4faf299fd> in func()  1 def func():  2 ----> 3 print (y)  4  5 y = 2 UnboundLocalError: local variable 'y' referenced before assignment

因为在 y = 2 之前,y 并不存在,调用 y 的值就会出错。

回到开始那个例子:

在函数 func 外部,定义的变量 x,赋值为 50,作为参数传给了函数 func。而在函数 func 内部,变量 x 是形参,它的作用域是整个函数体内部。它与外面的那个 x 没有关系。只不过它的初始值是由外面那个 x 传递过来的。

所以,虽然函数体内部的 x 被重新赋值为 2,也不会影响外面那个 x 的值。

不过有时候,我们希望能够在函数内部去改变一些变量的值,并且这些变量在函数外部同样被使用到。怎么办?

一种方法是,用 return 把改变后的变量值作为函数返回值传递出来,赋值给对应的变量。比如开始的那个例子,可以在函数结尾加上

return x

然后把调用改为

x = func(x)

还有一种方法,就是使用“全局变量”。

在 Python 的函数定义中,可以给变量名前加上 global 关键字,这样其作用域就不再局限在函数块中,而是全局的作用域。

In [25]:
#通过 global 改写开始的例子: def func(): global x print ('X in the beginning of func(x): ', x) x = 2 print ('X in the end of func(x): ', x) x = 50 func() print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 2 X after calling func(x): 2 

函数 func 不再提供参数调用。而是通过 global x 告诉程序:这个 x 是一个全局变量。于是函数中的 x 和外部的 x 就成为了同一个变量。这一次,当 x 在函数 func 内部被重新赋值后,外部的 x 也随之改变。

前面讲的局部变量和全局变量是 Python 中函数作用域最基本的情况。实际上,还有一些略复杂的情况,比如:

In [26]:
def func(): print ('X in the beginning of func(x): ', x) # x = 2 print ('X in the end of func(x): ', x) x = 50 func() print ('X after calling func(x): ', x) 

X in the beginning of func(x): 50 X in the end of func(x): 50 X after calling func(x): 50 

程序可以正常运行。虽然没有指明 global,函数内部还是使用到了外部定义的变量。然而一旦加上

x = 2

这句,程序就会报错。因为这时候,x 成为一个局部变量,它的作用域从定义处开始,到函数体末尾结束。

建议在写代码的过程中,显式地通过 global 来使用全局变量,避免在函数中直接使用外部变量。

map 函数

  • python2 和 python3 中 map返回值得类型不一样

来看两个问题:

  1. 假设有一个数列,如何把其中每一个元素都翻倍?

  2. 假设有两个数列,如何求和?

第一个问题,普通程序员大概会这么写:

In [27]:
lst_1 = [1,2,3,4,5,6] lst_2 = [] for item in lst_1: lst_2.append(item * 2) print (lst_2) 

[2, 4, 6, 8, 10, 12] 

In [29]:
#Python 程序员大概会这么写: lst_1 = [1,2,3,4,5,6] lst_2 = [i * 2 for i in lst_1] print (lst_2) 

[2, 4, 6, 8, 10, 12] 

这是我在《【Python 第66课】列表综合》里说到的方法,微信中回复 66 可以查看。

今天来说另一种 Python 程序员常用的写法 — map:

In [53]:
lst_1 = [1,2,3,4,5,6] def double_func(x): return x * 2 lst_2 = map(double_func, lst_1) print (list(lst_2)) 

[2, 4, 6, 8, 10, 12] 

map 是 Python 自带的内置函数,它的作用是把一个函数应用在一个(或多个)序列上,把列表中的每一项作为函数输入进行计算,再把计算的结果以列表的形式返回。

map 的第一个参数是一个函数,之后的参数是序列,可以是 list、tuple。

所以刚刚那个问题也可以写成:

In [52]:
lst_1 = (1,2,3,4,5,6) lst_2 = map(lambda x: x * 2, lst_1) print (list(lst_2)) 

[2, 4, 6, 8, 10, 12] 

这里原数据改为了元组,函数用 lambda 表达式替代。可参考《【Python 第70课】lambda 表达式》,微信中回复 70。

map 中的函数可以对多个序列进行操作。最开始提出的第二个问题,除了通常的 for 循环写法,如果用列表综合的方法比较难实现,但用 map 就比较方便:

In [51]:
lst_1 = [1,2,3,4,5,6] lst_2 = [1,3,5,7,9,11] lst_3 = map(lambda x, y: x + y, lst_1, lst_2) print (list(lst_3)) 

[2, 5, 8, 11, 14, 17] 

map 中的函数会从对应的列表中依次取出元素,作为参数使用,同样将结果以列表的形式返回。所以要注意的是,函数的参数个数要与 map 中提供的序列组数相同,即函数有几个参数,就得有几组数据。

对于每组数据中的元素个数,如果有某组数据少于其他组,map 会以 None 来补全这组参数。

此外,当 map 中的函数为 None 时,结果将会直接返回参数组成的列表。如果只有一组序列,会返回元素相同的列表,如果有多组数列,将会返回每组数列中,对应元素构成的元组所组成的列表。听上去很绕口是不是……代码试试看就明白了:

In [50]:
def f(x, y): return (x, y) lst_1 = [1,2,3,4,5,6] lst_2 = [1,3,5,7,9,11] lst_3 = list(map(f, lst_1, lst_2)) print (lst_3) 

[(1, 1), (2, 3), (3, 5), (4, 7), (5, 9), (6, 11)] 

In [40]:
def f(x, y): return (x, y) l1 = [ 0, 1, 2, 3, 4, 5, 6 ] l2 = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ] list(map(f, l1, l2)) 

Out[40]:
[(0, 'Sun'), (1, 'Mon'), (2, 'Tue'), (3, 'Wed'), (4, 'Thu'), (5, 'Fri'), (6, 'Sat')]

reduce 函数

  • python3中需要 from functools import reduce

上次说了 Python 中一个比较有意思的内置函数 map,今天再来介绍另一个类似的函数:reduce

map 可以看作是把一个序列根据某种规则,映射到另一个序列。reduce 做的事情就是把一个序列根据某种规则,归纳为一个输出。

上栗子。以前我们给过一个习题,求1累加到100的和。寻常的做法大概是这样:

In [56]:
sum = 0 for i in range(1, 101): sum += i print (sum) 

5050

In [59]:
#如果用 reduce 函数,就可以写成: from functools import reduce lst = range(1, 101) def add(x, y): return x + y print (reduce(add, lst)) 

5050

解释一下:

reduce(function, iterable[, initializer])

第一个参数是作用在序列上的方法,第二个参数是被作用的序列,这与 map 一致。另外有一个可选参数,是初始值。

function 需要是一个接收2个参数,并有返回值的函数。它会从序列 iterable 里从左到右依次取出元素,进行计算。每次计算的结果,会作为下次计算的第一个参数。

提供初始值 initializer 时,它会作为第一次计算的第一个参数。否则,就先计算序列中的前两个值。

如果把刚才的 lst 换成 [1,2,3,4,5],那 reduce(add, lst) 就相当于 ((((1+2)+3)+4)+5)。

同样,可以用 lambda 函数:

reduce((lambda x, y: x + y), xrange(1, 101))

所以,在对于一个序列进行某种统计操作的时候,比如求和,或者诸如统计序列中元素的出现个数等(可尝试下如何用 reduce 做到),可以选择使用 reduce 来实现。相对可以使代码更简洁。

我觉得,写代码的可读性是很重要的事情,简洁易懂的代码,既容易让别人看懂,也便于自己以后的维护。同时,较少的代码也意味着比较高的开发效率和较少的出错可能。应尽量避免写混乱冗长的代码。当然,也不用为了一味追求代码的精简,总是想方设法把代码写在一行里。那就又走了另一个极端,同样也缺乏可读性。而至于是否使用类似 map、reduce 这样的方法,也是根据需要和个人习惯,我认为并没有一定的规则限制。

多线程

很多人使用 python 编写“爬虫”程序,抓取网上的数据。 举个例子,通过豆瓣的 API 抓取 30 部影片的信息:

Python3 多线程 http://www.runoob.com/python3/python3-multithreading.html

In [62]:
import urllib3, time import urllib time_start = time.time() data = [] for i in range(30): print ('request movie:', i) id = 1764796 + i http = urllib3.PoolManager() r = http.request('url','https://api.douban.com/v2/movie/subject/%d' % id) data.append(r) print (i, time.time() - time_start) print ('data:', len(data)) 

request movie: 0 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

0 1.0452296733856201 request movie: 1 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

1 1.4376976490020752 request movie: 2 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

2 2.036301851272583 request movie: 3 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

3 2.424480676651001 request movie: 4 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

4 3.1788370609283447 request movie: 5 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

5 3.515458583831787 request movie: 6 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

6 3.929321050643921 request movie: 7 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

7 4.4893105030059814 request movie: 8 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

8 4.876185178756714 request movie: 9 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

9 5.189667701721191 request movie: 10 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

10 5.549666404724121 request movie: 11 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

11 5.911073446273804 request movie: 12 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

12 6.593060493469238 request movie: 13 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

13 6.948549032211304 request movie: 14 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

14 7.268184423446655 request movie: 15 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

15 7.610193967819214 request movie: 16 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

16 8.079214572906494 request movie: 17 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

17 8.54995846748352 request movie: 18 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

18 8.875677585601807 request movie: 19 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

19 9.214396715164185 request movie: 20 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

20 9.786171436309814 request movie: 21 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

21 10.36324691772461 request movie: 22 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

22 10.938879013061523 request movie: 23 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

23 11.297513961791992 request movie: 24 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

24 11.634414911270142 request movie: 25 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

25 11.952378273010254 request movie: 26 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

26 12.278428792953491 request movie: 27 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

27 12.637410163879395 request movie: 28 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

28 12.983117580413818 request movie: 29 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

29 13.632150173187256 data: 30 

程序里用了 time.time() 来计算抓取花费的时间。运行一遍,大约需要十几秒(根据网络情况会有差异)。

如果我们想用这套代码抓取几万部电影,就算中间不出什么状况,估计也得花上好几个小时。

然而想一下,我们抓一部电影信息的过程是独立,并不依赖于其他电影的结果。因此没必要排好队一部一部地按顺序来。那么有没有什么办法可以同时抓取好几部电影?

答案就是:多线程。

来说一种简单的多线程方法:

python 里有一个 thread 模块,其中提供了一个函数:

start_new_thread(function, args[, kwargs])

function 是开发者定义的线程函数,

args 是传递给线程函数的参数,必须是tuple类型,

kwargs 是可选参数。

调用 start_new_thread 之后,会创建一个新的线程,来执行 function 函数。而代码原本的主线程将继续往下执行,不再等待 function 的返回。通常情况,线程在 function 执行完毕后结束。

改写一下前面的代码,将抓取的部分放在一个函数中:

In [65]:
import urllib3, time, _thread def get_content(i): id = 1764796 + i http = urllib3.PoolManager() r = http.request('url','https://api.douban.com/v2/movie/subject/%d' % id) data.append(r) print (i, time.time() - time_start) print ('data:', len(data)) time_start = time.time() data = [] for i in range(30): print ('request movie:', i) _thread.start_new_thread(get_content, (i,)) input('press ENTER to exit...\n') 

request movie: 0 request movie: 1 request movie: 2 request movie: 3 request movie: 4 request movie: 5 request movie: 6 request movie: 7 request movie: 8 request movie: 9 request movie: 10 request movie: 11 request movie: 12 request movie: 13 request movie: 14 request movie: 15 request movie: 16 request movie: 17 request movie: 18 request movie: 19 request movie: 20 request movie: 21 request movie: 22 request movie: 23 request movie: 24 request movie: 25 request movie: 26 request movie: 27 request movie: 28 request movie: 29 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

5 0.7017581462860107 data: 1 10 0.7559306621551514 data: 2 24 0.7629213333129883 data: 3 1 0.7649266719818115 data: 4 6 0.7935028076171875 data: 5 14 0.803107500076294 data: 6 23 0.8040831089019775 data: 7 15 0.8114683628082275 data: 8 253 0.8258225917816162 data: 10 0.826324462890625 data: 10 261328 0.8268251419067383 data: 13 0.8273270130157471 data: 13 0.8268251419067383 data: 13 811 0.845090389251709 data: 15 0.8446097373962402 data: 15 1718 16 0.883171558380127 data: 0.8815431594848633 data: 18 18 0.880507230758667 data: 18 21 0.9177229404449463 data: 19 2 0.9450147151947021 data: 20 4 0.9600613117218018 data: 21 0 0.9701051712036133 data: 22 20 0.9744563102722168 data: 23 27 0.9754600524902344 data: 24 79 1.0218162536621094 data: 26 1.0213446617126465 data: 26 19 1.0371334552764893 data: 27 12 1.0552606582641602 data: 28 29 1.0806910991668701 data: 29 22 1.1721751689910889 data: 30 press ENTER to exit... 

F:\Anaconda\envs\TensorFlow\lib\site-packages\urllib3\connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning) 

Out[65]:
''

因为主线程不在等待函数返回结果,所以在代码最后,增加了 raw_input,避免程序提前退出。

从输出结果可以看出:

在程序刚开始运行时,已经发送所有请求

收到的请求并不是按发送顺序,先收到就先显示

总共用时两秒多

data 里同样记录了所有30条结果

所以,对于这种耗时长,但又独立的任务,使用多线程可以大大提高运行效率。但在代码层面,可能额外需要做一些处理,保证结果正确。如上例中,如果需要电影信息按 id 排列,就要另行排序。

多线程通常会用在网络收发数据、文件读写、用户交互等待之类的操作上,以避免程序阻塞,提升用户体验或提高执行效率。

多线程的实现方法不止这一种。另外多线程也会带来一些单线程程序中不会出现的问题。这里只是简单地开个头。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/182676.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号