遞迴、三元表示式、生成式(列表,字典)、匿名函式

Hans_Wang發表於2021-11-18

1. 遞迴函式

image

1.1 什麼是遞迴?

生活中用到的遞迴:

從前有座山,山裡有座廟,廟裡有個老和尚,正在給小和尚講故事呢!講的什麼呢? 講的是:"從前有座山,山裡有座廟,廟裡有個老和尚,正在給小和尚講故事呢!講的什麼呢? 講的是:'從前有座山,山裡有座廟,廟裡有個老和尚,正在給小和尚講故事呢!講的什麼呢? 

遞迴就是函式在執行過程中,直接或者間接的呼叫了自身。

遞迴的核心:

  1. 遞推
    一層層往下推導答案(每次遞迴之後複製度相較於上一次一定要有所下降)
  2. 回溯
    依據最後的結論往後推匯出最初需要的答案

重點: 遞迴一定要有結束條件!!!

如果沒有結果條件會一直遞迴下去,python直譯器中預設遞迴次數是1000

>>> import sys
>>> sys.getrecursionlimit()
1000

image

1.2 遞迴示例

示例1:求第5個人的的年齡,已知第1個人的年齡為18,第2個人比第1個人大兩歲,第3個人比第2個人大兩歲,依次類推

# 程式碼:
def foo(num):
    if num == 1:
        return 18
    return foo(num-1) +2

res = foo(5)
print(res)

執行結果:
    26

image

示例2: 只列印列表中的數字

l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,]]]]]]]]]]]]]]

def boo(l):
    for i in l:
        if type(i) == int:
            print(i, end=' ')
        else:
            boo(i)

boo(l)
print()
執行結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 

示例3: 階乘

# 程式碼:
def func1(num):
    if num == 1:
        return 1
    return func1(num -1) * num

res = func1(5)
print(res)
# 執行結果:
120

2. 三元表示式

判斷兩個數的大小,返回大的數:

之前的程式碼:

# 程式碼
def foo(a, b):
    if a > b:
        return a
    else:
        return b

print(foo(5, 6))

# 執行結果:
6

使用三元表示式:

def foo2(a,b):
    return  a if a >b else b

print(foo2(5,6))
# 執行結果:
6

# 判斷使用者輸入的是y或n

user_input=input("Please input y/n:").strip()
Please input y/n:y
if user_input == 'y':
    print("OK")
else:
    print("NO")
OK
# 使用三元表示式:
>>> user_input=input("Please input y/n:").strip()
Please input y/n:y
>>> "OK" if user_input=='y' else "NO"
'OK'

值 if 條件 else 值條件成立採用if前面的值,不成立採用else後面的值。

三元表示式還可以巢狀:

>>> res = True if 5 > 4 else (False if 1 < 2 else True)          
>>> print(res)
True

# 如果 前面的if 5 > 4為真則直接返回,否則再去計算 else後面的(False if 1 < 2 else True)

>>> res = True if 5 < 4 else (False if 1 < 2 else True) 
>>> print(res)
False

但是,三元表示式儘量不要巢狀使用

注意: 當功能需求僅僅是二選一的情況下,那麼推薦使用三元表示式

3. 列表生成式

列表生成式:功能是提供一種方便的列表建立方法.

示例1: 給一個列表裡面的每一個元素都加個ex_字首。

# 給列表每個元素都個ex_字首,組成一個新列表:
    list1 = ['apple', 'orange', 'purple']
    new_list = ['ex_apple', 'ex_orange', 'ex_purple']
# 目前程式碼實現
# 程式碼:
list1 = ['apple', 'orange', 'purple']
new_list=[]
def foo(list1):
    for name in list1:
        new_list.append("ex_%s" % name) 

foo(list1)
print(new_list)

# 執行結果:
['ex_apple', 'ex_orange', 'ex_purple']

# 使用列表生成式
>>> res = ["ex_%s" % name for name in list1]
>>> res
['ex_apple', 'ex_orange', 'ex_purple']

列表生成式裡面還可以使用if

# 除了orange外其他元素加`ex_`字首並加入列表。
>>> res = ["ex_%s" % name for name in list1 if name != 'orange'] 
>>> res
['ex_apple', 'ex_purple']

# 但 if 後面不能再加else了。

4. 字典生成式

快速生成一個字典。

如果快速把列表 list1 = ['apple', 'orange', 'purple'] 生成一個字典

>>> {i:j  for i, j in enumerate(list1)}    
{0: 'apple', 1: 'orange', 2: 'purple'}

# enumerate() 為列舉
# 對於一個可迭代的(iterable)/可遍歷的物件(如列表、字串),enumerate將其組成一個索引序列,利用它可以同時獲得索引和值。預設從0開始,但可以修改。
>>> {i:j  for i, j in enumerate(list1,start=1)}
{1: 'apple', 2: 'orange', 3: 'purple'}

還可以快速生成一個集合:

把 list1 = ['apple', 'orange', 'purple'] 生成一個集合
>>> {i  for i in list1}                 
{'purple', 'apple', 'orange'}

5. 匿名函式lambda

匿名函式:沒有名字的函式.

格式:

lambda 形參:返回值

def foo(n):
    return n**2

#就相當於:
lambda n:n**2

# 在呼叫的時候
>>> print(foo(3))
9
# 而匿名函式:
>>> print((lambda n:n**2)(3))
9

匿名函式一般不會單獨使用 都是配合其他函式一起使用

把列表中 list_num = [1, 2, 3, 4, 5]的元素都乘以2。
正常會把每個元素都遍歷一遍,然後乘以2,最後列印。
還可以使用map()內建方法,它的引數可以是一個函式
def foo(x):
    return x*2

print(list(map(foo, list_num)))
[2, 4, 6, 8, 10]

# 還可以把foo替換為一個匿名函式
>>> print(list(map(lambda x:x*2, list_num)))
[2, 4, 6, 8, 10]

6. 二分法

演算法就是解決問題的高效方法。

示例:從一個列表中查詢一個數是否存在

# 普通方法,在全部遍歷,然後判斷是否有要找到的值
>>> list_num = [12, 34, 54, 78, 101, 132, 136, 248, 567, 901, 1000]
>>> count=0
>>> for n in list_num:
        count+=1
        if n == 132:
            print("找了%d次,終於找到了" % count)
            break
    
    找了6次,終於找到了
    
# 使用二分法(把元素一分為二)
list_num = [12, 34, 54, 78, 101, 132, 136, 248, 567, 901, 1000]
find_num =  901   # 要找的數
def two(list_num):
    num = len(list_num) // 2 # 把元素一分為二
    if find_num >list_num[num]:  # 如果要找的數,大於中間的數則向右邊找
        right_list=list_num[num+1:]
        print(right_list)
        two(right_list)
    elif find_num <  list_num[num]:  # 如果要找的數,小於中間的數則向左邊找
        left_list=list_num[:num]
        print(left_list)
        two(left_list)
    elif find_num == list_num[num]: # 如果正好等於則直接找到了。
        print("Good,Find")
    else:						# 否則就是沒找到
        print("Not found")

two(list_num)
# 執行結果:
[136, 248, 567, 901, 1000]
[901, 1000]
[901]
Good,Find

注意 使用二分法,資料必須有序。

如果要查詢的元素在開頭 那麼還沒有依次遍歷查詢的效率高

相關文章