練習(xí) 13 參數(shù)菩浙,解包,變量
在這個(gè)練習(xí)中我們將會(huì)再涉及一種 input
方法句伶,你可以用這種方法把變量傳給一個(gè)腳本(也就是你的 .py
文件)劲蜻。你知道如何運(yùn)行 ex13.py
吧?輸入 python3.6 ex13.py
就行(Windows 下輸入 python ex13.py
)考余。這句命令的 ex13.py 就叫做參數(shù)(argument)先嬉。我們現(xiàn)在要做的就是寫(xiě)一個(gè)也接受參數(shù)的腳本。
輸入這個(gè)程序楚堤,然后我會(huì)詳細(xì)解釋?zhuān)?/p>
ex13.py
1 from sys import argv
2 # read the WYSS section for how to run this
3 script, first, second, third = argv
4
5 print("The script is called:", script)
6 print("Your first variable is:", first)
7 print("Your second variable is:", second)
8 print("Your third variable is:", third)
第一行我們進(jìn)行了 “import”(導(dǎo)入)疫蔓,這能讓你把 Python 功能庫(kù)中的功能(features)添加到你的腳本中含懊。Python 會(huì)問(wèn)你你想用什么,而不是一次把所有的功能都給你衅胀。它會(huì)讓你的程序很小岔乔,但是它同時(shí)也可以為其它閱讀你代碼的程序員提供參考。
這個(gè) argv
是 “argument variable” 滚躯,一個(gè)在編程語(yǔ)言中非常標(biāo)準(zhǔn)的名字雏门,你會(huì)在其它很多的語(yǔ)言中看到它的使用。當(dāng)你運(yùn)行 Python 腳本的時(shí)候掸掏,這個(gè)變量(variable)保存了你傳給 Python 腳本的參數(shù)(argument)茁影。在這個(gè)練習(xí)中,你會(huì)做更多相關(guān)的練習(xí)丧凤,看看會(huì)發(fā)生什么募闲。
第三行“解包”(unpacks)了 argv
,而不是保留所有的參數(shù)愿待,它分成了四個(gè)變量:script
, first
, second
, 以及 third
浩螺。這可能看起來(lái)很奇怪,但是“解包”這個(gè)詞可能是對(duì)這個(gè)操作的最好定義仍侥,就好像在說(shuō):“把 argv 里面的東西解包年扩,然后按順序分配給從左到右每一個(gè)變量。最后就像平常一樣把它們打印出來(lái)即可访圃。
等等!Features 還有另一個(gè)名字
我在這兒把它們叫做 features (就是你導(dǎo)入進(jìn)來(lái)讓 python 做更多事情的東西)相嵌,但是很少有人叫它們 features腿时。我用這個(gè)名字只是因?yàn)槲蚁胱屇阍趯?zhuān)業(yè)術(shù)語(yǔ)之外思考它們的真正含義。不過(guò)在你繼續(xù)學(xué)習(xí)之前饭宾,你需要知道它們真正的名字:modules (模塊)批糟。
從現(xiàn)在開(kāi)始我們會(huì)把這些 features 說(shuō)成導(dǎo)入模塊,比如看铆,“你想導(dǎo)入 sys
模塊”徽鼎。
它們還被有些程序員叫做“l(fā)ibraries”(庫(kù)),但是我們就用模塊這個(gè)名字吧弹惦。
你會(huì)看到
警告否淤! |
---|
注意!你之前一直直接運(yùn)行 python 腳本棠隐,不用輸入命令行參數(shù)石抡。如果你只輸入 python3.6 ex13.py 你就錯(cuò)了助泽!注意看我是怎么操作的嚎京,這在任何有 argv 的地方都會(huì)用到隐解。 |
像這樣運(yùn)行這個(gè)程序鞍帝,前面是你要傳遞的命令行參數(shù):
練習(xí) 13 會(huì)話(huà)
$ python3.6 ex13.py first 2nd 3rd
The script is called: ex13.py
Your first variable is: first
Your second variable is: 2nd
Your third variable is: 3rd
當(dāng)你做一些不同參數(shù)的運(yùn)行時(shí),你會(huì)看到:
練習(xí) 13 會(huì)話(huà)
$ python3.6 ex13.py stuff things that
The script is called: ex13.py
Your first variable is: stuff
Your second variable is: things
Your third variable is: that
$
$ python3.6 ex13.py apple orange grapefruit
The script is called: ex13.py
Your first variable is: apple
Your second variable is: orange
Your third variable is: grapefruit
事實(shí)上你還可以把 first
帕涌,2nd
溜嗜,3rd
替換成任何你想替換的東西宵膨。如果你沒(méi)有正確運(yùn)行,你會(huì)收到這樣的報(bào)錯(cuò):
練習(xí) 13 會(huì)話(huà)
$ python3.6 ex13.py first 2nd
Traceback (most recent call last):
File "ex13.py", line 3, in <module>
script, first, second, third = argv
ValueError: not enough values to unpack (expected 4, got 3)
這種情況一般是當(dāng)你運(yùn)行腳本的時(shí)候沒(méi)有在命令行放足夠的變量(在本例中只有 first
炸宵、2nd
)辟躏。注意當(dāng)我運(yùn)行的時(shí)候只給出 first
捎琐、2nd
裹匙,就會(huì)出現(xiàn)錯(cuò)誤說(shuō)“需要三個(gè)以上的值來(lái)解包”,這就是告訴你籽御,你沒(méi)有給到足夠多的參數(shù)〖继停”
附加練習(xí)
- 試著給你的腳本三個(gè)以?xún)?nèi)的參數(shù)项鬼,看看你會(huì)收到什么樣的報(bào)錯(cuò),你是否能解釋它鸠真。
- 寫(xiě)一個(gè)參數(shù)少的腳本和一個(gè)參數(shù)多的腳本龄毡,給未解包的變量起個(gè)合適的名字。
- 把
input
和argv
結(jié)合起來(lái)創(chuàng)建一個(gè)腳本撤嫩,從用戶(hù)那里獲取更多input
蠢终。別想得太難,就用argv
來(lái)獲取一些東西程奠,再用input
從用戶(hù)那里獲取一些東西丈牢。- 記住模塊給我們一些特征瞄沙,記住它叫模塊(modules)距境,我們之后會(huì)用到。
常見(jiàn)問(wèn)題
當(dāng)我運(yùn)行的時(shí)候我收到了 ValueError: need more than 1 value to unpack.
還記得我說(shuō)過(guò)垫桂,學(xué)習(xí)編程的一項(xiàng)重要技能就是注意細(xì)節(jié)诬滩。如果你看了“你會(huì)看到”那部分,你就會(huì)看到我是如何在命令行上運(yùn)行有參數(shù)的腳本的后控,你應(yīng)該準(zhǔn)確按照我做的來(lái)空镜。
argv
和 input()
之間的區(qū)別是什么? 區(qū)別取決于用戶(hù)在哪被要求輸入张抄,如果是在命令行舶斧,就用 argv察皇。如果你想讓它們?cè)诔绦蛞呀?jīng)運(yùn)行的情況下用鍵盤(pán)輸入什荣,那就用 input()
。
命令行參數(shù)是字符串嗎嗜闻?是的桅锄,它們是以字符串的形式進(jìn)來(lái)的样眠,即使你在命令行輸入的是數(shù)字翠肘。你可以用 int()
把它們轉(zhuǎn)化成數(shù)值束倍,就像 int(input())
。
你如何使用用命令行绪妹?” 你應(yīng)該已經(jīng)學(xué)過(guò)命令行的使用了邮旷,現(xiàn)在應(yīng)該用得很 6 了。但是如果你還沒(méi)有學(xué)糕簿,先去附錄 A 學(xué)習(xí)命令行速成課程狡孔。
我不知道怎么把 argv
和 input()
結(jié)合在一起。 別把它想得太難殃恒。就在腳本最后加兩行辱揭,用 input()
獲取一些東西问窃,再打印出來(lái)。然后試著用更多方式在同一個(gè)腳本中使用這兩樣?xùn)|西嵌戈。
為什么我不能這樣用:input('? ') = x
? 因?yàn)樗鼘?xiě)反了听皿,按我的要求寫(xiě),就能運(yùn)行庵朝。
練習(xí) 14 提示和傳遞
讓我們來(lái)做一個(gè)把 argv
和 input
結(jié)合在一起的練習(xí)來(lái)問(wèn)用戶(hù)一些特別的問(wèn)題。這些問(wèn)題會(huì)在你學(xué)習(xí)下一個(gè)練習(xí)中閱讀和寫(xiě)文件的時(shí)候用到椎瘟。在這個(gè)練習(xí)中我們會(huì)用一種不同的方式使用 input
昔逗,就是讓它打印出一個(gè)簡(jiǎn)單的 >
提示符。這有點(diǎn)像 Zork 或者 Adventure 這兩款游戲婆排。
ex14.py
1 from sys import argv
2
3 script, user_name = argv
4 prompt = '> '
5
6 print(f"Hi {user_name}, I'm the {script} script.")
7 print("I'd like to ask you a few questions.")
8 print(f"Do you like me {user_name}?")
9 likes = input(prompt)
10
11 print(f"Where do you live {user_name}?")
12 lives = input(prompt)
13
14 print("What kind of computer do you have?")
15 computer = input(prompt)
16
17 print(f"""
18 Alright, so you said {likes} about liking me.
19 You live in {lives}. Not sure where that is.
20 And you have a {computer} computer. Nice.
21 """)
我們把用戶(hù)提示符設(shè)置成變量 prompt
段只,然后把它賦給 input
而不是一遍遍地輸入它們〖ǎ現(xiàn)在如果我們想把提示符變成別的東西,只要修改一個(gè)地方炕婶,然后重新運(yùn)行腳本即可莱预,非常方便依沮。
你會(huì)看到
當(dāng)你運(yùn)行腳本的時(shí)候,記住一定要把你的名字賦給這個(gè)腳本宋渔,讓 argv
接收到你的名字辜限。
練習(xí) 14 會(huì)話(huà)
$ python3.6 ex14.py zed
Hi zed, I'm the ex14.py script.
I'd like to ask you a few questions.
Do you like me zed?
> Yes
Where do you live zed?
> San Francisco
What kind of computer do you have?
> Tandy 1000
Alright, so you said Yes about liking me.
You live in San Francisco. Not sure where that is.
And you have a Tandy 1000 computer. Nice.
附加練習(xí)
- 查查看 Zork 和 Adventure 游戲是什么,找來(lái)玩玩氧急。
- 把
prompt
變量改成別的東西岂座。- 在你的腳本里再加一個(gè)參數(shù)费什,就像之前練習(xí)中
first, second = argv
一樣。- 確定你理解了我是如何在最后一行把
"""
多行格式字符(style multiline string)和{}
格式激活器(format activator)結(jié)合起來(lái)的瘩蚪。
常見(jiàn)問(wèn)題
我運(yùn)行腳本的時(shí)候收到了 SyntaxError: invalid syntax
稿黍。我再說(shuō)一次,你得在命令行里運(yùn)行它言沐,而不是在 python 里酣栈。如果你輸入 python3.6
矿筝,然后再輸入 python3.6 ex14.py Zed
,就會(huì)無(wú)法運(yùn)行榆综,因?yàn)槟闶窃?python 里面運(yùn)行 python铸史。關(guān)掉窗口,然后只輸入 python3.6 ex14.py Zed
陋守。
你說(shuō)的“改變提示符”是什么意思利赋?我不太理解。看到這個(gè)變量 prompt = '>'
了嗎中燥?改變它的值塘偎。你知道的吟秩,它只是一個(gè)字符串,你已經(jīng)做了 13 個(gè)練習(xí)來(lái)創(chuàng)建它們了闹伪,所以好好想想,把它弄明白杀怠。
我收到了報(bào)錯(cuò)信息:ValueError: need more than 1 value to unpack.
我前面說(shuō)過(guò)厅克,你需要看看“你會(huì)看到”那部分然后復(fù)制我的做法。這兒也一樣硕旗,注意我是如何輸入命令行的女责,以及我為什么有一個(gè)命令行參數(shù)鲤竹。
我如何從 IDLE 來(lái)運(yùn)行這些?不要用 IDLE碘橘。
我能在 prompt 變量外面用雙引號(hào)嗎吱肌?你完全可以,試試吧纺蛆。
你有一臺(tái) Tandy computer规揪?是的猛铅,在我很小的時(shí)候。
我運(yùn)行的時(shí)候收到了報(bào)錯(cuò)信息:NameError: name 'prompt' is not defined 堕伪。 你要么把 prompt
變量拼寫(xiě)錯(cuò)了栗菜,要么把那行漏掉了疙筹〖旌牛回過(guò)頭去蛙酪,從下到上比較每一行代碼桂塞。你一旦遇到這種報(bào)錯(cuò)馍驯,就說(shuō)明你拼寫(xiě)錯(cuò)誤或者忘了創(chuàng)建變量。
練習(xí) 15 閱讀文件
你已經(jīng)知道如何用 input
或者 argv
來(lái)獲取用戶(hù)的輸入了】翊颍現(xiàn)在你將學(xué)習(xí)如何閱讀文件趴乡。你需要好好做這個(gè)練習(xí)蝗拿,才能理解發(fā)生了什么,記住要仔細(xì)輸入和檢查惦辛。對(duì)文件進(jìn)行操作很容易把文件刪掉仓手,所以你要千萬(wàn)小心嗽冒。
在這個(gè)練習(xí)中你要寫(xiě)兩個(gè)文件。一個(gè)是通常你要運(yùn)行的 ex15.py
区匠,一個(gè)是叫做 ex15_sample.txt
的文本文件帅腌。以下是文本文件中要輸入的內(nèi)容:
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
我們要做的就是在我們的腳本中打開(kāi)這個(gè)文件并把它打印出來(lái)速客。然而,我們不想只是簡(jiǎn)單粗暴(hard coding)地把 ex15_sample.txt
這個(gè)文件名輸入進(jìn)去岔擂,hard coding 的意思是把一些應(yīng)該從用戶(hù)那里獲取的信息直接放到源代碼里。這樣不好塑崖,因?yàn)槲覀冸S后會(huì)需要它載入別的文件痛倚。解決方法是用 argv
或者 input
來(lái)問(wèn)用戶(hù)應(yīng)該打開(kāi)哪個(gè)文件蝉稳,而不是 hard coding 文件名。
ex15.py
1 from sys import argv
2
3 script, filename = argv
4
5 txt = open(filename)
6
7 print(f"Here's your file {filename}:")
8 print(txt.read())
9
10 print("Type the filename again:")
11 file_again = input("> ")
12
13 txt_again = open(file_again)
14
15 print(txt_again.read())
這個(gè)文件里發(fā)生了一些奇妙的事情嗡髓,讓我們快速分解來(lái)看一下:
第 1-3 行用了 argv
來(lái)獲取一個(gè)文件名收津,然后第 5 行用了一個(gè)新的命令 open
∽ズ現(xiàn)在氛濒,運(yùn)行 pydoc open
然后閱讀說(shuō)明唆姐》盥看見(jiàn)了吧剧蹂,就像你自己的腳本和輸入,它用了一個(gè)參數(shù)(parameter)然后返回了一個(gè)值先巴,你可以把它賦給你自己的變量伸蚯。你只是打開(kāi)了一個(gè)文件简烤。
第 7 行打印了一些信息横侦,第 8 行就有一些新東西了绰姻。我們對(duì) txt 用了一個(gè)叫做 read.
的函數(shù)引瀑,你從 open
那里得到的是一個(gè)文件憨栽,而且你還可以通過(guò) . 命令名,以及參數(shù),來(lái)給它一個(gè)命令锯蛀,就像用 open
和 input
那樣次慢。區(qū)別是迫像,txt.(read)
是說(shuō):txt
,執(zhí)行不帶參數(shù)的 read
命令菌羽!
剩下的部分基本上類(lèi)似由缆,但是我們會(huì)把分析留到附加練習(xí)里均唉。
你會(huì)看到
警告! |
---|
注意罩缴!你一直通過(guò)輸入文件名來(lái)運(yùn)行腳本层扶,但是你要用 argv 加上參數(shù)來(lái)運(yùn)行÷悖看看下面例子的第一行焰薄,你會(huì)看我是通過(guò)輸入 python ex15.py ex15_sample.txt 來(lái)運(yùn)行它的。 ex15.py 后面的內(nèi)容就是你要輸入的參數(shù)亩码,如果你漏掉了野瘦,就會(huì)收到報(bào)錯(cuò)信息鞭光!所以千萬(wàn)要注意! |
我創(chuàng)建了一個(gè)叫做 ex15_sample.txt
的文件來(lái)運(yùn)行我的腳本席覆。
練習(xí) 15 會(huì)話(huà)
$ python3.6 ex15.py ex15_sample.txt
Here's your file ex15_sample.txt:
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
Type the filename again:
> ex15_sample.txt
This is stuff I typed into a file.
It is really cool stuff.
Lots and lots of fun to have in here.
附加練習(xí)
這部分可能比較難佩伤,在你往下進(jìn)行之前晦毙,確保你盡力去做這個(gè)附加練習(xí)。
- 在每行上面添加注釋解釋其含義孤荣。
- 如果你不確定垃环,上網(wǎng)搜返敬,或者問(wèn)別人劲赠,比如你不知道 open 的用法,直接搜
python3.6 open
即可霹肝。- 我在這兒用的是“命令”(command)這個(gè)詞塑煎,不過(guò)最铁,它也叫“函數(shù)”(function)或者“方法”(method)垮兑。你會(huì)在本書(shū)后面學(xué)到 functions 和 methods系枪。
- 把第 10-15 行刪掉(或者用別的方法使其失效)然后再運(yùn)行腳本磕谅。
- 只用 input 來(lái)試試運(yùn)行這個(gè)腳本膊夹。為什么要獲取文件名的話(huà)一種方法比另一種方法更好?
- 開(kāi)啟 python3.6 shell工秩,然后就像這個(gè)程序中一樣從提示界面用
open
拓诸。注意你是如何從 python3.6 里面打開(kāi)文件并運(yùn)行read
的麻昼?- 在你的腳本中對(duì)
txt
調(diào)用close()
以及txt_again
變量抚芦。當(dāng)你對(duì)它們完成操作后關(guān)掉文件是非常重要的迈螟。
常見(jiàn)問(wèn)題
txt = open(filename)
會(huì)返回文件的內(nèi)容嗎答毫? 不會(huì)。它其實(shí)是創(chuàng)建了一個(gè)叫做“文件對(duì)象”(file object)的東西消返。你可以把它想象成曾經(jīng)的 DVD 播放器撵颊,你可以在里面移動(dòng)然后“讀取”它們惫叛。但是 DVD 播放器不是 DVD 本身嘉涌,就像文件對(duì)象也不是文件本身一樣夸浅。
我無(wú)法像你附加練習(xí) 7 中說(shuō)的那樣在 Terminal/PowerShell 里輸入代碼题篷。 首先厅目,在命令行輸入 python3.6
然后敲回車(chē)。現(xiàn)在你已經(jīng)在 python3.6 里面了葫笼。然后你可以輸入代碼路星,python 就會(huì)運(yùn)行一些诱桂。試著這樣玩玩挥等,然后輸入 quit()
并回車(chē),退出迁客。
為什么打開(kāi)文件兩次不會(huì)收到報(bào)錯(cuò)掷漱?
Python 不會(huì)限制你只能打開(kāi)一次文件榄檬,事實(shí)上有時(shí)候確實(shí)需要打開(kāi)多次。
from sys import argv
是什么意思鹿榜?現(xiàn)在你只需要明白 sys
是一個(gè)包(package)海雪,這個(gè)短語(yǔ)是說(shuō)從那個(gè)包里獲取 argv
功能(feature)。你會(huì)在后面深入學(xué)習(xí)這塊內(nèi)容犬缨。
我把腳本文件名這樣放進(jìn)去:ex15_sample.txt = argv
, 但是無(wú)法運(yùn)行喳魏。 你不能這樣做。嚴(yán)格按照我的代碼來(lái)怀薛,然后用同樣的方法在命令行運(yùn)行它刺彩。你不用把文件名放進(jìn)去,你得讓 python 自己放。