09函數-返回值、作用域、遞歸...

1. 函數的返回值

  • 返回值就是函數執行後返回的結果
  • 通過return來指定返回結果
  • return後面可以是任意類型的結果
#求任意個數的和
# def s(*b):
#     r = 0
#     for i in b:
#         r += i
#     print(r)
# s(1, 2, 3, 4, 5, 99) # 114
'''
return後面可以是任意類型的值,是什麼函數就返回什麼
'''
def fn():
    return 123
r=fn()
print(r)    # 123
print(fn)   # <function fn at 0x0000000002862598>
print(fn()) # 123

def fn1():
    print('執行fn1啦')
    def fn2():
        print('執行fn2啦')
    return fn2
    # return後的語句是永遠不會執行的
    print('執行完return啦')
m = fn1()   # 執行fn1啦
print(m)    # <function fn1.<locals>.fn2 at 0x00000000028E2730>
m()         # 執行fn2啦
'''
break與return的區別
break是退出循環,函數中後面其他語句可以執行
return是退出函數,return後面函數中語句不能執行
return是用來結束函數的
'''
def fn3():
    for i in range(5):
        print(i)
        if i==3:
            # break
            # continue 僅跳過當次循環
            return
    print('循環執行完畢')
fn3()

# 求任意個數的和
def s(*b):
    r = 0
    for i in b:
        r += i
    # print(r)
    return r
n= s(1, 2, 3, 4, 5, 99) # 114
print(n+2)      # 116

# fn函數對象  fn()調用函數
def fn():
    # return 123
    print('python')
print(fn)       # <function fn at 0x00000000028A28C8>
print(fn())
# 結果是:
# python  # 打印語句執行
# None   # 沒有返回值,是空
fn()            # python  直接調用函數,執行打印語句

2. 文檔字符串

  • help()是python的內置函數
  • 通過help(函數對象)可以查詢定義的函數對象的用法
  • 定義函數時在函數內部編寫文檔字符串,文檔字符串是對函數的說明
'''
help()可以查詢python中函數的用法
語法:help(函數對象)
help(print)
'''
# help(print)
def fn(a:int, b:str, c:bool)->int:
    '''
    這是一個文檔字符串案例
    :param a:
    :param b:
    :param c:
    :return:
    '''
    return 123
help(fn)

3. 函數的作用域(scope)

  • 作用域指變量生效的區域
  • 分爲全局作用域和函數作用域
  • 全局作用域在程序執行時創建,在程序執行結束時銷燬
    。所有函數以外的區域都是全局作用域
    。所有在全局作用域定義的變量都是全局變量,可以從程序的任意位置訪問調用全局變量
  • 函數作用域在函數調用時創建,在函數調用結束時銷燬
    。函數每調用一次,產生一個新的函數作用域
    。在函數作用域中定義的變量是局部變量,只能在函數內部被訪問
# 作用域scope
# 作用域指變量生效的區域
# 全局作用域b
# 函數作用域a
# b=20
# def fn():
#     a=2
#     print('函數內部:', 'a =', a)
#     print('函數內部:', 'b =', b)
#
# fn()
# # print('函數外部:', 'a =', a)  # NameError: name 'a' is not defined
# print('函數外部:', 'b =', b)

# 從函數內部可以訪問外部的數據,從外部卻不能訪問裏面的數據
def fn1():
    a=10
    def fn2():
        b=40
        print('fn2中的a', a)
        print('fn2中的b', b)
    fn2()
    print('fn1中的a', a)
    # print('fn1中的b', b)  # NameError: name 'b' is not defined
fn1()
# 在函數內部修改全局變量
a = 20
def fn3():
    global a
    a = 3
    print('函數內部:', 'a =', a)    # 函數內部: a = 3

fn3()

print('函數外部:', 'a =', a)    # 函數外部: a = 3

4. 命名空間

  • 命名空間實際上是一個專門存儲變量的字典
  • locals()用來獲取當前作用域的命名空間
  • 返回值是字典
# 命名空間是一個專門用來存儲變量的字典
# locals()是用來獲取當前作用域的命名空間,返回值時字典

a=20
b=30
scope=locals()

print(scope)
print(scope['a'])
print(scope['b'])
# 可以通過向字典添加k-v值向全局的命名空間增值,但不建議使用
# 而且在函數中這種添加方式會失敗
scope['c']=99
print(scope['c'])
print(c)    # 99  添加成功
def fn():
    a = 33
    b = 22
    scope = locals()
    # scope['d'] = 55
    # print(scope)
    # print(scope['a'])
    # print(scope['b'])
    # print(scope['d'])
    # print(d)    # NameError: name 'd' is not defined

    # globals() 獲取全局變量
    global_scope=globals()
    print(global_scope)     # ...'a': 20, 'b': 30, 'scope': {...}, 'c': 99, 'fn': <function fn at 0x0000000002892730>

