鍍金池/ 教程/ Python/ 函數(shù)練習(xí)
標(biāo)準(zhǔn)庫(kù) (4)
如何成為 Python 高手
標(biāo)準(zhǔn)庫(kù) (6)
標(biāo)準(zhǔn)庫(kù) (3)
類(lèi)(2)
Pandas 使用 (2)
xml
用 tornado 做網(wǎng)站 (5)
文件(1)
練習(xí)
列表(3)
從小工到專(zhuān)家
除法
錯(cuò)誤和異常 (2)
函數(shù)(1)
用 tornado 做網(wǎng)站 (7)
為做網(wǎng)站而準(zhǔn)備
函數(shù)練習(xí)
標(biāo)準(zhǔn)庫(kù) (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網(wǎng)站 (3)
字符串(1)
函數(shù)(2)
寫(xiě)一個(gè)簡(jiǎn)單的程序
將數(shù)據(jù)存入文件
語(yǔ)句(5)
SQLite 數(shù)據(jù)庫(kù)
集成開(kāi)發(fā)環(huán)境(IDE)
集合(1)
類(lèi)(1)
用 tornado 做網(wǎng)站 (6)
用 tornado 做網(wǎng)站 (2)
自省
語(yǔ)句(4)
錯(cuò)誤和異常 (1)
用 tornado 做網(wǎng)站 (4)
集合(2)
列表(1)
標(biāo)準(zhǔn)庫(kù) (1)
生成器
mysql 數(shù)據(jù)庫(kù) (1)
第三方庫(kù)
實(shí)戰(zhàn)
運(yùn)算符
類(lèi)(3)
字典(2)
語(yǔ)句(1)
數(shù)和四則運(yùn)算
語(yǔ)句(2)
文件(2)
MySQL 數(shù)據(jù)庫(kù) (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫(kù) (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫(xiě)模塊
用 tornado 做網(wǎng)站 (1)
標(biāo)準(zhǔn)庫(kù) (5)
函數(shù)(4)
類(lèi)(5)
字符串(2)
關(guān)于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學(xué)函數(shù)和運(yùn)算優(yōu)先級(jí)
字符串(3)
為計(jì)算做準(zhǔn)備
多態(tài)和封裝
類(lèi)(4)
迭代
語(yǔ)句(3)
錯(cuò)誤和異常 (3)
分析 Hello
Python 安裝
標(biāo)準(zhǔn)庫(kù) (2)
列表(2)
元組

函數(shù)練習(xí)

已經(jīng)學(xué)習(xí)了函數(shù)的基本知識(shí),現(xiàn)在練習(xí)練習(xí)。完成下面練習(xí)的原則:

  1. 請(qǐng)讀者先根據(jù)自己的設(shè)想寫(xiě)下代碼,然后運(yùn)行調(diào)試,檢查得到的結(jié)果是否正確
  2. 我也給出參考代碼,但是,參考代碼并不是最終結(jié)果
  3. 讀者可以在上述基礎(chǔ)上對(duì)代碼進(jìn)行完善
  4. 如果讀者愿意,可以將代碼提交到 github 上,或者到我的 QQ 群(群號(hào):26913719)中跟大家分享討論

解一元二次方程

解一元二次方程,是初中數(shù)學(xué)中的基本知識(shí),一般來(lái)講解法有:公式法、因式分解法等。讀者可以根據(jù)自己的理解,寫(xiě)一段求解一元二次方程的程序。

最簡(jiǎn)單的思路就是用公式法求解,這是普適法則(普世法則?普適是否等同于普世?)。

古巴比倫留下的陶片顯示,在大約公元前 2000 年(2000 BC)古巴比倫的數(shù)學(xué)家就能解一元二次方程了。在大約公元前 480 年,中國(guó)人已經(jīng)使用配方法求得了二次方程的正根,但是并沒(méi)有提出通用的求解方法。公元前 300 年左右,歐幾里得提出了一種更抽象的幾何方法求解二次方程。

7 世紀(jì)印度的婆羅摩笈多(Brahmagupta)是第一位懂得用使用代數(shù)方程,它同時(shí)容許有正負(fù)數(shù)的根。

11 世紀(jì)阿拉伯的花拉子密 獨(dú)立地發(fā)展了一套公式以求方程的正數(shù)解。亞伯拉罕·巴希亞(亦以拉丁文名字薩瓦索達(dá)著稱(chēng))在他的著作 Liber embadorum 中,首次將完整的一元二次方程解法傳入歐洲。(源自《維基百科》)

參考代碼:

#!/usr/bin/env Python
# coding=utf-8

"""
solving a quadratic equation
"""

from __future__ import division
import math

def quadratic_equation(a,b,c):
    delta = b*b - 4*a*c
    if delta<0:
        return False
    elif delta==0:
        return -(b/(2*a))
    else:
        sqrt_delta = math.sqrt(delta)
        x1 = (-b + sqrt_delta)/(2*a)
        x2 = (-b - sqrt_delta)/(2*a)
        return x1, x2

if __name__ == "__main__":
    print "a quadratic equation: x^2 + 2x + 1 = 0"
    coefficients = (1, 2, 1)
    roots = quadratic_equation(*coefficients)
    if roots:
        print "the result is:",roots
    else:
        print "this equation has no solution."

保存為 20501.py,并運(yùn)行之:

$ python 20501.py 
a quadratic equation: x^2 + 2x + 1 = 0
the result is: -1.0

能夠正常運(yùn)行,求解方程。

但是,如果再認(rèn)真思考,發(fā)現(xiàn)上述代碼是有很大改進(jìn)空間的。至少我發(fā)現(xiàn):

  • 如果不小心將第一個(gè)系數(shù)(a)的值輸入了 0,程序肯定會(huì)報(bào)錯(cuò)。如何避免之?要記住,任何人的輸入都是不可靠的。
  • 結(jié)果貌似只能是小數(shù),這在某些情況下是近似值,能不能得到以分?jǐn)?shù)形式表示的精確結(jié)果呢?
  • 復(fù)數(shù),Python 是可以表示復(fù)數(shù)的,如果 delta<0,是不是寫(xiě)成復(fù)數(shù)更好,畢竟我是學(xué)過(guò)高中數(shù)學(xué)的。

讀者是否還有其它改進(jìn)呢?你能不能進(jìn)行改進(jìn),然后跟我和其他朋友一起來(lái)分享你的成就呢?

至少要完成上述改進(jìn),可能需要其它的有關(guān) Python 知識(shí),甚至于前面沒(méi)有介紹。這都不要緊,掌握了基本知識(shí)之后,在編程的過(guò)程中,就要不斷發(fā)揮 google 的優(yōu)勢(shì),讓她幫助你找尋完成任務(wù)的工具。

Python 是一個(gè)開(kāi)發(fā)的語(yǔ)言,很多大牛人都寫(xiě)了一些工具,讓別人使用,減輕了后人的勞動(dòng)負(fù)擔(dān)。這就是所謂的第三方模塊。雖然 Python 中已經(jīng)有一些“自帶電池”,即默認(rèn)安裝的,比如上面程序中用到的 math,但是我們還嫌不夠。于是又很多第三方的模塊來(lái)專(zhuān)門(mén)解決某個(gè)問(wèn)題。比如這個(gè)解方程問(wèn)題,就可以使用 SymPy(www.sympy.org)來(lái)解決,當(dāng)然 NumPy 也是非常強(qiáng)悍的工具。

統(tǒng)計(jì)考試成績(jī)

每次考試之后,教師都要統(tǒng)計(jì)考試成績(jī),一般包括:平均分,對(duì)所有人按成績(jī)從高到低排隊(duì),誰(shuí)成績(jī)最好,誰(shuí)成績(jī)最差。還有其它的統(tǒng)計(jì)項(xiàng),暫且不做了。只統(tǒng)計(jì)這幾項(xiàng)吧。下面的任務(wù)就是讀者轉(zhuǎn)動(dòng)腦筋,思考如何用程序?qū)崿F(xiàn)上面的統(tǒng)計(jì)。為了簡(jiǎn)化,以字典形式表示考試成績(jī)記錄,例如:{"zhangsan":90, "lisi":78, "wangermazi":39},當(dāng)然,也許不止這三項(xiàng),可能還有,每個(gè)老師所處理的內(nèi)容稍有不同,因此字典里的鍵值對(duì)也不一樣。

