
在使用數(shù)學(xué)知識(shí)畫(huà)出很酷的各種圖形之前,你需要先學(xué)習(xí)Python編程語(yǔ)言的基礎(chǔ)知識(shí)。本文將會(huì)帶你熟悉以下編程概念:循環(huán)、變量、函數(shù)、使用小龜模塊繪制圖像。本文假設(shè)你已經(jīng)安裝了Python,如果沒(méi)有,歡迎你訪問(wèn)我在B站的視頻課程,你可以在編程入門—使用python語(yǔ)言開(kāi)發(fā)游戲課程中學(xué)習(xí)下載Python并安裝以及Python的基礎(chǔ)操作。本文是在Python編程中發(fā)現(xiàn)數(shù)學(xué)之美的第一章內(nèi)容,視頻內(nèi)容在這兒,其余內(nèi)容會(huì)陸續(xù)發(fā)布在我的B站專欄中,歡迎關(guān)注。
小龜模塊
Python的小龜模塊來(lái)源于Logo語(yǔ)言。Logo語(yǔ)言發(fā)明于1960年代,目的是使所有人都能夠?qū)W習(xí)編程。Logo語(yǔ)言有可供人機(jī)交互的圖形界面。Python的設(shè)計(jì)者對(duì)Logo語(yǔ)言的小龜模塊如此喜歡,以至于他們也在Python中設(shè)計(jì)了小龜模塊。
在Python的小龜模塊中,你可以控制類似小龜?shù)膱D像,像在游戲中控制一個(gè)角色。你需要給小龜清晰明確的指令,指導(dǎo)小龜在屏幕上的動(dòng)作。因?yàn)樾↓數(shù)倪\(yùn)動(dòng)會(huì)留下軌跡,我們可以通過(guò)控制小龜運(yùn)動(dòng)畫(huà)出各種圖形。
導(dǎo)入小龜模塊
打開(kāi)IDLE,新建文件,保存為myturtle.py。使用小龜模塊,你需要首先引入它的函數(shù)。在Python中,函數(shù)是指完成某一功能的可重復(fù)使用的一段代碼。Python中有許多內(nèi)置函數(shù),當(dāng)然你也可以創(chuàng)建自己的函數(shù),我們稱之為自定義函數(shù)。本章中你就將寫(xiě)自己的自定義函數(shù)。
模塊在Python中指一個(gè)文件,這個(gè)文件中含有預(yù)定義的函數(shù)和定義,這些函數(shù)和定義你可以在其他程序中使用。小龜模塊在你安裝Python的時(shí)候已經(jīng)自動(dòng)安裝了。
Python中引入模塊的方法有許多,我們使用簡(jiǎn)單的一種,在myturtle.py中,輸入以下語(yǔ)句:
from turtle import *
from表示我們將從外部的文件中導(dǎo)入某些內(nèi)容。我們?cè)?code>from后輸入要導(dǎo)入的模塊,這里是turtle。我們用import獲取欲導(dǎo)入的內(nèi)容,這里的通配符*表示我們將turtle的內(nèi)容全部引入到當(dāng)前的程序。
移動(dòng)小龜
現(xiàn)在你已經(jīng)引入了小龜模塊,你可以輸入指令輸入指令移動(dòng)小龜了。我們將使用foreward()函數(shù)(縮寫(xiě)為fd)來(lái)命令小龜移動(dòng)一段距離并在后面留下軌跡。注意,forward()是我們從turtle小龜模塊中引入函數(shù)中的其中一個(gè)。使小龜移動(dòng):
foreward(100)
這里,括號(hào)中的100表示小龜移動(dòng)的步數(shù)。在編程語(yǔ)言中,100是傳遞給foreward函數(shù)的參數(shù)。當(dāng)然,你也可以將100改成其它任何值。保存,運(yùn)行程序,一個(gè)新窗口會(huì)打開(kāi),窗口中心有一個(gè)箭頭。
正如你所見(jiàn),小龜起點(diǎn)為窗口正中,向右移動(dòng)了100步(100個(gè)像素)。注意,默認(rèn)的形狀是一個(gè)箭頭,不是烏龜。輸入以下指令變?yōu)闉觚數(shù)男螤睿?/p>
from turtle import *
forward(100)
shape('turtle')
或許你已經(jīng)猜到了,shape()是小龜模塊中定義的另一個(gè)函數(shù)。這個(gè)函數(shù)讓你可以定義默認(rèn)的箭頭為其他形狀,如圓、方塊。這里,shape()函數(shù)的參數(shù)是字符串'turtle',不是數(shù)字。保存并運(yùn)行,你會(huì)看到箭頭的形狀已經(jīng)變成了小龜。
改變方向
小龜只能在它的方向上向前走。改變方向,你首先必須使用right()或left()函數(shù)讓小龜轉(zhuǎn)一定的角度。修改程序如下:
from turtle import *
forward(100)
shape('turtle')
right(45)
forward(150)
你會(huì)發(fā)現(xiàn),小龜從窗口中心開(kāi)始,向前走100步,右轉(zhuǎn)45度,然后向前走了150步。
練習(xí)1-1:修改代碼,使小龜?shù)能壽E畫(huà)一個(gè)正方形。
循環(huán)執(zhí)行代碼
每一種編程語(yǔ)言都有自動(dòng)重復(fù)執(zhí)行一定次數(shù)的方法。這個(gè)功能很重要,因?yàn)橹貜?fù)執(zhí)行避免了你一遍又一遍輸入相同內(nèi)容代碼的麻煩。它還可以幫你避免輸入錯(cuò)誤,從而保證程序正常運(yùn)行。
for循環(huán)
Python語(yǔ)言中使用for執(zhí)行循環(huán)代碼。我們用range指明循環(huán)次數(shù)。打開(kāi)IDLE,新建文件for_loop.py,輸入:
for i in range(2):
print('hello')
這里,range()函數(shù)為每一個(gè)循環(huán)i創(chuàng)建了一個(gè)迭代器。迭代器每次使用會(huì)依順序產(chǎn)生新值。括號(hào)中的2是傳遞給range()函數(shù)的參數(shù),與前面?zhèn)鬟f給forward()和right()參數(shù)類似。
這個(gè)例子中,range(2)創(chuàng)建了一個(gè)包括兩個(gè)值:0和1的序列。對(duì)兩個(gè)值中的每一個(gè),for分別執(zhí)行冒號(hào)之后的代碼,在這兒是執(zhí)行打印hello。
記住,在所有需要循環(huán)執(zhí)行的代碼(冒號(hào)之后的)前按TAB鍵(或4個(gè)空格),以使這些代碼有相同的縮進(jìn)??s進(jìn)告訴Python哪些代碼行在循環(huán)內(nèi)容需要for循環(huán)執(zhí)行。別忘了for語(yǔ)句最后的冒號(hào),它告訴Python下面的代碼是需要循環(huán)執(zhí)行的。保存、運(yùn)行以上代碼,你會(huì)看到輸出兩行hello。
打印兩行hello是因?yàn)?code>range(2)創(chuàng)建了包含兩個(gè)數(shù)字0和1的序列。這表示for指令逐個(gè)訪問(wèn)序列中的0和1,每次訪問(wèn)打印hello。我們可以對(duì)代碼做如下修改:
for i in range(10):
print(i)
保存并運(yùn)行,結(jié)果是打印了從0到9的10個(gè)數(shù)字。
你注意到了嗎?range()函數(shù)的序列是從0開(kāi)始,到參數(shù)的前一個(gè)數(shù)字結(jié)束(這里是9)。上面的代碼的作用可簡(jiǎn)述為“對(duì)從0到9范圍中的每一個(gè)值,打印當(dāng)前的數(shù)字?!?code>for循環(huán)重復(fù)執(zhí)行代碼,直到超出數(shù)字范圍。下面我們?cè)谛↓敵绦蛑惺褂?code>for循環(huán)。
使用for循環(huán)畫(huà)正方形
上面的練習(xí)1-1中,你面臨的挑戰(zhàn)是使用forward()和right()畫(huà)正方形。完成這個(gè)任務(wù),你不得不重復(fù)forward(100)和right(90)四次。這不但需要輸入許多代碼,而且輸入過(guò)程中還往往出錯(cuò)。
現(xiàn)在我們有了for循環(huán),就可以省去重復(fù)輸入相同代碼的麻煩了。下面的myturtle.py程序,使用for代替了重復(fù)的forward()和right()語(yǔ)句:
from turtle import *
shape('turtle')
for i in range(4):
forward(100)
right(90)
注意,shape('turtle')語(yǔ)句應(yīng)該在import語(yǔ)句后面其他繪畫(huà)代碼的前面。for循環(huán)內(nèi)部的兩行代碼告訴小龜,向前100步然后右轉(zhuǎn)90度(想想對(duì)小龜來(lái)說(shuō)哪邊是左哪邊是右)。由于正方形有四條邊,我們使用range(4)讓代碼循環(huán)四次,運(yùn)行代碼的結(jié)果會(huì)如下面的圖片:

