python 基礎 day03 函數(shù)

python 基礎 day03

1.冒泡排序

"""
冒泡排序,雖然,python自帶 sort() 方法 和 sorted() 函數(shù),但是還是要會
主要思想就是,一個列表,從前往后遍歷,然后判斷,要是后邊的比前邊的小就互換值,嗯,就是這樣
"""
def bubbleSort(a_list):
    for i in range(len(a_list)):  #我們可能要循環(huán)列表好幾遍,為啥呢,你笨想,一遍肯定不能把小值都拖到前邊,得好幾遍
        for j in range(0,len(a_list)-1-i):  #為啥要 -i ?,當 i = 0 ,第二層循環(huán)遍歷范圍是整個列表;當 i=1,第二層遍歷的是沒有最后一個元素的列表
            if a_list[j] > a_list[j+1]:     # 為啥要這么干? 因為,我們遍歷換位置操作,其實是將大值向后移動,在第一次遍歷,最大值就會被移動到最后完成排序了,就不用再遍歷它了
                a_list[j],a_list[j+1]=a_list[j+1],a_list[j]
    return a_list

list1 =   [64, 34, 25, 12, 22, 11, 90]
def main():
    new_list = bubbleSort(list1)
    print(new_list)
    print("排序完畢!")

if __name__ == "__main__":
    main()

2. 函數(shù)

一、集合(set)

特點:不允許有重復元素,如果添加重復元素,則會自動過濾,可以進行交集、并集的運算。

本質(zhì):無序且無重復元素的數(shù)據(jù)結構

1 創(chuàng)建集合

s1 = set()  #空集合  不能是{},這是字典
s2 = {1,2,3,4}
print(s1)
print(set([30,40,50]))  #通過列表創(chuàng)建
print(set((11,22,33)))  #通過元組創(chuàng)建
print(set('hello'))     #通過字符串創(chuàng)建  
print(set({'name':'大寶','age':20}))   #通過字典創(chuàng)建,得到一個鍵的集合

#注意:重復元素在set中會被自動過濾
#set 不支持 +  和 *  的運算

2 集合操作

#1 增加
#add添加不可變元素
s1.add(5)
# s1.add([6,7]) #不能添加列表,列表和字典都是不可哈希的
s1.add((6,7))  #可以添加元組元素,元組是可哈希的
print(s1)

#set.update(s) s必須是可迭代的對象:列表、元組、字符串、字典
#update會把列表、元組、字符串打碎添加到集合中
s1 = {1,2,3,4}
s1.update([5,6])
s1.update((7,8))
s1.update('hello')
s1.update({'1':10,'2':20})  #將字典的鍵添加到s1
print(s1)

#2 刪除
#set.remove(elem),如果沒有該元素也不報錯
set3 = {1,2,3,4,5,6}
set3.remove(4)  #直接刪除指定元素
print(set3)

print(set3.pop()) #刪除任意元素,并返回該元素的值
print(set3)
#set.discard() #刪除的元素不存在,不會報錯
set3.discard(10) 
#set3.remove(10) #如果元素不存在,則報錯:KeyError

#3元素個數(shù)
print(len(set3))

#4 成員操作
print(2 in set3)  #True

#5 并、交、差集
s1 = {1,2,3,4,5}
s2 = {3,4,5,6,7}
print(s1 | s2)  #并集
print(s1.union(s2))  #并集
s1.union_updaet(s2) #這表示求并集,并把并集賦值給s1
print(s1 & s2)  #交集
print(s1.intersection(s2)) #交集
s1.intersection_update(s2) #這表示求交集,并把交集賦值給s1
print(s1 - s2)  #差集
print(s1.difference(s2)) #差集 
s1.difference_update(s2) #這表示求差集,并把差集賦值給s1

#6.亦或 "^" 和對稱差集
#對稱差集和 "^" 求的是兩個序列除去交集以后的部分
print(s1 ^ s2)
print(s1.symmetric_difference(s2))
s1.symmetric_difference_update(s2) ##這表示求對稱差集,并把對稱差集賦值給s1

