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)


相关推荐

  • goland2021.2激活破解码

    idea激活码:https://javaforall.cn/100143.html,全栈程序员必看教程网idea激活码推荐

  • Java多线程——基本概念「建议收藏」

    Java多线程——基本概念「建议收藏」线程和多线程程序:是一段静态的代码,是应用软件执行的蓝本进程:是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡的过程线程:是比进程更小的执行单位。进程在其执行过程中,可以产生多个线程,形成多条执行线索,每条线索,即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念主线程:(每个Java程序都有一个…

  • Geth私链的多节点运行「建议收藏」

    Geth私链的多节点运行「建议收藏」前一阵分别介绍了在Ubuntu和CentOS下搭建基于Geth的以太坊私链,这篇文章介绍如何搭建Geth多节点的运行。提示:在Ubuntu和CentOS下搭建以太坊私链,请参考《在Ubuntu下使用Geth搭建自己的以太坊私有链》和《CentOS7下安装Geth,搭建以太坊私有链》一、在Windows下安装Geth为了方便测试,我在Windows下搭建了一个套Geth环境。安装方…

  • rabbit mq exchange_exchange设置公司邮箱

    rabbit mq exchange_exchange设置公司邮箱上一篇,我们介绍了rabbimtmq的简单工作队列的使用方式,即生产者和消费者之间直接通过绑定相同的workqueue进行消息的发送和接收,如果业务逻辑比较简单,这样的方式也是可以用的,但在实际工作中,实际的业务场景远远比这个复杂,而且需要更加细粒度的对消息进行进行分发和接收,这就需要用到rabbitmq的另外一个组件exchange;顾名思义,exchange在rabbitmq中翻译为交换机…

  • 基于jQuery 常用WEB控件收集

    基于jQuery 常用WEB控件收集

  • 一个好玩的小游戏(纯C语言编写)

    一个好玩的小游戏(纯C语言编写)最近在看知乎是发现了一个这一个专栏https://zhuanlan.zhihu.com/c2game从中获取的许多知识,本文中的游戏也是从里面学到的,不过本人又自己加了一些功能。这是一个类似于飞机大战的游戏,不过目前代码量比较小,所以看起来非常简陋游戏界面如下更新日志,本人将原来的原来的代码有进一步的优化了一下,之前是只有一个非常小的战机现在更新后可以产生一个非常大的战机(看起来也更

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号