1. 程式人生 > >python3基礎11

python3基礎11

day11

函數語言程式設計
   是指用一系列函式解決問題
 示例:
   求1 + 2 + 3 + ....+ 100的和
   方法一
   s = 0
   for x in range(1,101):
       s += x
   print(s)
   方法二
   print(sum(range(1,101)))

函式的可重入性:
   當一個函式輸入一定,則輸出必然一定的函式稱為可重入性函式
 說明:
   可重入函式內一定不會訪問區域性變數以外的變數
 示例:

   #可重入函式:(推薦使用)
   def myadd(x,y):
       return x + y
   print(myadd(100, 200))  #300

   #不可重入函式:
   y = 200
   def myadd():
       return x + y
   print(myadd(100))  #300
   y = 300
   print(myadd(100))  #400

高階函式High Order Function
 什麼是高階函式:
   滿足下列條件中的一個的函式即為高階函式
   1.函式接收一個或多個函式作為引數傳入
   2.函式返回一個函式

python內建的高階函式:
  map, filter, sorted

map函式:
  map(func, *iterable) (*iterable為星號元組形參,可儲存多個物件) 
  返回一個可迭代物件,此可迭代物件用函式func對可迭代物件iterable中的每一個元素作為引數計算後得到新的資料

  示例見:
  mymap.py

def power2(x):
    return x ** 2

for x in map(power2,range(1,10)):
    print(x)  #1  4  9  16 ... 81


練習一:
 1.求:1**2 + 2**2 + 3**2 + ... +9**2的和
#程式碼
 #方法一
def sums(n):
    return n**2
s = 0
for n in map(sums,range(1,10)):
    s += n    
print(s)
#方法二
s = 0
for x in map(lambda x: x ** 2,range(1,10)):
    s += x
prnt(s)
#方法三
print(sum(map(lambda x: x ** 2,range(1,10))))
 

 2.求:1**3 + 2**3 + 3**3 + ... +9**3的和

print(sum(map(lambda x: x ** 3,range(1,10))))


  示例2見:
  mymap2.py


def mypow(x, y):
    return x ** y

for i in map(mypow,[1,2,3,4],(4,3,2,1)):
    print(i)

#程式碼
練習二:
  求1**9 + 2 ** 8 + 3**7 + ... + 9**1的和

# 方法一
def mypow(x, y):
    return x ** y
s = 0
for x in map(mypow,range(1,10),range(9,0,-1)):
    s += x
print(s)

# 方法二
s = 0
for n in map(lambda x, y:x ** y,range(1,10),range(9,0,-1)):
    s += n
print(s)

#方法三
print(sum(map(pow,range(1,10),range(9,0,-1))))


filter函式:
  filter(function,iterable)
  作用:
    篩選可迭代物件iterable中的資料,返回一個可迭代物件,此可迭代物件只返回iterable中符合條件的資料
    function將對iterable中提供的每一個數據進行求布林值,如果為True則保留,返回False則丟棄此資料
  示例見:
    myfilter.py

def isadd(x):
    return x % 2 == 1
for x in filter(isadd,range(10)):
    print(x)

L = list(filter(isadd,range(10)))
print("L=",L)

練習三:
1.將1~20的偶數用filter生成可迭代物件後,將可迭代物件生成的資料存於列表中
  最終結果:
  L = [2,4,6,8,10.....18,20]
#程式碼
#方法一
def ou(n):
    return n % 2 == 0
L = list(filter(ou,range(2,21)))
print(L)
#方法二
def ou(n):
    if n % 2 == 0:
        return True
    return False
L = list(filter(ou,range(2,21)))
print(L)
#方法三
L = list(filter(lambda n: n%2==0,range(2,21)))

print(L)

2.用filter函式將1~100之間所有的素數放入到列表L中
  print(L)   #[2,3,5,7....]

def sushu(n):
    if n < 2:
        return False
    for b in range(2,n):
        if n % b == 0:
            return False       
    return True

L = list(filter(sushu,range(100)))
print(L)


sorted函式
  作用:
   將原可迭代物件的資料進行排序,生成排序後的列表
  函式參照格式:
   sorted(interable,key=None,reverse=False)
  說明;
   interable 可迭代物件
   key 
   函式是用來提供一個值,這個值作為排序的依據,如果不給出key函式,則用原資料的值進行排序和比較
   reverse標誌用來設定是否降序排列
  示例:
   L = [5, -2, -4, 0, 3, 1]
   L2 = sorted(L)                #[-4, -2, 0, 1, 3, 5]
   L3 = sorted(L,reverse=True)   #[5, 3, 1, 0, -2, -4]
   L4 = sorted(L,key=abs,reverse=False)      
   #[0, 1, -2, 3, -4, 5]按絕對值排序
   L5 = sorted(L,key=abs,reverse=True) 
   #[5, -4, 3, -2, 1, 0]

   names = ['Tom', 'Jerry', 'Spike', 'Tyke']
   L6 = sorted(names)
   #['Jerry', 'Spike', 'Tom', 'Tyke']
   L7 = sorted(names, key=len)
   #['Tom', 'Tyke', 'Jerry', 'Spike']