#7.子集于超集
set1 = {1,2,3}
set2 = {1,2,3,4,5,6}

print(set1 < set2)
print(set1.issubset(set2))  # 這兩個相同,都是說明set1是set2子集。

print(set2 > set1)
print(set2.issuperset(set1))  # 這兩個相同,都是說明set2是set1超集。


二、補充

2.1數(shù)據(jù)類型的轉換

函數(shù)名 函數(shù)值
int(x) 將x轉換為int類型
float(x) 將x轉換成浮點型
str(x) 將x轉換成字符串
bool(x) 轉換成bool類型 的True False
dict(x) 將序列x轉換成字典
list(x) 將序列x轉換成列表
set(x) 將序列x轉換成集合
tuple(x) 將序列x轉換成元組

2.2布爾值

在python中,能夠解釋為假的值有:None、0、0.0、False、所有的空容器(空列表、空元組、空字典、空集合、空字符串),其它是真

2.3 zip函數(shù)

zip() 函數(shù)用于將可迭代的對象作為參數(shù),將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表。

如果各個迭代器的元素個數(shù)不一致,則返回列表長度與最短的對象相同,利用 * 號操作符,可以將元組解壓為列表。

語法:zip(iterable1,iterable2, ...)

參數(shù)說明:iterable -- 一個或多個可迭代對象(字符串、列表、元祖、字典)

a = [1,2,3,4]
b = [2,3,4]
res = zip(a,b)
print(list(res))  #[(1, 2), (2, 3), (3, 4)]
# 可以使用for-in 遍歷
for x,y in zip(a,b):
    print(x,y)

2.4 列表推導式

運用列表推導式,可以快速生成list,可以通過一個list推導出另一個list,而代碼卻十分簡潔。

#列表推導式語法:
[exp for iter_var in iterable] 
執(zhí)行for-in循環(huán)時,通過iter_var遍歷iterable每一項,exp表達式中可以直接使用iter_var,每遍歷一項,產(chǎn)生一個新的列表元素。
#生成[0,1,4,9,16,25]
[x*x for x in range(6)]

#生成[0,4,16,36,64]
l2 = [x*x for x in range(9) if x % 2 ==0]
print(l2)

#可以使用雙重循環(huán)
suit = ['?','?','?','?']
face = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
poke = [(x,y) for x in suit for y in face]

#字典推導式
#列表生成式可以使用兩個變量,實現(xiàn)字典的鍵值交換
d = {"X":"A","Y":"B","Z":"C"}
list5 = {v:k for k,v in d.items()}
print(list5)

#集合推導式
print({x for x in range(10)})

#練習:
1.將一個列表中所有的字符串變成小寫
  l = ["Hello","World","IBM","Apple"]
如果是這樣的列表呢
  l =  ["Hello","World",10,"IBM","Apple"]

2.5 可變與不可變對象

# 不可變
指向內(nèi)存的值是不變的 int float str tutle 
# 可變
該對象指向的內(nèi)存的值是可變的
可變類型:字典 列表 集合  list  dict  set
 

2.6 判斷是不是各種類型

# isinstance()
isinstance(2,int)
isinstance(a_list,list)
isinstance(a_tuple,tuple)
isinstance(a_set,set)
isinstance(a_dict,dict)

三、函數(shù)引入

前面我們寫過九九乘法表,但如果我要七七乘法表或五五乘法表的話,你會看到三者代碼極其類似,只是循環(huán)變量不同,那么如何做到代碼重用,而不是簡單拷貝黏貼修改呢,其實可是使用函數(shù)完成這一功能

def table(row,col,sep=3):
    for i in range(1, row + 1):
        for j in range(1, col + 1):
            if j <= i:
                print("%d*%d = %2d" % (i, j, i * j), end='%*s'%(sep,' '))
        print('')
#一次編碼,到處運行
table(8,8)
table(5,5,8)

函數(shù)的優(yōu)點:

  • 代碼可復用
  • 代碼可維護性高
  • 容易排錯
  • 可讀性好
  • 利于團隊開發(fā)