怎么做?

有幾種可能要考慮到:

  • 最高分或者最低分,可能有人并列。
  • 要實(shí)現(xiàn)不同長(zhǎng)度的字典作為輸入值。
  • 輸出結(jié)果中,除了平均分,其它的都要有姓名和分?jǐn)?shù)兩項(xiàng),否則都匿名了,怎么刺激學(xué)渣,表?yè)P(yáng)學(xué)霸呢?

不管你是學(xué)渣還是學(xué)霸,都能學(xué)好 Python。請(qǐng)思考后敲代碼調(diào)試你的程序,調(diào)試之后再閱讀下文。

參考代碼:

#!/usr/bin/env Python
# coding=utf-8
"""
統(tǒng)計(jì)考試成績(jī)
"""
from __future__ import division

def average_score(scores):
    """
    統(tǒng)計(jì)平均分.
    """
    score_values = scores.values()
    sum_scores = sum(score_values)
    average = sum_scores/len(score_values)
    return average

def sorted_score(scores):
    """
    對(duì)成績(jī)從高到低排隊(duì).
    """
    score_lst = [(scores[k],k) for k in scores]
    sort_lst = sorted(score_lst, reverse=True)
    return [(i[1], i[0]) for i in sort_lst]

def max_score(scores):
    """
    成績(jī)最高的姓名和分?jǐn)?shù).
    """
    lst = sorted_score(scores)    #引用分?jǐn)?shù)排序的函數(shù) sorted_score
    max_score = lst[0][1]
    return [(i[0],i[1]) for i in lst if i[1]==max_score]