練習四:
  names = ['Tom', 'Jerry', 'Spike', 'Tyke']
  排序依據是字串的反序
  'moT' 'yrreJ'  'ekipS' 'ekyT'
  結果:
    ['Spike','Tyke','Tom','Spike']

#方法一:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
S = []
for i in range(len(names)):
    S.append(names[i][::-1])
    L = sorted(S)
N = []
for x in range(len(L)):
    N.append(L[x][::-1])
print(N)

#方法二:
names = ['Tom', 'Jerry', 'Spike', 'Tyke']
def k(s):
    return s[::-1]

L = sorted(names,key=k)
print(L)

遞迴函式 recurison
  遞迴是指 函式直接或間接呼叫自身

 遞迴示例:
 #函式直接呼叫自身
 def f():
     f()    #直接呼叫自身
 f()
 print("遞迴完成")

 #函式間接呼叫自身
 def fa():
     fb()
 def fb():
     fa()
 fa()
 print("遞迴完成")


遞迴說明:
   遞迴一定要控制遞迴的層數,當符合某一條件時要終止遞迴呼叫,幾乎所有的遞迴都能用while迴圈來代替

遞迴的優缺點:
 優點:
   可以把問題簡單化,讓思路理會清晰,程式碼更簡潔
 缺點:
   遞迴因系統環境影響大,當遞迴深度太大時,可能會得不到預知的結果

遞迴呼叫分為兩個階段:L
 遞推階段:
  從原問題出發,按遞迴公式遞推,從未知到已知,最終達到遞迴終止條件
 迴歸階段:
  按遞迴終止條件得出結果,逆向逐步帶入遞迴公式,迴歸到原問題的求解

示例:
 限制遞迴層數的示例見:
 recurison2.py

def fx(n):
    print("遞迴進入第",n,'層')

    if n == 3:
        return

    fx(n+1)    
    print("遞迴退出第",n,'層')


fx(1) #呼叫

print("程式結束")

#結果:
# 遞迴進入第 1 層
# 遞迴進入第 2 層
# 遞迴進入第 3 層
# 遞迴退出第 2 層
# 遞迴退出第 1 層
# 程式結束

遞迴求階乘示例見:
 recurison_factorial.py

def myfac(n):

    #5! = 5 * 4!
    #5! = 5 * 4! * 3!
    #5! = 5 * 4! * 3! * 2!
    #5! = 5 * 4! * 3! * 2! * 1!
    #5! = 5 * 4! * 3! * 2!
    #5! = 5 * 4! * 3!
    #5! = 5 * 4!

    if n == 1:
        return 1
    #如果不是1,則遞推到下一級求解

    return n * myfac(n - 1)

print(myfac(5))
print(myfac(4))


練習五:
 用遞迴實現求和:
  def mysum(n):
      #返回 1+2+3+4+5+...+n的和
  print(mysum(100))

#程式碼
def mysum(n):
    if n == 1:
        return 1
    return n + mysum(n - 1)
print(mysum(100))


閉包 closure
  什麼時閉包
   閉包是指引用了此函式外部變數的函式
   如果一個內嵌函式訪問了外部巢狀函式的變數,則這個內嵌函式就是閉包
  閉包必須滿足的三個條件:
   1.必須有一個內嵌函式
   2.內嵌函式必須引用外部函式中的變數
   3.外部函式返回值必須是內嵌函式
 示例見:
  closure.py

def make_power(y):
    def fn(x):
        return x ** y 
    return fn

pow2 = make_power(2)
print("5的平方是:",pow2(5))


def pow3(x):
    return x**3
pow3 = make_power(3)

print('6的三次方是:',pow3(6))
print('5的三次方是:',pow3(5))

pow10 = make_power(10)

print('2的十次方',pow10(2))


練習六:
已知有五位朋友在一起
 第五個人說他比第四個人大2歲
 第四個人說他比第三個人大2歲
 第三個人說他比第二個人大2歲
 第二個人說他比第一個人大2歲
 第一個人說他十歲

編寫程式:
1.算出第5個人幾歲?
2.算出第3個人幾歲?


def myage(x):
    return (x-1)*2+10
print(myage(3))
print(myage(5))

def myage(x):
    if x == 1:
        return 10
    return myage(x - 1) + 2
print(myage(3))
print(myage(5))        


課後練習:
1.寫程式算出1~20的階乘的和
 1!+2!+3!+4!+.....+20!

#方法一:
def myfac(n):
    if n == 1:
        return 1 
    return n * myfac(n - 1)
# L = []
# for i in range(1,21):
#     L.append(myfac(i))
# print(sum(L))
print(sum(map(myfac,range(1,21))))


#方法二:

def myfac(n):
    s = 1
    for i in range(1,n+1):
        s = s * i
    return s