1.函數(shù)定義

函數(shù)就是完成特定功能的代碼塊,本質(zhì)上是對代碼的封裝。 語法格式

def 函數(shù)名([參數(shù)1],[參數(shù)2]....[參數(shù)n]):
    函數(shù)體
  • 函數(shù)名命名規(guī)則同變量名,要滿足標識符命名規(guī)則
  • 不能和系統(tǒng)函數(shù)重名,否則系統(tǒng)函數(shù)無法使用
  • 函數(shù)定義分兩部分函數(shù)頭和函數(shù)體
  • 函數(shù)體,就是實現(xiàn)功能的代碼段,以:開頭,必須縮進
  • 函數(shù)名的命名風格:一般建議用下劃線分隔的小寫單詞組成:say_hello

2 函數(shù)參數(shù)

2.1 實參和形參

  • 形參:就是函數(shù)定義時小括號里的變量
  • 實參:函數(shù)調(diào)用的時候,小括號里的表達式
  • 函數(shù)可以沒有形參和實參

2.2 參數(shù)分類

  • 位置參數(shù),要求實參順序必須和形參順序完全一致,由形參順序決定實參順序

    def say_hello(name,age,home):
        print('大家好,我是{},我今年{}歲了,我來自{}'.format(name,age,home))
    
    say_hello('王二妮',18,'湖北武漢') #實參個數(shù)、順序必須和形參一致
    
  • 關鍵字參數(shù),函數(shù)調(diào)用時,實參可以是鍵值對,鍵就是形參名字,這樣的調(diào)用,實參不必關心形參的順序。

    def say_hello(name,age,home):
        print('大家好,我是{},我今年{}歲了,我來自{}'.format(name,age,home))
    
    say_hello(name='王二傻',home='大連',age=20)  #三個關鍵字參數(shù)
    say_hello('大傻',home='美國',age=30)  #兩個關鍵字參數(shù)
    sya_hello('二傻',24,home='何方')    #一個關鍵字參數(shù)
    
  • 默認值,如果形參在定義的時候給定一個值,那么函數(shù)在調(diào)用時就可以不傳實參,可以簡化調(diào)用

    • 默認值參數(shù)必須放到最右邊
    • 如果傳了實參,那么實參優(yōu)先,不會使用默認值
    • 默認值只計算一次
    • 默認值必須是不可變對象
    • 如果默認參數(shù)指向的是一個可變數(shù)據(jù)類型,那你無論調(diào)用多少次默認參數(shù),都是同一個對象,除非你給它傳個參數(shù),你給他穿個參數(shù),也只是你這一次調(diào)用不一樣了,原來的還在,如果你繼續(xù)默認調(diào)用,就還是他
    def my_power(x,n=2):
      return (x) ** n
    my_power(3)
    my_power(4,0.5)
    
    def test(a=[]):
        a.append('end')
        print(a)
    test([1,2,3])
    test()   #['end']
    test()   #['end','end']
    #默認值參數(shù)指向一個可變類型
    def func(a,list=[]):
        list.append(a)
        return list
    ret1 = func(10,) # ret1 = [10,]
    ret2 = func(20,[]) # ret2 = [20,]
    ret3 = func(100,) # ret3 = [10,100]
    print(func(10,)) #[10,100]
    print(func(20,[])) #[20]
    print(func(100,))#[10,100]
    
  • 可變參數(shù),傳入的參數(shù)個數(shù)是可變的,可以是1個、2個到任意個,還可以是0個。

    #使用*接收任意數(shù)量的位置參數(shù)
     #注意:*的不定長參數(shù)被當做元組處理
    def demo(a,b,*args):
        print(a,b,args)
    
    demo(12,33,90)
    demo(1,2,3,4,5)
    a=(1,2,3)
    demo(*a)
    
    #使用**接收任意數(shù)量的關鍵字參數(shù)
    #注意:**的不定長參數(shù)被當做字典處理
    def demo1(a,**args):
        print(a,args)
    demo1(1,name='kk',age=3)
    b = {'a':20,'b':12,'c':32}
    demo(**b)
    
    ## 定義函數(shù)參數(shù)時,用*args 和 **keargs 就是在裝包
    # 調(diào)用函數(shù)時,傳輸入?yún)?shù),用 *args 和 **kwargs 就是在解包
    