def min_score(scores):
    """
    成績(jī)最低的姓名和分?jǐn)?shù).
    """
    lst = sorted_score(scores)
    min_score = lst[len(lst)-1][1]
    return [(i[0],i[1]) for i in lst if i[1]==min_score]

if __name__ == "__main__":
    examine_scores = {"google":98, "facebook":99, "baidu":52, "alibaba":80, "yahoo":49, "IBM":70, "android":76, "apple":99, "amazon":99}

    ave = average_score(examine_scores)
    print "the average score is: ",ave    #平均分

    sor = sorted_score(examine_scores)
    print "list of the scores: ",sor      #成績(jī)表

    xueba = max_score(examine_scores)
    print "Xueba is: ",xueba              #學(xué)霸們

    xuezha = min_score(examine_scores)
    print "Xuzha is: ",xuezha             #學(xué)渣們

保存為 20502.py,然后運(yùn)行:

$ python 20502.py
the average score is:  80.2222222222
list of the scores:  [('facebook', 99), ('apple', 99), ('amazon', 99), ('google', 98), ('alibaba', 80), ('android', 76), ('IBM', 70), ('baidu', 52), ('yahoo', 49)]
Xueba is:  [('facebook', 99), ('apple', 99), ('amazon', 99)]
Xuzha is:  [('yahoo', 49)]

貌似結(jié)果還不錯(cuò)。不過(guò),還有改進(jìn)余地,看看現(xiàn)實(shí),就感覺(jué)不怎么友好了。看官能不能優(yōu)化一下?當(dāng)然,里面的函數(shù)也不一定是最好的方法,你也可以修改優(yōu)化。期盼能夠在我上面公布的途徑中交流一二。

找素?cái)?shù)