fn()

5. 遞歸函數

  • 遞歸是將一個大問題分解爲一個一個小問題,直到無法再分解爲止
  • 遞歸函數有兩個條件
    。基線——大問題可以被分解爲的最小問題,滿足基線條件時,遞歸不再執行
    。遞歸條件——將問題繼續分解的條件(此處就像剝洋蔥,直到無法再剝)
# 求10!,10的階乘
# 1!=1
# 2!=2*1
# 3!=3*2*1
# .....
# 10!=10*9*8*7*6*5*4*3*2*1
# r = 10
# for i in range(1,10):
#     r*=i
# print(r)
# print(10*9*8*7*6*5*4*3*2*1)

# 定義一個函數來求任意數num的階乘num!

# def factorial_num(num):
#     '''
#
#     :param num: int,
#     :return: int
#     '''
#     for i in range(1,num):
#         num*=i
#     return num
#
# r = factorial_num(10)
# print(r)

# 遞歸是一種解決問題的方式
# 簡單來說遞歸就是自己引用自己,遞歸函數就是在函數中調用自己
# 遞歸的兩個條件:
#   1.基線條件——問題可被分解爲的最小條件,當滿足次條件時遞歸不再執行
#   2.遞歸條件——將問題繼續分解的條件
# 如果缺少遞歸中的條件基線,則爲無窮遞歸,類似死循環
# def factorial_some():
#     基線條件
#         return
#     遞歸條件
#     factorial_some()
# factorial_some()

# 用遞歸的解決方案來實現任意數的階乘
# 10!=10*9!
# 9!=9*8!
# ...
# 1!=1
def factorial_num(num):

    # 基線條件——最小爲1階乘爲1(這裏我們沒有考慮0!=1)
    if num == 1:
        return 1

    # 遞歸條件——繼續分解條件
    return num*factorial_num(num-1)

r = factorial_num(5)
print(r)
  • 遞歸練習:
# 練習一 定義一個函數:計算任意數的任意次冪
# caculate_num(num,p)

# 循環的方式:
# def caculate_num(num, p):
#     res = 1
#     for i in range(1, p+1):
#         res *= num
#
#     return res
# r = caculate_num(1, 4)
# print(r)

# 遞歸的方式:
# 參數 num 的 p 次冪
# def caculate_num(num, p):
#
#     # 條件一:基線條件 分解的最小事件
#     if p == 1:
#         return num
#
#     # 條件二:遞歸條件 繼續分解的條件
#     return num*caculate_num(num, p-1)
# res = caculate_num(3, 5)
# print(res)

# 練習二 : 創建函數檢查一個字符串是否是迴文,是返回True,不是返回False
# check_Palindrome(s)
# 把字符串存入列表中處理 獲取字符串長度len()

# 循環方式:

# s = list(input('輸入字符串:'))
# m = len(s)
# print(m)
# for i in range(m):
#
#     if s[i] == s[m-i-1]:
#         if i == m//2:
#             print(s[i])
#             print('True')
#     else:
#         print('False')
#         break

# 循環放入函數中
# s = list(input('輸入字符串:'))
# def check_palindrome(s):
#     m = len(s)
#     for i in range(m):
#
#         if s[i] == s[m - i - 1]:
#             if i == m // 2:
#                 print(s[i])
#                 return 'True'
#         else:
#             return 'False'
# print(check_palindrome(s))

# 遞歸方式:
# 是不是考慮類似剝洋蔥的思想,剝掉一層還一層
# 比較 abcdefgfedcba 第一個和最後一個是否一致
# 比較 bcdefgfedcb 第一個和最後一個是否一致
# 比較 cdefgfedc 第一個和最後一個是否一致
# 比較 defgfed 第一個和最後一個是否一致
# 比較 efgfe 第一個和最後一個是否一致
# ...
# 比較 fgf 第一個和最後一個是否一致
# g 字符串長度小於2時,一定爲迴文
# 字符串第一個和最後一個不一致時,一定不是迴文
s = list(input('輸入字符串:'))
def check_palindrome(s):
    print(s[1:-1])
    # 條件一:基線
    if len(s)<2:
        return True
    elif s[0]!=s[-1]:
        return False
    # 條件二:循環
    return check_palindrome(s[1:-1])    # 相當於s1=s[1:-1],s2=s1[1:-1]...

print(check_palindrome(s))

# 遞歸另一種寫法
def another_check(s):
    if len(s) < 2:
        return True
    return s[0] == s[-1] and another_check(s[1:-1])

print(another_check(s))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章