def sum_factorial(n):
    s = 0
    for i in range(1, n):
        s += myfac(i)
    return s

print(sum_factorial(20)) 
2.已知有列表:
  L = [[3,5,8], 10, [[13,14],15,18],20]
 (1)寫一個函式print_list(lst)打印出所有的數字
    print_list(L)   #3 5 8 10 13.....
 (2)寫一個函式sum_list(lst)返回字列表中所有數字的和
    print(sum_list(L))  #106
  注:
   type(x)函式可以返回一個物件的型別
   如:
    >>>type(20) is int   #True
    >>>type([3, 5, 8]) is list   #True
    >>>type(20) is list   #False
L = [[3,5,8], 10, [[13,14],15,18],20]
def print_list(lst):
    for i in lst:
        if type(i) is int:
            print(i)
        if type(i) is list:
            print_list(i)
print_list(L)

def sum_list(lst):
    s = 0
    for x in lst:
        if type(x) is int:
            s += x
        elif type(x) is list:
            s += sum_list(x)    #求x繫結列表的和
    return s


print("和是:", sum_list(L))

 (3)改寫之前的學生資訊的程式,要求新增四個功能:
 | 5)按學生成績高-低顯示學生資訊 |
 | 6)按學生成績低-高顯示學生資訊 |
 | 7)按學生年齡高-低顯示學生資訊 |
 | 8)按學生年齡低-高顯示學生資訊 |

def input_student(L):
    L = []
    while True:
        a = input("請輸入姓名:")
        if a == '':
            break
        b = int(input("請輸入年齡: "))
        c = int(input("請輸入成績: "))
        d = {}
        d["name"] = a
        d['age'] = b
        d['score'] = c
        L.append(d)
    return L


def get_chinese_char_count(s):
    c = 0
    for i in s:
        if ord(i) > 127:
            count += 1
    return c 


def output_student(L): 
    m = 0
    for i in L:
        j = i["name"]
        m = max(len(j),m)
        count = get_chinese_char_count(j)
    print('+'+'-'*(m-count)+'+'+'-'*m+'+'+'-'*(m+1)+'+')
    print('|'+'name'.center(m)+'|'+'age'.center(m)+'|'+'score'.center(m+1)+'|') 
    print('+'+'-'*(m-count)+'+'+'-'*m+'+'+'-'*(m+1)+'+')
    for i in L:
        j = i["name"]
        p = str(i["age"])
        q = str(i["score"]) 
        print('|'+j.center(m)+'|'+p.center(m)+'|'+q.center((m+1))+'|') 
    print('+'+'-'*(m-count)+'+'+'-'*m+'+'+'-'*(m+1)+'+')


def delete_student(L):
    n = input("請輸入您要刪除資訊學生的名字:")
    print("正在刪除學生資訊")
    for a in L:
        if a["name"] == n:
             L.remove(a)
             print("學生資訊已經刪除")
             break  
    else:
        print("您輸入的姓名不存在")
    return L


def alter_student(L):
    a = input("請輸入您要修改資訊的學生名字:")
    b = input("請輸入您要修改資訊的學生年齡:")
    c = input("請輸入您要修改資訊的學生成績:")
    for m in L:
        if m["name"] != a:
            print("學生不存在") 
        if m["name"] == a:
            m["age"] = b
            m["score"] = c
            print("學生資訊已經修改")
    return L


def score_high_student(L):
    def get_score(d):   #d是字典
        return d['score']
    L2 = sorted(L, key=get_score, reverse=True)
    output_student(L2)


def score_low_student(L):
    def get_score(d):   #d是字典
        return d['score']
    L2 = sorted(L, key=get_score, reverse=False)
    output_student(L2)


def age_high_student(L):
    L2 = sorted(L, key=lambda d:d['age'], reverse=True)
    output_student(L2)


def age_low_student(L):
    L2 = sorted(L, key=lambda d:d['age'])
    output_student(L2)

def operate():
    print("+------------------------------+")
    print("|1)新增學生資訊            |")
    print("|2)顯示學生資訊           |")
    print("|3)刪除學生資訊          |")
    print("|4)修改學生資訊           |")
    print("|5)按學生成績高-低顯示學生資訊 |")
    print("|6)按學生成績低-高顯示學生資訊 |")
    print("|7)按學生年齡高-低顯示學生資訊 |")
    print("|8)按學生年齡低-高顯示學生資訊 |")
    print("|q)退出                        |")
    print("+------------------------------+")


def main():
    L = []
    while True:
        operate()
        x = input("請輸入您的選擇:")
        if x == 'q':
            break
        elif x == '1':
            L += input_student(L)
        elif x == '2':
            output_student(L)
        elif x == '3':
            delete_student(L)
        elif x == '4':
            alter_student(L)
        elif x == '5':
            score_high_student(L)
        elif x == '6':
            score_low_student(L)
        elif x == '7':
            age_high_student(L)
        elif x == '8':
            age_low_student(L)         
main()