定義函數(shù)
定義函數(shù)用def語句,格式:def 函數(shù)名(自變量) :函數(shù)名稱的定義規(guī)則和變量定義規(guī)則相同。在縮進板塊中編寫函數(shù)體遥皂,最后用return返回一個值。
求n的階乘
def f(x) :
"""
計算階乘
:param x: 一個非負整數(shù)
:return: x的階乘
"""
y = 1
for n in range(1, x + 1) :
y *= n
# return表示返回一個值,同時結(jié)束此函數(shù)
return y
注意:函數(shù)內(nèi)部一旦執(zhí)行到return,該函數(shù)就會停止執(zhí)行绘面,并將結(jié)果返回。如果沒有return語句侈沪,函數(shù)執(zhí)行完畢就會停止,返回的是一個空值none晚凿。
求最大公約數(shù)
def gcd(x, y):
"""
計算兩個數(shù)的最大公約數(shù)
:param x: 一個非負整數(shù)
:param y: 一個非負整數(shù)
:return: x,y的最大公約數(shù)
"""
(x, y) = (y ,x) if x > y else (x, y)
for factor in range(x, 0, -1):
if x % factor == 0 and y % factor == 0:
return factor
判斷素數(shù)
def is_prime(x):
"""
判斷素數(shù)
Parameters:
x - 一個非負整數(shù)
y - 一個非負整數(shù)
Returns:
如果num是素數(shù)返回True,反之返回False
"""
for num in range (2,int(sqrt(x)) + 1):
if x % num == 0:
return False
# return True
# 排除1的寫法:
return True if x != 1 else False
-
函數(shù)自變量的四種定義方式:
1.不設(shè)定自變量
def main():
pass
2.自變量為確定個數(shù)的參數(shù)亭罪,如上面的is_prime函數(shù),自變量為1個歼秽,即x应役;gcd函數(shù),自變量為2個,即x箩祥,y
3.自變量為不確定的參數(shù)
如下舉例說明:
在參數(shù)數(shù)量不確定的情況下院崇,求多個數(shù)的和
利用*args 定義可變參數(shù):*args 參數(shù)數(shù)量不確定,可為0個袍祖,也可為多個底瓣。在調(diào)用函數(shù)add時,輸入的自變量為多少個蕉陋,函數(shù)就求多少個數(shù)的和捐凭。
def add(*args):
"""
參數(shù)數(shù)量不確定的情況下,求多個數(shù)的和
:param argus:
*args 定義可變參數(shù):*args 參數(shù)數(shù)量不確定凳鬓,可為0個茁肠,也可為多個
:return: 多個參數(shù)的和
"""
total = 0
for value in args:
total += value
return total
if __name__ == '__main__':
# 直接傳入可變參數(shù)
# 求的是1+3+2+2+2+2的和
print(add(1,3,2,2,2,2))
# 傳入列表,求列表中各個元素的和
mylist = [1, 3, 5, 2, 10]
# 如果傳入的直接就是一個列表缩举,必須在列表前面加上*垦梆,才能取到列表中各個元素,否則會被視為只傳入了一個值仅孩,即列表
print(add(*mylist))
4.自變量設(shè)定了默認值
定義搖n個色子托猩,求每次色子點數(shù)之和的函數(shù),假設(shè)我們給自變量一個默認值,可設(shè)置為“n=2”格式杠氢,如下:
def roll_dice(n=2):
total = 0
for _ in range (n) :
total += randint(1, 6)
return total
if __name__ == '__main__':
# 調(diào)用函數(shù)敬拓,但未定義自變量,自變量取默認值2
roll_dice()
# 調(diào)用函數(shù)扫腺,定義自變量的值為3
roll_dice(3)
注意:在定義函數(shù)自變量時严望,官方建議不要用空格,如定義自變量為n温艇,并給n賦一個默認值2因悲,官方建議的書寫格式為:n=2,而不是n = 2勺爱。但在其他情況下,官方建議的書寫格式為:n = 2琐鲁。
空函數(shù)
如果想定義一個什么事也不做的空函數(shù),可以用pass語句适贸。pass語句的意義:什么都不做烙样,實際上是用來做占位符。比如現(xiàn)在還沒有想好怎么寫函數(shù)的代碼,就可以先放一個pass精耐,程序可以順利運行。
舉例說明:
def nop():
pass
pass還可以放在其他語句中惊完,如:
if x<1:
pass
函數(shù)的調(diào)用
一個文件就是一個模塊荷辕,一個模塊中可能有1個或任意多個函數(shù)
-
當前模塊中調(diào)用函數(shù)
調(diào)用函數(shù)時控嗜,若函數(shù)就在當前文本,則可以直接進行調(diào)用。格式為:函數(shù)名(變量)博助。由于很多時候這一個函數(shù)會被其他文本調(diào)用,為了讓其他文本在調(diào)用此函數(shù)時不執(zhí)行其他的代碼,可以使用下面的if條件語句,讓其他文本在導入此模塊時不執(zhí)行下面的代碼,原理:只有本文件執(zhí)行時,name = main饶米,當其他文件執(zhí)行時,name = 這個文件的命名,則name != main,if條件不成立,代碼不執(zhí)行。
-
其他模塊調(diào)用函數(shù)
若當前文本需要調(diào)用其他文本的函數(shù),則需要引入調(diào)用的函數(shù)模塊欲险。
1.同一跟目錄下的兩個文本函數(shù)之間調(diào)用:from 要調(diào)用的函數(shù)所在文本的名稱 import 函數(shù)名稱
2.不同根目錄下的兩個文本函數(shù)直接的調(diào)用:from 要調(diào)用的函數(shù)所在文本的路徑(如day01.practice.prime然低,表示day01包下面的practice包下面的prime文本)import 函數(shù)名稱
3.一個文本可能存在多個函數(shù)刚照,若需要調(diào)用此文本的所有函數(shù),可寫作如下格式:import combination * 導入combination中所有模塊
#導入 combination文件中所有模塊
import combination *
4.直接引入函數(shù)所在文本繁莹,每次調(diào)用時再輸入:文件名.函數(shù)名稱檩互。若原本的文件名太過復雜,還可臨時給他命一個新的名字(別名):import combination as com 此處把combination命為com咨演,在調(diào)用時闸昨,寫作com.f
import combination
#調(diào)用cobination的f(x)函數(shù)
print(com.f(5))
-
實例說明
1.直接調(diào)用輸出內(nèi)容
打印100以內(nèi)的素數(shù):
if __name__ == '__main__':
for num in range(1,100):
# 當is_prime(num)函數(shù)返回的值為True時,if條件語句才會執(zhí)行
if is_prime(num):
print(num)
調(diào)用求階乘函數(shù):f(x)薄风,求組合數(shù)C(m, n)
m = int(input('m = '))
n = int(input('n = '))
# 調(diào)用函數(shù)f(x)
print(f(m) // f(n) // f(m - n))
2.調(diào)用函數(shù)構(gòu)造新的函數(shù)
求最小公倍數(shù)饵较,lcm函數(shù)調(diào)用cgd函數(shù)
def lcm(x,y):
"""
計算兩個數(shù)的最小公倍數(shù)
Parameters:
x - 一個非負整數(shù)
y - 一個非負整數(shù)
Returns:
x,y的最小公倍數(shù)
"""
return x * y // gcd(x, y)
3.函數(shù)的遞歸調(diào)用
函數(shù)的遞歸調(diào)用指的是函數(shù)直接或間接調(diào)用函數(shù)自身,構(gòu)造這樣的遞歸函數(shù)必須滿足以下幾點:
1.收斂條件 - 讓遞歸在有限的次數(shù)完成或者進行回溯
2.如果遞歸無法在有限次數(shù)內(nèi)收斂就有可能導致RecursionError遭赂,而且棧的空間很小循诉,必須控制此函數(shù)的遞歸深度在棧的遞歸深度內(nèi)。
3.遞歸公式
在進入函數(shù)調(diào)用之前要保存當前的執(zhí)行現(xiàn)場,函數(shù)的執(zhí)行現(xiàn)場是保存在一種稱為棧(stack)的內(nèi)存空間上撇他,棧是一種先進后出(FILO)的存儲結(jié)構(gòu)茄猫。所以函數(shù)在做遞歸調(diào)用時,會一層一層向下遞歸困肩,最后在一層一層回溯划纽。
求最大公約數(shù)
def gcd(x, y):
if x > y:
return gcd(y, x)
elif y % x == 0:
return x
else:
return gcd(y % x, x)
求1到100的和
def add(n):
if n == 1 :
return 1
return n + add(n - 1)
計算走樓梯有多少種方式
10級樓梯,1次可選擇1锌畸,2勇劣,3層臺階,走完這10層臺階潭枣,問有多少種走法
def way(n):
if n < 0:
return 0
elif n == 0:
return 1
return way(n - 1) + way(n - 2) + way(n - 3)
漢諾塔
def hanoi(n, a, b, c):
if n > 0:
hanoi(n - 1, a, c, b)
print(a,'---->', b)
hanoi(n - 1, c, b, a)
函數(shù)命名沖突
當有多個函數(shù)命名沖突時比默,后面的函數(shù)自動覆蓋前面相同名稱的函數(shù)幻捏。
-
自己設(shè)定的函數(shù)和python內(nèi)置的函數(shù)沖突:
如自己編寫了一個求最大公約數(shù)的函數(shù)gcd,和math中的內(nèi)置的gcd函數(shù)沖突
from combination import gcd,
from math import gcd
調(diào)用gcd函數(shù)時退敦,如果直接書寫gcd()粘咖,文本會自動調(diào)用寫在后面的那個函數(shù),如上就會調(diào)用math中的gcd侈百,為了避免這種情況,可以按照以下方式調(diào)用:
# 方法一
import combination
import math
print(math.gcd())
print(combination.gcd())
# 方法二
from combination import gcd
# 調(diào)用的是conbinaion中的gcd函數(shù)
print(gcd())
from math import gcd
# 調(diào)用的是math中的gcd函數(shù)
print(gcd())
函數(shù)變量的作用域
變量的作用域有三種:
1.全局(global)作用域的變量:定義在函數(shù)外部的變量翰铡,此變量可在全局范圍內(nèi)被調(diào)用
2.嵌套(enclosed)作用域的變量:當一個函數(shù)調(diào)用另一個函數(shù)時钝域,定義在外層函數(shù)中的變量,此變量可被內(nèi)外層函數(shù)調(diào)用
3.局部(local)作用域:當一個函數(shù)嵌套在另一個函數(shù)內(nèi)部時锭魔,定義在內(nèi)層函數(shù)中的變量例证,此變量只能被內(nèi)層函數(shù)調(diào)用
4.內(nèi)置(build-in)作用域
Python 搜索一個變量的方式是從局部作用域到嵌套作用域再到全局作用域,如果都沒有搜索到迷捧,則會搜索內(nèi)置函數(shù)织咧,簡稱為LEGB(Local - Enclosed - Global - Build-in),如果想改變搜索范圍漠秋,可以使用global和nonlocal關(guān)鍵字改變變量的作用域笙蒙。
舉例說明:
# 在函數(shù)外面定義的a是一個全局變量
# 實際開發(fā)時一定要減少對全局變量的使用
# global variable
a = 100
def foo():
# 把foo函數(shù)內(nèi)的變量a改為全局變量,這時如果在函數(shù)外調(diào)用a庆锦,當搜索到此處的a = 200時捅位,原本變量a不能在函數(shù)外被調(diào)用,但此處變量a改為了全局變量搂抒,則能被函數(shù)外的代碼調(diào)用
global a
a = 200
# local variable
# 函數(shù)內(nèi)部的局部變量 離開foo函數(shù)變量是無法訪問的
b = 'hello'
def bar():
# 把局部作用域bar中的變量b改為嵌套作用域foo中的局部變量b艇搀,這時如果在foo中調(diào)用b,則搜索到的是b = 'good'求晶,而不是之前的b = 'hello'
nonlocal b
b = 'good'
print(a)
print(b)
bar()
print(b)
# foo()函數(shù)運行結(jié)果:200 good good
foo()
# 運行結(jié)果:200
print(a)