小龜向前100步然后右轉(zhuǎn),重復(fù)了四次,最終回到原來(lái)出發(fā)的點(diǎn)。恭喜你,你使用for循環(huán)畫(huà)出了正方形。
創(chuàng)建自定義函數(shù)
我們寫(xiě)了畫(huà)正方形的代碼,我們可以使用個(gè)小魔術(shù)將代碼保存起來(lái),以后需要畫(huà)正方形的時(shí)候隨時(shí)調(diào)用。每種變成語(yǔ)言都有實(shí)現(xiàn)這個(gè)功能的方法,在Python里它被成為函數(shù),函數(shù)在編程中非常重要。函數(shù)使代碼精巧并易于維護(hù)修改,將復(fù)雜問(wèn)題化解為若干函數(shù)的過(guò)程中,也有助于你找到解決問(wèn)題的最佳方法。在前面的代碼中你已經(jīng)使用過(guò)Python語(yǔ)言內(nèi)置的函數(shù),現(xiàn)在我們將學(xué)習(xí)怎么創(chuàng)建我們自己的函數(shù)。
定義函數(shù)你需要為它取個(gè)名字,可以取任何名字,記住不要與Python語(yǔ)言的關(guān)鍵字相同,如list,range,等等。為函數(shù)命名的時(shí)候,最后取個(gè)有意義的名字,這樣你調(diào)用的時(shí)候能夠方便的想起來(lái)。這里我們?yōu)槲覀儺?huà)正方向的函數(shù)命名為square(),因?yàn)槲覀冞@個(gè)函數(shù)的作用是畫(huà)正方形,修改剛才的程序mytutle.py,增加下面內(nèi)容:
def square():
for i in range(4):
forward(100)
right(90)
def關(guān)鍵字告訴Python我們正定義一個(gè)函數(shù),后面的將會(huì)是函數(shù)名字,這兒是square()。別忘了square后面的兩個(gè)括號(hào)!Python中它們的出現(xiàn)表示現(xiàn)在要處理的是函數(shù)。后面我們將在括號(hào)中放數(shù)值,但即使沒(méi)有任何數(shù)值,括號(hào)也必須要有以讓Python知道這是個(gè)函數(shù)。另外,不要忘記函數(shù)定義語(yǔ)句末尾的冒號(hào)。注意,函數(shù)內(nèi)容部分的代碼都有向右4個(gè)空格的縮進(jìn),這是告訴Python哪些代碼是函數(shù)內(nèi)部的語(yǔ)句。
如果現(xiàn)在運(yùn)行,什么也不會(huì)出現(xiàn)。你定義了函數(shù),但還沒(méi)有運(yùn)行它。要運(yùn)行函數(shù)你需要調(diào)用它,對(duì)代碼繼續(xù)修改,修改后的代碼如下:
from turtle import *
shape('turtle')
def square():
for i in range(4):
forward(100)
right(90)
square()
保存,運(yùn)行。程序的最后一行,通過(guò)square()調(diào)用了函數(shù)?,F(xiàn)在你可以在程序任何位置調(diào)用square()函數(shù)來(lái)方便地繪制四方形了。
你還可以將這個(gè)函數(shù)放在循環(huán)中,來(lái)繪出更復(fù)雜的圖形。例如,畫(huà)一個(gè)正方形,右轉(zhuǎn)一定角度,畫(huà)另一個(gè)正方形,繼續(xù)右轉(zhuǎn)...這樣循環(huán)若干次。
下面的練習(xí)將繪制一個(gè)由正方形組成的有趣的圖形。要畫(huà)出這個(gè)圖形,需要你的小龜忙活一會(huì)兒,所以你可以通過(guò)調(diào)用speed()函數(shù)控制小龜?shù)乃俣取T?code>shape('turtule')語(yǔ)句后面插入一行speed(0),使小龜移動(dòng)的速度達(dá)到最快(speed(1)使小龜速度最慢)。當(dāng)然你可以調(diào)整speed()的參數(shù)。
練習(xí)1-2:正方形組成的圓。寫(xiě)程序,這個(gè)程序?qū)?huà)60個(gè)正方形,每畫(huà)一個(gè)正方形后右轉(zhuǎn)5度。程序中要使用循環(huán)語(yǔ)句。運(yùn)行結(jié)果如圖:circle of squares
使用變量繪制圖形
現(xiàn)在為止我們的正方形大小都相同。想要不同大小的正方形,要改變小龜前進(jìn)的距離。要通過(guò)每次修改函數(shù)獲得不同的距離,那太麻煩了。我們用變量來(lái)解決這個(gè)問(wèn)題,變量在Python中表示可以改變的值。變量與數(shù)學(xué)函數(shù)表達(dá)式中的x相似。
數(shù)學(xué)中的變量名字是一個(gè)字母,編程中你可以給變量取任何名字。類似與函數(shù),我建議你的變量名稱應(yīng)該是有意義的,便于記憶和理解。
函數(shù)中使用變量
定義函數(shù)的時(shí)候,可以將變量作為傳遞給函數(shù)的參數(shù)。例如,可以修改square()的定義,來(lái)畫(huà)不同尺寸的正方形,對(duì)myturtle.py修改如下:
def square(sidelength):
for i in range(4):
forward(sidelength)
right(90)
這里我們?cè)诤瘮?shù)定義中增加了sidelength。現(xiàn)在你調(diào)用這個(gè)函數(shù)的時(shí)候,要在括號(hào)間傳遞一個(gè)值給函數(shù),這個(gè)值我們稱之為參數(shù)。傳遞的任何值都將作為sidelength的數(shù)值。例如,調(diào)用square(50)和square(80)將分別繪制邊長(zhǎng)為50和80的正方形。
變量錯(cuò)誤
調(diào)用函數(shù)的時(shí)候,如果函數(shù)定義中有參數(shù),而調(diào)用時(shí)未指明參數(shù),Python會(huì)報(bào)錯(cuò)。如調(diào)用上面的函數(shù)square(),IDLE中會(huì)出現(xiàn)以下錯(cuò)誤提示:
TypeError: square() missing 1 required positional argument: 'sidelength'
這個(gè)錯(cuò)誤提示我們?nèi)鄙倭艘粋€(gè)需要的參數(shù)(這兒是sidelength)。怎樣避免出現(xiàn)這種錯(cuò)誤呢?我們可以在定義函數(shù)時(shí)給參數(shù)賦一個(gè)默認(rèn)值,例如這樣:
def square(sidelength=100):
這里,我們給sidelength賦值100。現(xiàn)在我們調(diào)用square時(shí)如果填寫(xiě)了參數(shù),會(huì)繪制邊長(zhǎng)為我們填寫(xiě)數(shù)值的正方形,如果我們沒(méi)有填寫(xiě),也不會(huì)報(bào)錯(cuò),會(huì)繪制邊長(zhǎng)為100的正方形。我們可以這樣調(diào)用函數(shù):
square(30)
square(50)
squre()
運(yùn)行結(jié)果會(huì)是這樣:

