函數作用
增強代碼的重用性和可讀性
在沒有使用函數編程之前,我們可能一直遵循的都是面向過程編程,即根據業務邏輯從上到下實現各個功能,這樣的做的壞處是代碼可讀性不強,大量冗餘代碼,而且執行效率不高;有了函數後,我們就可以將多次使用到的相同代碼模塊放在單獨的函數定義中,在任何想要調用它的地方隨時調用,這就叫做函數式編程。
面向對象編程其實就是對函數進行再分類和封裝,讓開發"更快更好更強..."
函數的定義
def 函數名(參數):
...
函數體
...
返回值
函數的定義主要有如下要點:
1)def:表示函數的關鍵字
2)函數名:函數的名稱,日後根據函數名調用函數
3)函數體:函數中進行一系列的邏輯計算,如:發送郵件、計算出 [11,22,38,888,2]中的最大數等...
4)參數:爲函數體提供數據
5)返回值:當函數執行完畢後,可以給調用者返回數據
函數參數
可以對Python函數傳以下幾種形式的參數:
1、普通參數(嚴格按照順序,將實際參數賦值給形式參數)
2、默認參數(必須放置在參數列表的最後)
3、指定參數(將實際參數賦值給指定的形式參數)
4、動態參數:
* 默認將傳入的參數,全部放置在元組中
** 默認將傳入的參數,全部放置在列表中
5、萬能參數 *args,**kwargs
這幾種參數原理有點類似字符串的格式化輸出
str.format() 格式化輸出 s1 = "i am {0}, age {1}".format("kobe",18) print(s1) s2 = "i am {0}, age {1}".format(*["kobe",18]) print(s2) s3 = "i am {name}, age {age}".format(name='kobe',age='18') print(s3) dic_01 = {'name':'kobe','age':18} s4 = "i am {name}, age {age}".format(**dic_01) print(s4) 輸出: i am kobe, age 18 i am kobe, age 18 i am kobe, age 18 i am kobe, age 18
1)普通參數
def login(user,pwd): print(user,pwd) login(user,pwd)
2)默認參數
def login(user="kobe", pwd=123): print(user,pwd) login()
3)指定參數
def login(user, pwd): print(user,pwd) login(pwd=123, user="kobe") #指定參數的話,參數順序就可以隨便
4)動態參數
*args 一個星號
def f1(*args): print(args,type(args)) f1(11,22,'hhhh') li = [22,33,'hehe'] f1(li,'44') f1(*li) # 給全部的參數作爲元組的每一個元素添加 lii = 'kobe' f1(*lii) # 循環字符串每一個元素 輸出 (11, 22, 'hhhh') <class 'tuple'> # 函數接受所有參數,還是原來的元組 ([22, 33, 'hehe'], '44') <class 'tuple'> # 函數接受列表元素,並將他的整體作爲一個元組的一部分 (22, 33, 'hehe') <class 'tuple'> # 用一個星號可以將列表中的每一個元素添加進元組 ('k', 'o', 'b', 'e') <class 'tuple'> # 字符串循環的話,是每一個字符
**args 兩個星號
def f2(**args): print(args,type(args)) f2(n1="kobe") dic = {'k1':'v1','k2':'v2'} f2(kk=dic) # 只有一個鍵值對f2(**dic) 輸出 {'n1': 'kobe'} <class 'dict'> # 兩個星號動態參數會將鍵值保存爲字典 {'kk': {'k1': 'v1', 'k2': 'v2'}} <class 'dict'> # 傳字典參數要是不加兩個**,只會出現一個鍵值對 {'k1': 'v1', 'k2': 'v2'} <class 'dict'> # 傳字典參數,正確做法是加兩個**
混合傳參
def f3(*args,**kwargs): # 萬能參數只能放置在args後 print(args) print(kwargs) f3(11,22,33,k1="v1",k2="v2") 輸出 (11, 22, 33) # Python會自動將列表通過*args接收爲元組 {'k1': 'v1', 'k2': 'v2'} # 鍵值對會自動通過**args接收爲字典
函數擴展01:重複函數定義
def f4(a1,a2): return a1 + a2def f4(a1,a2): return a1 * a2 ret = f4(8,8) print(ret) 輸出 64 # 原因是因爲Python執行代碼自上而下,之前被執行的 a1+a2 =16由於在內存中沒人使用,很快會被Python的垃圾回收機制所回收
函數擴展02:函數傳參是原值引用還是重新創建的新值?
def f5(a1): a1.append(999) li_01 = [11,22,33] f5(li_01) print(li_01) 輸出 [11, 22, 33, 999] # 結果表明函數傳參是使用的引用,增加的話會改變原列表
函數擴展03:全局變量
NAME = "kobe" # 全局變量(潛規則:全局變量都用大寫) def f6(): age = 18 # 局部變量 global NAME # 修改全局變量 # 如果需要修改的變量是一個列表,則在函數裏面可以讀,可以append添加 但是不可以修改或者賦值 name = "jordan" print(NAME,age) f6() 輸出 kobe 18
Python的內置函數
1、 abs取絕對值
n = abs(-1)
2、all()所有元素爲真則爲真
n = all([1, 2, 3, 4]) print(n)
# any() 只要有真則爲真
n = any([1, 0, None]) print(n)
3、ascii()自動執行對象的__repr__方法
4、進制轉化
# bin() 10進制轉換成2進制 # oct() 10進制轉換成8進制 # hex() 10進制轉換成16進制
5、bool值
# 0,None,"",[],{},() 都爲False print(bool(0))
6、 bytes()
# bytes()字符串轉換字節類型 # bytearray()字符串轉換字節生成列表 # utf-8 一個漢字佔用3個字節 # gbk 一個漢字佔用2個字節 # 真是這個原因才導致很多gbk文件用utf-8打開會出現亂碼 s = "李傑" n = bytes(s, encoding="utf-8") print(n) 輸出 b'\xe6\x9d\x8e\xe6\x9d\xb0'
7、將字節轉換成字符串
n = str(bytes(s, encoding="utf-8"), encoding="utf-8") print(n) 輸出 李傑
8、 定義的函數功能模塊是否可以被調用
def f1(a, b): return a + b a = 100 b = 10 print(callable(f1)) 輸出: True
9、 ACSII碼轉換數字
print(chr(65)) print(ord('A')) 輸出: A 65
10、 利用random生成6位數字加字母隨機驗證碼
import random li = [] for i in range(6): r = random.randrange(0, 5) if r == 2 or r == 4: num = random.randrange(0, 9) li.append(str(num)) else: temp = random.randrange(65, 91) c = chr(temp) li.append(c) result = "".join(li) # 使用join時元素必須是字符串 print(result) 輸出 335HQS VS6RN5 ...
11、 將字符串編譯後執行 compile → exec + eval
s = "print(123)"r = compile(s, "<string>", "exec") # 將字符串編譯成Python代碼 exec(r) 輸出: 123
12、 exec 和 eval 都可以執行,通常exec功能更強大(可以接受代碼或者字符串)
# 但是 eval 有返回值,exec沒有 s = "8*8"ret = eval(s) print(ret) 輸出: 64
13、 查看對象提供的功能
print(dir(dict)) 輸出: ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'] help(list) # 讀模塊源碼
14、 共97,每頁顯示10條,需要最少頁
r = divmod(97, 10) n1, n2 = divmod(97, 10) print(n1, n2) 輸出: 9 7
15、 判斷某一對象是否是某類的實例
s = [1, 2, 3] print(isinstance(s, list)) 輸出: True
16、篩選函數filter
# 函數返回True,將元素添加到結果中 # filter(函數, 可迭代對象) # 循環第二個參數,讓每一個參數去執行函數,如果返回True,表示元素合法 def f2(a): if a > 22: return True li = [11, 22, 33] ret = filter(f2, li) print(list(ret)) 輸出: [33] 或者用lambda代替 result = filter(lambda a: a > 22, li) print(list(result)) # lambda 會自動 return f1 = lambda a: a > 30 ret = f1(90) print(ret)
17、篩選函數 map
# 將函數返回值添加到結果中 # 對可迭代對象內的元素做統一操作 li = [11, 22, 33, 44] result = map(lambda a: a+100, li) print(list(result)) 輸出: [111, 122, 133, 144]
18、所有的全局變量、局部變量
NAME = 'AAA' def show(): a = 123 b = 456 print(locals()) print(globals()) show()
19、hash值
# 將一個對象轉換成他的hash值 s = 'hhh' print(hash(s)) 輸出: 3160577387536464976
20、len長度計算
# python 3 裏面按照字符查找,返回2 # Python 2 裏面按照字節查找,返回6 s = '李傑' print(len(s))
21、round取相鄰整數
print(round(1.4)) print(round(1.8)) 輸出: 1 2
22、zip 並行迭代
l1 = ["kobe", 11, 22, 33] l2 = ["is", 11, 22] l3 = ["boy", 11, 22, 33] r = zip(l1, l2, l3) tmp = list(r)[0] print(" ".join(tmp)) 輸出: kobe is boy
函數示例小程序:用戶登陸註冊
def login(user,pwd): """ 用戶用戶登陸驗證 :param: user 用戶名 :param: pwd 密碼 :return: Ture 登陸成功 False 登陸失敗 """ f = open('db','r') for line in f: if line.split('|')[0] == user and line.split('|')[1] == pwd: return True return False def register(user, pwd): """ 用戶用戶註冊 :param user: 用戶名 :param pwd: 密碼 :return: 默認None """ f = open('db', 'a') temp = "\n" + user + "|" + pwd f.write(temp) f.close() def main(): select = input("請選擇:【1】登陸 【2】註冊 :") if select == "1": print("正在登陸...") user = input("請輸入用戶名: ") pwd = input("請輸入密碼: ") ret = login(user, pwd) if ret is True: print("登陸成功!") else: print("登陸失敗!") if select == "2": print("正在註冊...") user = input("請輸入用戶名: ") pwd = input("請輸入密碼 ") ret = register(user, pwd) print("註冊成功!") main()
三元運算&三目運算
# 三元運算 通過一條命令代替if else語句
if 1==1: name = "kobe" else: name = "jordan" name = "kobe" if 1 == 1 else "jordan"
# lambda表達式
def f1(a1): return a1 + 100 f2 = lambda a1, a2: a1 + a2 ret = f1(10) ret2 = f2(100,10) print(ret,ret2) 輸出 110 110
文件操作
1)打開文件
# f = open('db', 'r') # 只讀 # f = open('db', 'w') # 只寫,先清空 # f = open('db', 'x') # python 3.0 新加(如果文件存在報錯,不存在則創建並寫內容) # f = open('db', 'a') # 追加 # f = open('db', 'r', encoding="utf-8") # 指定字符編碼,防止亂碼 # f = open('db', 'rb') # 以二進制打開
r+ a+ w+的區別
# r+ 能調整寫文件指針位置,其他的總是寫到末尾 # a+ 能讀,但是寫文件只能在末尾添加 # w+ 會先清空文件再寫 f = open('db', 'r+', encoding="utf-8") # 如果模式沒有加 b 中文默認按照一個字符讀取數據 data = f.read(1) f.seek(3) # 調整文件指針到執行位置(以字節方式查找) print(f.tell()) f.write("777") # 會覆蓋已經存在的元素
2)操作文件
f.read() # 無參數默認讀全部;有參數(b按字節;無b按字符) f.tell() # 查看指針位置 f.seek() # 按字節調整指針位置 f.write() # 寫文件 f.close() # 關閉 f.fileno() # 文件的描述符 f.flush() # 強刷文件到硬盤 f.readable() # 是否可讀 f.readline() # 僅讀取一行 f.truncate() # 截斷指針後面的所有數據
for循環文件對象
for line in f: print(line)
關閉文件
f.close() with open('db') as f: pass
同時打開兩個文件
with open('db01') as f1, open('db02') as f2: pass