1. 程式人生 > 其它 >Python語言之函式

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的計算。

把問題歸納為遞迴函式的方法:

  1. 明確函式幹什麼:定義傳入的引數

  2. 尋找遞迴結束條件:思考什麼時候終止遞歸併返回什麼樣的值

  3. 找出遞迴的關係式:例如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)

結尾