這是一個(gè)比較常見(jiàn)的題目。我們姑且將范圍縮小一下,找出 100 以?xún)?nèi)的素?cái)?shù)吧。

還是按照前面的管理,讀者先做,然后我提供參考代碼,然后自行優(yōu)化。

質(zhì)數(shù)(Prime number),又稱(chēng)素?cái)?shù),指在大於1的自然數(shù)中,除了 1 和此整數(shù)自身外,無(wú)法被其他自然數(shù)整除的數(shù)(也可定義為只有 1 和本身兩個(gè)因數(shù)的數(shù))。

哥德巴赫猜想是數(shù)論中存在最久的未解問(wèn)題之一。這個(gè)猜想最早出現(xiàn)在 1742 年普魯士人克里斯蒂安·哥德巴赫與瑞士數(shù)學(xué)家萊昂哈德·歐拉的通信中。用現(xiàn)代的數(shù)學(xué)語(yǔ)言,哥德巴赫猜想可以陳述為:“任一大于 2 的偶數(shù),都可表示成兩個(gè)質(zhì)數(shù)之和?!薄8绲掳秃詹孪朐谔岢龊蟮暮荛L(zhǎng)一段時(shí)間內(nèi)毫無(wú)進(jìn)展,直到二十世紀(jì)二十年代,數(shù)學(xué)家從組合數(shù)學(xué)與解析數(shù)論兩方面分別提出了解決的思路,并在其后的半個(gè)世紀(jì)里取得了一系列突破。目前最好的結(jié)果是陳景潤(rùn)在 1973 年發(fā)表的陳氏定理(也被稱(chēng)為“1+2”)。(源自《維基百科》)

對(duì)這個(gè)練習(xí),我的思路是先做一個(gè)函數(shù),用它來(lái)判斷某個(gè)整數(shù)是否是素?cái)?shù)。然后循環(huán)即可。參考代碼:

#!/usr/bin/env Python
# coding=utf-8

"""
尋找素?cái)?shù)
"""

import math

def is_prime(n):
    """
    判斷一個(gè)數(shù)是否是素?cái)?shù)
    """
    if n <= 1:
        return False
    for i in range(2, int(math.sqrt(n) + 1)):
        if n % i == 0:
            return False
    return True

if __name__ == "__main__":
    primes = [i for i in range(2,100) if is_prime(i)]    #從 2 開(kāi)始,因?yàn)?1 顯然不是質(zhì)數(shù)
    print primes

代碼保存后運(yùn)行:

$ python 20503.py 
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

打印出了 100 以?xún)?nèi)的質(zhì)數(shù)。

還是前面的觀點(diǎn),這個(gè)程序你或許也發(fā)現(xiàn)了需要進(jìn)一步優(yōu)化的地方,那就太好了。另外,關(guān)于判斷質(zhì)數(shù)的方法,還有好多種,讀者可以自己創(chuàng)造或者網(wǎng)上搜索一些,拓展思路。

編寫(xiě)函數(shù)的注意事項(xiàng)

編寫(xiě)函數(shù),在開(kāi)發(fā)實(shí)踐中是非常必要和常見(jiàn)的,一般情況,你寫(xiě)的函數(shù)應(yīng)該是:

  1. 盡量不要使用全局變量。
  2. 如果參數(shù)是可變類(lèi)型數(shù)據(jù),在函數(shù)內(nèi),不要修改它。
  3. 每個(gè)函數(shù)的功能和目標(biāo)要單純,不要試圖一個(gè)函數(shù)做很多事情。
  4. 函數(shù)的代碼行數(shù)盡量少。
  5. 函數(shù)的獨(dú)立性越強(qiáng)越好,不要跟其它的外部東西產(chǎn)生關(guān)聯(lián)。

總目錄   |   上節(jié):函數(shù)(4)   |   下節(jié):類(lèi)(1)

如果你認(rèn)為有必要打賞我,請(qǐng)通過(guò)支付寶:qiwsir@126.com,不勝感激。