給函數(shù)參數(shù)設(shè)置缺省值,我們可以不同擔(dān)心調(diào)用時(shí)忘記填寫(xiě)參數(shù)了。在編程中,我們稱之為讓程序變得健壯。
練習(xí)1-3:繪制三角形。寫(xiě)
triangle()函數(shù),函數(shù)功能為繪制給定變長(zhǎng)的三角形。
等邊三角形
多邊形是有多個(gè)邊的圖形。等邊三角形是多邊形的一種,有三條邊且變長(zhǎng)相等。

等邊三角形有3個(gè)都為60度的內(nèi)角,你的數(shù)學(xué)老師肯定告訴過(guò)你,三角形內(nèi)角和為180度。
寫(xiě)繪制三角形的函數(shù)
現(xiàn)在,讓我們用目前學(xué)到的知識(shí)畫(huà)出一個(gè)等邊三角形。因?yàn)槊總€(gè)內(nèi)角都是60度,我們可以將right()參數(shù)修改為60度,像下面這樣修改myturtle.py:
def triangle(sidelength=100):
for i in range(3):
forward(sidelength)
right(60)
triangle()
保存,運(yùn)行。你看到了什么?

我們沒(méi)看到三角形,看起來(lái)畫(huà)的好像是六邊形的一半。想想為什么?如果你是圖上的小龜,站在它的位置,向右轉(zhuǎn)60度,循環(huán)3次……是不是也會(huì)走出上圖的路徑。你應(yīng)該想到了,向右轉(zhuǎn),不應(yīng)該轉(zhuǎn)60度,而應(yīng)該轉(zhuǎn)180-60=120度。
練習(xí)1-4:寫(xiě)繪制多邊形的函數(shù)。函數(shù)名字為
polygon,參數(shù)為一個(gè)整數(shù),函數(shù)功能是繪制多邊形,邊的條數(shù)為參數(shù)值。
改變變量的值
我們可以這樣改變變量的值:在每一個(gè)循環(huán)中讓變量的值遞增,結(jié)果是每次循環(huán)所畫(huà)的正方形比上一次大一些。例如我們使用length變量,我們用這個(gè)變量的值作為變長(zhǎng)畫(huà)正方形,下一個(gè)循環(huán)中為length增加5:
length = length + 5
這是一個(gè)賦值語(yǔ)句,length變量被賦予length原來(lái)的值加上5。打開(kāi)IDLE,輸入以下語(yǔ)句:
>>> radius = 10
上面我們創(chuàng)建了一個(gè)變量,其名字是radius,其值為10。任何時(shí)候你都可以重新給這個(gè)變量賦一個(gè)新值:
>>> radius = 20
現(xiàn)在,變量radius中的值為20了。
練習(xí)1-5:創(chuàng)建一個(gè)函數(shù),函數(shù)的功能為畫(huà)60個(gè)正方形,每畫(huà)一個(gè)正方形后旋轉(zhuǎn)5度,且邊長(zhǎng)增加。初始邊長(zhǎng)為5,每次增加5。結(jié)果應(yīng)該如圖所示:
總結(jié)
本文我們學(xué)習(xí)了使用Python的小龜模塊turtle和它的內(nèi)置函數(shù)forward()及right()。我們探索了使用這個(gè)兩個(gè)函數(shù)繪制復(fù)雜有趣的圖形。turtle是Python其中一個(gè)包,你可以訪問(wèn)Python的官方網(wǎng)站https://python.org/,上面有turtle更全面的介紹。
本文我們還學(xué)校了如何定義自己的函數(shù),自定義函數(shù)可以讓我們實(shí)現(xiàn)代碼復(fù)用。我們還學(xué)習(xí)了for循環(huán)。
練習(xí)1-6:星星的誕生。首先你要寫(xiě)一個(gè)名為
star的函數(shù),函數(shù)功能是繪制一個(gè)五角星,如圖:star
,接下來(lái),你需要寫(xiě)另一個(gè)starSpiral()函數(shù),函數(shù)的作用是繪制旋轉(zhuǎn)的五角星,結(jié)果如下圖:
stars spiral
我的博客即將同步至騰訊云+社區(qū),邀請(qǐng)大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1u784oq3iz7tj