2.3 參數(shù)組合

  • 形參順序須按照以下順序:位置參數(shù)、默認值參數(shù)、args,*kwargs

2.4 命令行參數(shù)(了解)

如果要獲取命令行下傳給python文件的參數(shù)可以使用體統(tǒng)模塊sys的argv來獲取

參數(shù)個數(shù):len(sys.argv)

文件名:sys.argv[0]

參數(shù):sys.argv[1],sys.argv[2].....

# 文件名: 1.py
import sys
print(len(sys.argv))
print(sys.argv[0])
print(sys.argv[1])

在命令行下執(zhí)行:python 1.py 2 3 4

3 函數(shù)調(diào)用

  • 函數(shù)調(diào)用必須在函數(shù)定義之后

  • 函數(shù)調(diào)用必須能夠正確傳遞實參

    def demo(a,b,c=0,*arg1,**arg2):
      print(a,b,c,arg1,arg2)
    demo(1,3,k=4)
    demo(1,2,3,4,5)
    demo(1,b=3,c=3,d=5)
    demo(*(1,2,3),**{'name':12})  #任何函數(shù)都可通過這種形式傳遞參數(shù)
    

4 返回值

可以通過return語句返回計算結果。語法: return 表達式

  • return的作用一個是終止函數(shù)的執(zhí)行,所有執(zhí)行了return后,其后的語句不會被執(zhí)行

  • 如果沒有return語句,則默認返回的是None

  • return還可以返回給調(diào)用者數(shù)值

  • return可以返回一個值,如果要返回多個值,那么返回的是一個元組

    def demo2():
        return 1
    def demo3():
        return 1,2,3
    print(demo2())
    print(demo3())  #(1,2,3)
    

5 文檔字符串

函數(shù)文檔字符串documentation string (docstring)是在函數(shù)開頭,用來解釋其接口的字符串。簡而言之:幫助文檔

  • 包含函數(shù)的基礎信息
  • 包含函數(shù)的功能簡介
  • 包含每個形參的類型,使用等信息

文檔字符串書寫規(guī)則:

  • 必須在函數(shù)的首行

  • 使用三引號注解的多行字符串(''' ''') 或(""" """)

  • 函數(shù)文檔的第一行一般概述函數(shù)的主要功能,第二行空,第三行詳細描述。

    def test():
        """
            函數(shù)名:test
            功能:測試
            參數(shù):無
            返回值:無
        """
        print("函數(shù)輸出成功")
    
    #使用__doc__屬性查看文檔字符串
    print(test.__doc__)
    

6.參數(shù)傳遞(**)

python的參數(shù)傳遞是簡單的值傳遞,當然這里的值是指變量的引用(地址),不是變量的值。不存在值傳遞和引用傳遞的區(qū)分。簡而言之,python的參數(shù)傳遞可以稱之為對象引用傳遞,對象可以分為:

  • 不可變對象:int、float、None、complex、bool、tuple、str,range
    • 在函數(shù)內(nèi)部不可能修改函數(shù)外部的變量
  • 可變對象: dict、list
    • 可以在函數(shù)內(nèi)部修改

7 空函數(shù)

借助于pass語句實現(xiàn),函數(shù)體不完成任何功能,只有一個pass語句

def test():
    pass # 占位符

8 全局變量與局部變量

  • 如果你在定義變量之前引用變量,會報錯,變量必須先定義,后引用
