Python語言之函式
Python語言之函式
前言
人生苦短,我用Python。
一、函式的定義和呼叫
什麼是函式?
函式是組織好的,可重複使用的,用來實現單一或相關聯功能的程式碼段,它能夠提高應用的模組性和程式碼的重複利用率。
函式的定義和呼叫
Python定義函式使用def關鍵字,格式如下:
def 函式名(引數列表):
函式體
例: def printInfo(): print('------------------------------------') print(' 人生苦短,我用Python ') print('------------------------------------')
定義了函式之後,想要讓這些程式碼能夠執行,需要呼叫函式。通過“函式名()” 即可完成呼叫。
# 呼叫剛才定義的函式
printInfo()
二、函式的引數
函式的引數
如果希望定義的函式,可以計算任何兩個數和,我們在定義函式的時候,讓函式接收資料,這就是函式的引數。
#定義接收兩個引數的函式
def add2num(a, b):
c = a+b
print(c)
a和b就是函式的引數(形參),呼叫的時候,可以傳入任意兩個數(實參)。
#呼叫帶有引數的函式
add2num(11, 22)
函式在被呼叫時會將實參按照相應的位置依次傳遞給形參,也就是說將第一個實參傳遞給第一個形參,將第二個實參傳遞給第二個形參,以此類推。
def get_max(a, b):
if a > b:
print(a,"是較大的值!")
else:
print(b,"是較大的值!")
get_max(8, 5)
關鍵字引數的傳遞
關鍵字引數的傳遞是通過“形參=實參”的格式將實參與形參相關聯,將實參按照相應的關鍵字傳遞給形參。
def connect(ip, port):
print(f"裝置{ip}:{port}連線!")
connect(ip="127.0.0.1", port=8080)
預設引數
呼叫函式時,如果沒有傳遞引數,則會使用預設引數。
def printinfo( name, age = 35 ): print("Name:", name) print("Age:", age) printinfo(name="miki" ) printinfo(age=9,name="miki" )
定義函式時,帶有預設值的引數一定要位於引數列表的最後面。否則程式會報錯。
不定長引數
有時可能需要一個函式能處理比當初宣告時更多的引數,這些引數叫做不定長引數,宣告時不會命名。
def functionname([formal_args,] *args, **kwargs):
"函式_文件字串"
function_suite
- 加了星號(*)的變數args會存放所有未命名的變數引數,args為元組;
- 加**的變數kwargs會存放命名引數,即形如key=value的引數, kwargs為字典。
一些程式碼
1.
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11,22)
def test(a,b,*args):
print(a)
print(b)
print(args)
test(11,22,33,44,55,66,77,88,99)
2.
def test(a,b,**kwargs):
print(a)
print(b)
print(kwargs)
test(11,22)
def test(a,b,**kwargs):
print(a)
print(b)
print(kwargs)
test(11,22,name='hello',id='12345')
3.
def test(a,b,**kwargs):
print(a)
print(b)
print(kwargs)
test(11,22,a=2,b=3)
4.
def test(a, b, *args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(1, 2, 3, 4, name = "hello", age = 20)
5.
def test(a, b, *args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11, 22, 33, 44, 55, 66, 77, 88, 99)
三、函式的返回值
函式的返回值是使用return語句來完成的。
def add2num(a, b):
c = a+b
return c
函式add2num中包含return,意味著這個函式有一個返回值,其返回值就是a和b相加的結果。
四、函式的四種類型
根據函式的引數和返回值,函式可以分為四種類型:
-
無引數,無返回值的函式
-
無引數,有返回值的函式
-
有引數,無返回值的函式
-
有引數,有返回值的函式
無引數,無返回值的函式
def printMenu():
print('--------------------------')
print(' xx涮涮鍋 點菜系統 ')
print(' 1. 羊肉涮涮鍋')
print(' 2. 牛肉涮涮鍋')
print(' 3. 豬肉涮涮鍋')
print('--------------------------')
printMenu()
無引數,有返回值的函式
# 獲取溫度
def getTemperature():
#這裡是獲取溫度的一些處理過程
#為了簡單起見,先模擬返回一個數據
return 24
temperature = getTemperature()
print('當前的溫度為:',temperature)
有引數,無返回值的函式
該類函式使用情景較少
def test(num1,num2):
result=num1+num2
print('計算結果為:%d'%result)
有引數,有返回值的函式
像資料處理並需要結果的應用,可以使用此類函式。
def calculateNum(num):
result = 0
i = 1
while i <= num:
result = result + i
i += 1
return result
result = calculateNum(100)
print('1~100的累加和為:', result)
五、函式的巢狀呼叫
舉個栗子:
def add_modify(a, b):
result = a + b
add()
print(result)
add_modify(10, 20)
函式的巢狀定義:
def add_modify(a, b):
result = a + b
print(result)
def test():
print("我是內層函式")
add_modify(10, 20)
注:
-
函式外部無法直接呼叫內層函式
-
只能通過外層函式間接呼叫內層函式
六、變數的作用域
作用域
-
為了避免變數的名稱發生衝突,所以Python引入了名稱空間的概念。
-
名稱空間指的是名稱到物件的對映,類似於字典,鍵名是變數的名字,值是變數的值。
名稱空間是相互獨立存在的,而且它們被安排在某個特定的層次,把這些層次結構組合起來就是作用域。
-
本地作用域:函式體中宣告的變數
-
函式巢狀作用域:巢狀函式中,外層函式體宣告的變數。
-
檔案作用域:py檔案中宣告的變數
-
內建作用域:python環境的作用域。主要是一些內建的函式名、內建的異常等關鍵字。例如open,range,quit等。
區域性變數
-
所謂區域性變數,就是在函式內部定義的變數。
-
區域性變數的作用域是函式內部,意味著它只在定義它的函式中有效,一旦函式結束就會消失。
全域性變數
-
定義在函式外的擁有全域性作用域。
-
全域性變數可以在整個程式範圍內訪問。
-
如果出現全域性變數和區域性變數名字相同的情況,則在函式中訪問的是區域性變數。
例:
a = 1
def test():
a = 10
print(f"區域性變數a:{a}")
test()
print(f"全域性變數a:{a}")
global和nonlocal關鍵字
-
修改函式中變數時,函式中使用global關鍵字用於申明變數為全域性變數。如果不使用global關鍵字,變數可讀但不可修改。
-
修改閉包函式中變數時,使用nonlocal關鍵字申明變數為外層函式的變數。如果不使用nonlocal關鍵字,外層函式變數可讀但不可修改。
例1:
a = 1
def test():
global a
a = 10
print(f"全域性變數a:{a}")
test()
print(f"全域性變數a:{a}")
>>>區域性變數a:10
全域性變數a:10
例2:
def test():
b = 2
c = 3
def test2():
b = 20
def test3():
nonlocal c
c = 30
test2()
test3()
print(b)
print(c)
test()
七、遞迴函式和匿名函式
遞迴函式
一個函式的內部可以呼叫其他函式。但是,如果一個函式在內部不呼叫其它的函式,而是自己本身的話,這個函式就是遞迴函式。
# 遞迴函式例子:求階乘
def fn(n):
if n==1:
return 1
return n*fn(n-1)
print(fn(5))
使用遞迴,實現階乘 n! = 1 * 2 * 3 * ... * n的計算。
把問題歸納為遞迴函式的方法:
-
明確函式幹什麼:定義傳入的引數
-
尋找遞迴結束條件:思考什麼時候終止遞歸併返回什麼樣的值
-
找出遞迴的關係式:例如f(n)和f(n-1)什麼關係?
匿名函式
匿名函式就是沒有名稱的函式,也就是不再使用def語句定義的函式。如果要宣告匿名函式,則需要使用lambda關鍵字,匿名函式的宣告格式如下所示:
lambda [arg1 [,arg2,.....argn]]:expression
匿名函式示例程式碼:
sum = lambda arg1, arg2: arg1 + arg2
# sum 函式名;lambda arg1, arg2 引數;arg1 + arg2 函式體(返回值)
print("執行結果:", sum( 10, 20 ))
print("執行結果:", sum( 20, 20 ))
注意:
使用Lambda宣告的匿名函式能接收任何數量的引數,可以返回一個或者多個值(多個值可以用元組、列表等方式)。
八、日期時間函式
時間函式
在Python中,通常有如下幾種方式表示時間:
(1)時間戳型別
(2)格式化的時間字串型別
(3)時間元組型別(struct_time)
時間戳
通常來講,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量,返回浮點秒數。
import time # 引入time模組
ticks = time.time()
print("當前時間戳為:", ticks)
格式化的時間字串
我們可以使用time模組的strftime方法來格式化日期。
import time
# 格式化成2016-03-20 11:45:39形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
格式化符號及其含義:
%y 兩位數的年份表示(00-99)
%Y 四位數的年份表示(000-9999)
%m 月份(01-12)
%d 月內中的一天
%H 24小時小時數(0-23)
%I 12小時制小時數(01-12)
%M 分鐘數(00-59)
%S 秒(00-59)
時間元組
返回struct_time型別的函式主要有gmtime()、localtime()和strptime(),struct_time元組。
序號 欄位 值
0 tm_year 2008
1 tm_mon 1到12
2 tm_mday 1到31
3 tm_hour 0到23
4 tm_min 0到59
5 tm_sec 0到61
6 tm_wday 0到6
7 tm_yday 1到366
8 tm_isdst -1,0,1,-1是決定是否為夏令時的旗幟
- time.altzone
返回格林威治西部的夏令時地區的偏移秒數。如果該地區在格林威治東部會返回負值(如西歐,包括英國)。對夏令時啟用地區才能使用。
import time
print(time.altzone)
- time.asctime([tupletime])
接受時間元組並返回一個可讀的形式為"Tue Dec 11 18:07:14 2008"(2008年12月11日 週二18時07分14秒)的24個字元的字串。
import time
t = (2008, 12, 11, 18, 7, 14, 1, 48, 0)
print(time.asctime(t))
- time.clock( )
用以浮點數計算的秒數返回當前的CPU時間。用來衡量不同程式的耗時,比time.time()更有用。
import time
t0 = time.clock( )
#do some thing
t1 = time.clock( )
print(t1-t0)
- time.ctime([secs])
作用相當於asctime(localtime(secs)),未給引數相當於asctime()。把一個時間戳(按秒計算的浮點數)轉化為time.asctime()的字串形式
import time
print(time.ctime(time.time()))
#或可轉化其他時候的時間戳
- time.gmtime([secs])
接收時間輟(1970紀元後經過的浮點秒數)並返回格林威治天文時間下的時間元組t。
import time
print(time.gmtime())
print(time.gmtime().tm_hour)
- time.localtime([secs])
接收時間輟(1970紀元後經過的浮點秒數)並返回當地時間下的時間元組t(t.tm_isdst可取0或1,取決於當地當時是不是夏令時)
import time
print(time.localtime())
print(time.localtime().tm_year)
- time.mktime(tupletime)
接受時間元組並返回時間戳,精確到整數秒
import time
print(time.mktime(time.localtime()))
- time.sleep(secs)
推遲呼叫執行緒的執行,secs指秒數。
- time.strftime(fmt[,tupletime])
接收以時間元組,並返回以可讀字串表示的當地時間,格式由fmt決定。
import time
t = (2009, 2, 17, 17, 3, 38, 1, 48, 0)
print(time.strftime("%b %d %Y %H:%M:%S", t))
- time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')
根據fmt的格式把一個時間字串解析為時間元組。
import time
struct_time = time.strptime("30 Nov 2020", "%d %b %Y")
print(struct_time)
- time.time( )
返回當前時間的時間戳
- time.tzset()
根據環境變數TZ重新初始化時間相關設定。
- time.timezone
表示當地時區(未啟動夏令時)距離格林威治的偏移秒數(>0,美洲;<=0大部分歐洲,亞洲,非洲)
import time
print(time.timezone)
- time.tzname
包含一對根據情況的不同而不同的字串,分別是帶夏令時的本地時區名稱,和不帶的。
import time
a = time.tzname[0]
b = a.encode('latin-1').decode('gbk')
print(b)
時間型別轉化關係
日曆函式
- calendar.calendar(year,m=3,w=2,l=1,c=6)
返回一個多行字串格式的year年年曆,m表示3個月一行,間隔距離為c。每日寬度間隔為w字元。每行長度為21* W+18+2* C。l是每星期行數。
import calendar
print(calendar.calendar(2022,m=3,w=2,l=1,c=6))
- calendar. firstweekday()
返回當前每週起始日期的設定。預設情況下,首次載入caendar模組時返回0,即每週從星期一開始。
- calendar.isleap(year)
判斷year是否是閏年,如果是返回True,否則為false。
- calendar.leapdays(y1,y2)
返回在Y1,Y2兩年之間的閏年總數。
- calendar.month(year,month,w=2,l=1)
返回一個多行字串格式的year年month月日曆,兩行標題,一週一行。每日寬度間隔為w字元。每行的長度為7* w+6。l是每星期的行數。
- calendar.monthcalendar(year,month)
返回一個整數的單層巢狀列表。每個子列表裝載代表一個星期的整數。Year年month月外的日期都設為0;從週一開始。範圍內的日子都由該月第幾日表示,從1開始。
- calendar.monthrange(year,month)
返回兩個整數。第一個這個月的第一天是星期幾,日從0(星期一)到6(星期日)。第二個是這個月的天數。
- calendar.prcal(year,w=2,l=1,c=6)
相當於print(calendar.calendar(year,w,l,c))
- calendar.setfirstweekday(weekday)
設定每週的起始日期碼。0(星期一)到6(星期日)
- calendar.prmonth(year,month,w=2,l=1)
相當於 print(calendar.monthcalendar(year,w,l,c))
- calendar.timegm(tupletime)
和time.gmtime相反:接受一個6元時間元組形式,返回該時刻的時間戳(1970紀元後經過的浮點秒數)
- calendar.weekday(year,month,day)
返回給定日期是周幾。0(星期一)到6(星期日)
九、隨機數函式
什麼是隨機?
真正的隨機涉及到了物理的量子,現實生活不是完全的隨機
通俗來講,越難以被猜到=隨機性越好
嚴格來講,隨機數有評判標準:NIST測試方法,TestU01的測試工具等等
據說UNIX系統中,將系統時間,連入WIFI,甚至按下的鍵盤次數都量化為了seed,參考指標越多,偽隨機數就越接近真正的隨機生成.
隨機數函式
- random.random()
用於生成一個0到1的隨機符點數: 0 <= n < 1.0。
import random
# 生成第一個隨機數
print("random():", random.random())
# 生成第二個隨機數
print("random():", random.random())
- random.uniform(a,b)
返回a,b之間的隨機浮點數,範圍[a,b]或[a,b]取決於四捨五入,a不一定要比b小。
import random
print("random:",random.uniform(50,100))
print("random:",random.uniform(100,50))
- random.randint(a,b)
返回a,b之間的整數,範圍[a,b],注意:傳入引數必須是整數,a一定要比b小。
import random
#生成的隨機數n: 12 <= n <= 20
print(random.randint(12,20))
- random.randrange([start], stop[, step])
返回有個區間內的整數,可以設定step。只能傳入整數,random.randrange(10, 100, 2),結果相當於從[10, 12, 14, 16, … 96, 98]序列中獲取一個隨機數。
- random.choice(sequence)
從sequence(序列,是有序型別的)中隨機獲取一個元素。列表、元組、字串都屬於sequence。
random.randrange(10,100,2)
結果等效於random.choice(range(10,100,2))
- random.shuffle(x[,random])
用於將列表中的元素打亂順序,俗稱為洗牌。
import random
p = ["Python","is", "powerful","simple"]
random.shuffle(p)
print(p)
- random.sample(sequence,k)
從指定序列中隨機獲取k個元素作為一個片段返回
import random
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
s = random.sample(list1, 5)
print(list1)
print(s)