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))