# global 
# 當全局變量是不可變類型的時候,我們還想要在函數(shù)里對他進行修改,就得在函數(shù)里進行global聲明
# 當全局變量是可變類型的時候,我們即使不在函數(shù)里進行global聲明,也可以在函數(shù)里對它進行修改
# 一般golbal 聲明都要在函數(shù)一開始的時候,global 也可以直接在函數(shù)里新聲明一個變量
a = "外部定義的變量"
list1 = ['外部定義的變量']
def func():
    print(a)
    print(list1)
def func1():
    global a 
    #我們在函數(shù)里聲明將要修改全局變量,那我們在函數(shù)內(nèi)的修改不需要返回值就可以改變外部變量
    a = a + "hhhhh"
    list1.append(a)
    print(a)
    print(list1)

def func2():
    #如果我們聲明要使用全局變量,我們函數(shù)里用的各種變量都隨便是什么名字,跟外邊都沒關系
    a = "莫哈哈"
    list1 = [1,2,3,4]
    print(a)
    print(list1)
 

func()  # 這個打印出來的是 "外部定義的變量" ["外部定義的變量"]
func1() # 這個打印出來的是 "外部定義的變量hhhhh" ["外部定義的變量","外部定義的變量hhhhh"]
func2()  # 這個打印出來的是 "莫哈哈" [1,2,3,4]



## 所以還是要注意,全局變量名和函數(shù)內(nèi)部的變量名還是整成不一樣的好。起名字是程序員最大的難點。

#內(nèi)部函數(shù)
#1.內(nèi)部函數(shù)可以訪問外部函數(shù)的變量
#2.內(nèi)部函數(shù)可以修改外部函數(shù)可變類型的變量
#3.內(nèi)部函數(shù)在無聲明情況下不可修改外部函數(shù)的不可變類型變量
#4.這個聲明 是 nonlocal,要加在內(nèi)部函數(shù)里,nonlocal 不能影響全局變量。
#5.內(nèi)部函數(shù)修改全局的不可變類型變量,需要在內(nèi)部函數(shù)內(nèi)部聲明 global
#locals()函數(shù)返回一個字典,包含當前函數(shù)內(nèi)聲明的內(nèi)容有什么
#globals()函數(shù)返回一個字典,包含當前的全局變量有什么
#調(diào)用外部函數(shù)


m = 2020
def func():
    #聲明變量,都是局部變量
    n = 100
    list1 = [1,2,3,4]

    #內(nèi)部函數(shù)
    #在函數(shù)內(nèi)部聲明另外一個函數(shù)
    def inner_func():
        #聲明要對全局變量m進行修改
        global m
        #聲明要對外部函數(shù)不可變類型變量n進行修改
        nonlocal n  
        #對list1里面的元素進行加5操作
        for index,i in enumerate(list1):
            list1[index]=i+n

        list1.sort()
        n +=1
        m += 1
    #調(diào)用內(nèi)部函數(shù)
    inner_func()
    print(list1)
    print(n)
    print(m)
    print(locals()) #locals()函數(shù)返回一個字典,包含當前函數(shù)內(nèi)聲明的內(nèi)容有什么
    print(globals()) #globals()函數(shù)返回一個字典,包含當前的全局變量有什么
#調(diào)用外部函數(shù)
func()



9.閉包

#當函數(shù)定義內(nèi)部函數(shù),且返回值時內(nèi)部函數(shù)名,就叫閉包
#1.閉包必須是外部函數(shù)種定義了內(nèi)部函數(shù)
#2.外部函數(shù)是有返回值的,且該返回值就是內(nèi)部函數(shù)名,不能加括號
#3.內(nèi)部函數(shù)引用外部函數(shù)的變量值
'''
閉包格式:

def 外部函數(shù)():
    ...
    def 內(nèi)部函數(shù)():
        ...
    return 內(nèi)部函數(shù)
'''
def func():
    a = 100

    def inner_func():
        b = 99
        print(a,b)

    print(inner_func)
    return inner_func


#調(diào)用函數(shù)時,用對象接住函數(shù)返回的內(nèi)部函數(shù),那其實,這個對象x就變成了func()的內(nèi)部函數(shù),當使用 x() 是可以調(diào)用它
x = func()

x()
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容