def my_sum(x,y):
return x+y
res = my_sum(1,2)
print(res)
函數對象
#函數名是第一類對象:
函數名指向的值能夠被看成參數傳遞(相似於變量)
name = 'syy'
x = name
print(x) #syy
print(id(x)) #2553483145936
def func():
pass
print(func) #<function func at 0x0000025287641EA0>
print(func()) #None
print(id(func())) #1904845968
#函數名能夠被當作參數傳遞給其餘函數
#能夠在定義以後的任何位置調用(包括函數體內部)
def func():
print('from func')
print(func)
def index(args):
print(args)
print('from index')
index(func)
#函數名能夠被當作函數的返回值,該功能實現了全局訪問局部
def func():
print('from func')
def index():
print('from index')
return func()
res = index()
print(res)
from index
from func
None
#函數名能夠被當作容器類型的元素
def func():
print('from func')
print(func())
l = [1,2,func,func()]
print(l)
from func
None
from func
[1, 2, <function func at 0x000001C9A5581EA0>, None]
#callable 可調用的,也就是說能夠加括號(),執行某一功能
#網絡爬蟲,就是爬取一個網頁的源代碼
1.在終端安裝Terminal
pip3 install requests
2.使用pycharm安裝(file-settings-project: project interpreter-雙擊)
import requests
response = requests.get('https://www.baidu.com')
if response.status_code == 200:
print(response.text)
函數的嵌套調用與嵌套定義
#函數的嵌套:
在函數內部調用其餘函數
能夠將複雜的問題簡單化
#先定義,後調用(相對於同級來講)
def index():
func()
print('index')
def func():
print('func')
func()
#嵌套調用返回值的問題,全局訪問局部
def outer():
print('outer')
def inner():
print('inner')
return inner
res = outer()
print(res)
print(res())
#函數嵌套的應用場景
def my_max_2(x,y):
if x > y:
return x
return y
def my_max_4(a,b,c,d):
res1 = my_max_2(a,b)
res2 = my_max_2(res1,c)
res3 = my_max_2(res2,d)
return res3
print(my_max_4(1,4,8,999))
#函數複雜的功能與簡單的接口
def all_func(type):
if type == '1':
print('redister')
elif type == '2':
print('login')
elif type == '3':
print('shopping')
all_func('1')
名稱空間
#什麼是名稱空間
存放變量名與變量值的內存地址的綁定關係的地方
#變量名與變量值
想要訪問一個變量的值,必須先去名稱空間中拿到變量名,才能訪問到內存中的變量的值
#名稱空間的分類
1.內置名稱空間
python解釋器'提早定義好'的變量名、函數名,放到內置名稱空間
len()、max()、min()
2.全局名稱空間
'文件級別'的
if、for、while不管嵌套多少層,他們內部所建立的變量名、函數名,都放到全局名稱空間
3.局部名稱空間
'函數體內建立'的變量名、函數名,都放到局部名稱空間
局部名稱空間之間沒法直接訪問
#生命週期
內置名稱空間,只要python解釋器啓動,就會馬上建立,關閉python解釋器的話,內置名稱空間自動銷燬
全局名稱空間,只要右鍵運行`.py`文件,自動建立,`.py`文件程序運行結束,自動銷燬
局部名稱空間,函數被調用的時候自動建立,函數指向結束,自動銷燬
#名稱空間的訪問順序
#所在位置爲全局的時候,調用函數名的話,先去全局名稱空間找,再去局部名稱空間中找
len = '我是全局名稱空間中的len'
def func():
len = '我是局部名稱空間中的len'
print(len)
print(len)
#所在位置爲局部的時候,調用函數名的話,先去局部名稱空間找,再去全局名稱空間找,再去內置名稱空間找
len = '我是全局名稱空間中的len'
def func():
len = '我是局部名稱空間中的len'
print(len)
func()
#同級別局部名稱空間不能互相訪問
def index():
x = 1
# print(y)
def func():
# print(x)
y = 666
index()
func()
#下級名稱空間能夠訪問上級名稱空間,上級名稱空間不能訪問下級名稱空間
x = 2
def index():
x = 1
def func():
print(x)
return func
x = 3
res = index()
res()
#函數在定義階段,查找名字的順序就已經固定了,不會由於函數的調用位置的變化而變化
x = 2
def index():
x = 1
def func():
print(x)
return func
x = 3
res = index()
x = 4
res() #1
x =5
def f1():
x = 1
def f2():
x = 2
def f3():
x = 3
def f4():
x = 4
print(x)
f4()
f3()
f2()
res = f1() #4,print()函數打印出來的
print(res) #None,沒有return,因此函數返回值爲None
x = 1
def outer():
def inner():
print('from inner',x)
return inner
res = outer()
def func():
x = 2
res()
func() #from inner 1
x = 1
def outer():
def inner():
print('from inner',x)
# x = 2 ,變量x在函數inner內部找,可是應該在調用以前定義
return inner
res = outer()
res() #報錯
名稱空間與做用域
#全局做用域
內置名稱空間、全局名稱空間都是全局做用域,都是全局有效
#局部做用域
局部名稱空間都是局部做用域,局部有效
#名稱空間的做用順序
x = 1
def func():
x = 2
func()
print(x) #1
#當全局是可變數據類型,直接能夠局部修改全局
x = []
def func():
x.append('哈哈哈')
func()
print(x)
#關鍵字 global,做用於全局是不可變數據類型,在全局名稱空間建立變量,global聲明多個的時候使用逗號隔開
x = 1
def func():
global x
x = 2
func()
print(x)
#關鍵字 nonlocal,做用於下一級對上一級局部名稱空間內變量的修改
def func():
x = 1
def index():
x = 2
index()
print(x)
func() #1
def func():
x = 1
def index():
nonlocal x
x = 2
index()
print(x)
func() #2
購物車
msg = """
1.註冊
2.登陸
3.轉帳
4.購物
5.支付
"""
def register():
print('register...')
def login():
print('login...')
def transfer():
print('transfer...')
def shopping():
print('shopping...')
def pay():
print('pay...')
func_dict = {
'1':register,
'2':login,
'3':transfer,
'4':shopping,
'5':pay,
}
while True:
print(msg)
choise = input('請輸入你想要執行的功能>>>: ').strip()
if choise in func_dict:
func_dict.get(choise)() #執行函數
else:
print('相關功能還在開發中...')
# if choise == '1':
# db_username = input('請輸入你的用戶名>>>: ').strip()
# db_passwd = input('請輸入你的密碼>>>: ').strip()
# print('用戶註冊成功')
# elif choise == '2':
# username = input('請輸入你的用戶名>>>: ').strip()
# passwd = input('請輸入你的密碼>>>: ').strip()
# elif choise =='3':
# transfer()
# elif choise =='4':
# shopping()
# elif choise == '5':
# pay()
閉包函數
#閉:定義在函數內部的函數
#包:內部函數引用了外部函數做用域的變量名、函數名
#格式
y = 2
def outer():
x = 1
def inner():
print(x,y)
#閉包函數訪問內部函數的問題
def outer():
x = 1
def inner():
print(x)
return inner
res = outer()
res() #1
#經過傳參的方式,能夠實現全局修改局部,使用關鍵字global、nonlocal能夠實現局部修改全局
#給函數體傳參的方式一 -- 位置參數傳參
def index(username):
print(username)
#給函數體傳參的方式二 -- 閉包函數
#閉包函數不會浪費變量名
def outer():
x = 1
y = 10
def my_max():
if x > y:
print(x)
print(y)
return my_max
res = outer()
res() #10
def outer(x,y):
def my_max():
if x > y:
print(x)
print(y)
return my_max
res = outer(1,10)
res() #10
#閉包函數與網絡爬蟲(使用閉包函數,定義變量名)
import requests
def my_req(url):
def inner():
response = requests.get(url)
if response.status_code == 200:
print(response.text)
return inner
requests_baidu = my_req('https://www.baidu.com')
requests_baidu()
裝飾器
#裝飾器
裝飾:就是給裝飾對象添加新的功能
器: 就是一個工具
#裝飾器原則:
開放:對擴展開放
封閉:對修改封閉(儘可能不修改代碼)
#裝飾器條件:
1.不改變裝飾對象的源代碼
2.不改變被裝飾對象(可調用對象callable)的調用方式 -- 使用閉包函數
#裝飾器做用於可調用對象,還能夠做用於裝飾器
時間戳 (裝飾器的原理)
#時間戳,當前時間距離1970-1-1 00:00:00相差的秒數
#1970-1-1 00:00:00爲Unix的誕生元年
import time
print(time.time()) #1604630670.6970603
#CPU睡一覺
import time
print('I am syy')
time.sleep(3) #暫停3秒
print('GWY warning!')
#計算代碼的執行時間
import time
def my_time():
print('syy')
time.sleep(3)
start = time.time()
my_time()
end = time.time()
print('%s 的執行時間是: %s'%('函數my_time',end - start))
無參裝飾器
#使用閉包函數修改函數名
import time
def func(): #測試函數
time.sleep(1)
print('重金求子')
def index(args):
def get_time():
start = time.time()
args()
end = time.time()
print('執行時間是: %s'%(end - start))
return get_time #返回值,返回被測試函數的返回值
func = index(func) #裝飾器中的get_time函數名 = 裝飾器名(要裝飾的函數名)
func()
重金求子
執行時間是: 1.0055692195892334
裝飾器的升級版
import time
def func():
time.sleep(1)
print('重金求子')
return '我是func'
def login(name):
time.sleep(2)
print('%s login success'%name)
return '我是login'
def index(ch):
def get_time(*args,**kwargs):
start = time.time()
res = ch(*args,**kwargs)
end = time.time()
print('執行時間是: %s'%(end - start))
return res
return get_time
func = index(func) #裝飾不須要傳參的函數
res = func()
print(res)
login = index(login) #裝飾須要傳參的函數
res = login('syy')
print(res)
裝飾器語法糖
import time
def index(ch):
def get_time(*args,**kwargs):
start = time.time()
res = ch(*args,**kwargs)
end = time.time()
print('執行時間是: %s'%(end - start))
return res
return get_time
@index #將下面緊挨着的函數的函數名,當作參數傳入裝飾器
def func():
time.sleep(1)
print('重金求子')
return '我是func'
@index
def login(name): #@index,至關於login = index(login)
time.sleep(2)
print('%s login success'%name)
return '我是login'
res = func()
print(res)
res = login('syy')
print(res)
裝飾器模板
#無參裝飾器
from functools import wraps
def outter(func):
@wraps(func)
def inner(*args,**kwargs): #*在形參中使用(),{}
print('執行被裝飾函數以前,能夠進行的操做')
res = func(*args,**kwargs) #*在實參中使用(),{}
print('執行被裝飾函數以後,能夠進行的操做')
return res
return inner
@outter #裝飾器中的inner函數名 = 裝飾器名(要裝飾的函數名)
def test():
pass
res = test()
print(res())
#有參裝飾器
from functools import wraps
def wps(params1,params2):
def outter(func):
@wraps(func)
def inner(*args,**kwargs):
print('執行被裝飾函數以前,能夠進行的操做')
res = func(*args,**kwargs)
print('執行被裝飾函數以後,能夠進行的操做')
return res
return inner
return outter
認證裝飾器
#要求
1.執行函數index以前,必須先輸入用戶名和密碼,認證以後才能執行index
2.不然提示用戶輸入錯誤,結束程序
def outter(func):
dict = {'is_auto':None}
def inner(*args,**kwargs):
db_username = 'syy'
db_password = 123
if dict['is_auto']: #避免屢次調用裝飾器,須要重複登陸的狀況
res = func(*args, **kwargs)
return res
else:
username = input('請輸入你的用戶名>>>: ').strip()
password = int(input('請輸入你的用戶密碼>>>: ').strip())
if username == db_username and password == db_password:
dict['is_auto'] = True
res = func(*args,**kwargs)
return res
else:
print('用戶名或密碼輸入錯誤!')
return inner
@outter
def index():
print('我是index函數')
res = index()
print(res)
@outter
def index2():
print('我是index2函數')
res = index2()
print(res)
多層裝飾器
#多層裝飾器在裝飾的時候,順序是從上往下
import time
def index(args):
def get_time():
start = time.time()
args()
end = time.time()
print('執行時間是: %s'%(end - start))
return get_time
def outter(func):
dict = {'is_auto': None}
def inner(*args,**kwargs):
db_username = 'syy'
db_password = 123
if dict['is_auto']:
res = func(*args, **kwargs)
return res
else:
username = input('請輸入你的用戶名>>>: ').strip()
password = int(input('請輸入你的用戶密碼>>>: ').strip())
if username == db_username and password == db_password:
dict['is_auto'] = True
res = func(*args,**kwargs)
return res
else:
print('用戶名或密碼輸入錯誤!')
return inner
@outter
@index
def index():
time.sleep(1)
print('我是index函數')
res = index()
print(res)
請輸入你的用戶名>>>: syy
請輸入你的用戶密碼>>>: 123
我是index函數
執行時間是: 1.0005483627319336
None
測試
import time
def index(args):
def get_time():
start = time.time()
args()
end = time.time()
print('執行時間是: %s'%(end - start))
return get_time
def outter(func):
dict = {'is_auto': None}
data_source = input('請輸入你的密碼存儲類型(file/mysql/redis)>>>: ')
def inner(*args,**kwargs):
db_username = 'syy'
db_password = 123
if dict['is_auto']: #------------------------
res = func(*args, **kwargs)
return res
else:
if data_source == 'file':
username = input('請輸入你的用戶名>>>: ').strip()
password = int(input('請輸入你的用戶密碼>>>: ').strip())
if username == db_username and password == db_password:
dict['is_auto'] = True
res = func(*args,**kwargs)
return res
else:
print('用戶名或密碼輸入錯誤!')
elif data_source == 'mysql':
print('mysql')
elif data_source == 'redis':
print('redis')
else:
print('密碼存儲類型輸入錯誤') #--------------------------
return inner
@outter
@index
def index():
time.sleep(1)
print('我是index函數')
res = index()
print(res)
有參裝飾器(3層def)
import time
def index(args):
def get_time():
start = time.time()
args()
end = time.time()
print('執行時間是: %s'%(end - start))
return get_time
def login_auth(data_source): #這一層僅僅是爲了傳參
def outter(func):
dict = {'is_auto': None}
def inner(*args,**kwargs):
db_username = 'syy'
db_password = 123
if dict['is_auto']:
res = func(*args, **kwargs)
return res
else:
if data_source == 'file':
username = input('請輸入你的用戶名>>>: ').strip()
password = int(input('請輸入你的用戶密碼>>>: ').strip())
if username == db_username and password == db_password:
dict['is_auto'] = True
res = func(*args,**kwargs)
return res
else:
print('用戶名或密碼輸入錯誤!')
elif data_source == 'mysql':
print('mysql')
elif data_source == 'redis':
print('redis')
else:
print('密碼存儲類型輸入錯誤')
return inner
return outter
@login_auth('file')
@index
def index():
time.sleep(1)
print('我是index函數')
res = index()
print(res)
請輸入你的用戶名>>>: syy
請輸入你的用戶密碼>>>: 123
我是index函數
執行時間是: 1.0005395412445068
None
裝飾器修復技術
#需求
1.用戶查看被裝飾函數的函數名的時候,查看到的就是被裝飾函數自己
2.用戶查看被裝飾函數的註釋的時候,查看到的就是被裝飾函數的註釋
#函數名問題
def outter(func):
def inner(*args,**kwargs):
func(*args,**kwargs)
return inner
@outter
def index():
pass
print(id(index)) #2887421694024
print(index.__name__) #inner,查看函數名的字符串形式
#查看函數註釋問題
def outter(func):
def inner(*args,**kwargs):
"""
我是裝飾器內部的註釋
:param args:
:param kwargs:
:return:
"""
print('哈哈')
res = func(*args,**kwargs)
return inner
@outter
def index():
"""
我是index內部的註釋
:return:
"""
pass
print(help(index))
inner(*args, **kwargs)
我是裝飾器內部的註釋
:param args:
:param kwargs:
:return:
None
#裝飾器修復技術,導入模塊
#修復函數名問題
from functools import wraps
def outter(func):
@wraps(func)
def inner(*args,**kwargs):
func(*args,**kwargs)
return inner
@outter
def index():
pass
print(id(index)) #1597239300168
print(index.__name__) #index
#修復註釋問題
from functools import wraps
def outter(func):
@wraps(func)
def inner(*args,**kwargs):
"""
我是裝飾器內部的註釋
:param args:
:param kwargs:
:return:
"""
print('哈哈')
res = func(*args,**kwargs)
return inner
@outter
def index():
"""
我是index內部的註釋
:return:
"""
pass
print(help(index))
index()
我是index內部的註釋
:return:
None
函數的遞歸
#遞歸
函數在調用階段,直接或間接的又調用本身
#做用
遞歸的做用是爲了解決使用循環的複雜程度
#格式
def func():
print('from func')
func()
func() #RecursionError:
def index():
print('from index')
login()
def login():
print('from login')
index()
login() #RecursionError:
#查看最大遞歸深度
import sys
print(sys.getrecursionlimit()) #1000,不是很精確
def func(n):
print('from func',n)
func(n+1)
func(1) #998
#修改最大遞歸深度
import sys
print(sys.getrecursionlimit())
sys.setrecursionlimit(500)
def func(n):
print('from func',n)
func(n+1)
func(1) #498
#遞歸分爲兩個階段
1.回溯,一次次重複的過程,這個重複的過程必須創建在上一次重複,問題的複雜度下降,直到有一個最終的結束條件
2.遞推,一次次向回推導的過程,獲得結果
#實例一
age(5) = age(4) + 2
age(4) = age(3) + 2
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 18
def age(n):
if n == 1:
return 18
return age(n-1) + 2
res = age(5)
print(res) #26
#實例二
#使用遞歸函數,不須要考慮循環的次數,只須要知道結束條件便可
l = [1,[2,[3,[4,[5,[6,[7,[8,[9,[10,]]]]]]]]]]
for i in l:
if type(i) == int:
print(i)
else:
for i in i:
if type(i) == int:
print(i)
else:
for i in i:
if type(i) == int:
print(i)
...
def get_num(L):
for i in L: #for循環取值,取完自動結束
if type(i) == int:
print(i)
else:
get_num(i) #使用遞歸,避免重複代碼
get_num(l)
算法之二分法
#算法
解決問題的高效率的方法
#前提
二分法必須基於一個有序的容器類型
#實例
l = [1,3,5,12,57,99,101,150,177,199,345,...]
#代碼1
num = 345
for i in l:
if num == i:
print('find it')
continue
#代碼2
def get_num(L,target_num):
middle_index = len(L) // 2
print(L)
if target_num not in L:
print('該值不存在於列表中')
return
if target_num > L[middle_index]:
num_right = L[middle_index+1:]
get_num(num_right,target_num)
elif target_num < L[middle_index]:
num_left = L[0:middle_index]
get_num(num_left,target_num)
else:
print('找到了',target_num)
get_num(l,19)
三元表達式
#做用
使用if判斷,從兩個值中,取出一個
#三元表達式固定表達式
#條件成立,值1
#條件不成立,值2
值1 if 條件 else 值2
#應用場景
當結果只有兩種可能性的狀況下,可使用三元表達式來簡化代碼
def my_max(x,y):
if x > y:
return x
return y
res = my_max(1,10)
print(res)
#實例1
#若是if後面的條件成立,返回if前面的值,不然返回else後面的值
x = 1
y = 19
res = x if x > y else y
print(res)
#實例2
is_free = input('請輸入是否免費y/n>>>: ')
is_free = '免費' if is_free == 'y' else '收費'
print(is_free)
列表生成式
#做用
使用for循環,快速操做列表
#格式
[操做i for i in 容器]
[操做i for i in 容器 if 條件] #不能使用else
#一個列表中,在每個元素的後面都添加一個後綴_dsb
l = ['syy','sniko','shou','ji']
#代碼1
ll = []
for i in l:
ll.append('%s_dsb'%i)
print(ll)
#代碼2
ll = []
for i in l:
ll.append(i + '_dsb') #python中,該方法鏈接字符串的效率很低
print(ll)
#代碼3
L = ['%s_dsb'%i for i in l]
print(L)
#一個列表中,在以s開頭的元素的後面都添加一個後綴_dsb
#for循環一次取出列表中的每個元素
#而後交給if判斷,條件成立的話,纔會交給前面的if判斷
#條件不成立,把該元素直接捨棄
l = ['syy','sniko','shou','ji']
L = ['%s_DSB'%i for i in l if i.startswith('s')]
print(L)
字典生成式
#做用
使用for循環,快速生成一個字典
#格式
{i:j for i,j in 容器}
{i:j for i,j in 容器 if 條件}
#實例1
#l2中,元素只能比l1多(或者相等),不能比l1少
d = {}
l1 = ['一','二','三']
l2 = ['yi','er','san']
for i,j in enumerate(l1):
d[j] = l2[i]
print(d) #{'一': 'yi', '二': 'er', '三': 'san'}
#實例2
l = ['syy',123,'pwd']
d = {i:j for i,j in enumerate(l)}
print(d) #{0: 'syy', 1: 123, 2: 'pwd'}
l = ['syy',123,'pwd']
d = {i:j for i,j in enumerate(l) if j != 'syy'}
print(d) #{1: 123, 2: 'pwd'}
#enumerate()
函數用於將一個可遍歷的數據對象(如列表、元組或字符串)組合爲一個索引序列,同時列出數據和數據下標,通常用在 for 循環當中。
#格式
enumerate(容器, [start=0])
集合生成式
#做用
使用for循環,快速生成一個集合
#格式
{i for i in 列表 if 條件}
#實例
res = {i for i in range(10) if i !=5}
print(res) #{0, 1, 2, 3, 4, 6, 7, 8, 9}
生成器表達式
#做用
作成生成器,不浪費內存取值
#格式
(i for i in 列表 if 條件)
#實例
res = (i for i in range(10) if i !=5)
print(res) #<generator生成器 object <genexpr> at 0x0000028E1823A728>
for i in res:
print(i)
匿名函數
#定義
沒有名字的函數
使用關鍵字lambda定義
#做用
臨時建立,用完自動刪除
#格式
#左邊至關於函數的形參
#右邊至關於函數的實參
#匿名函數一般不會單獨使用,須要配合內置函數一塊兒使用
(lambda 形參:操做)(實參)
#實例1
def my_sum(x,y):
return x+y
res = my_sum(1,2)
print(res)
res = (lambda x,y:x+y)(1,2)
print(res)
#匿名函數轉換成函數
func = lambda x,y:x+y
print(func) #<function <lambda> at 0x00000116E8401EA0>,能夠加括號執行
res = func(1,2)
print(res)
經常使用內置函數 max()
#原理
內部基於for循環,先將傳入容器類型中的元素一個個取出
若是沒有指定key(key對應的是一個函數)的時候,那麼就直接比較取出的值(比較大小、ASCII碼)
若是指定了key,那麼max()函數會將這個元素交給這個函數,獲得函數的返回值,再比較大小
#格式
max(l)
max(d,key=my_func)
#做用於列表,比較值的大小
l = [1,2,3]
print(max(l)) #內部使用的是for循環
l = ['syy','zz']
print(max(l)) #zz
#做用於字典,使用ASCII碼比較
#A-Z,65 90,a-z,95 122
d = {'syy':666,'egon':888888,'js':233}
print(max(d)) #syy
#max()函數的位置參數
d = {'syy':666,'egon':888888,'js':233}
def my_func(name):
return d[name]
print(max(d,key=my_func)) #egon
#內置函數max()與lambda表達式連用
d = {'syy':666,'egon':888888,'js':233}
print(max(d,key=lambda name:d[name])) #egon
min()
#格式
max(l)
max(d,key=my_func)
#做用於列表,比較值的大小
l = [1,2,3]
print( min(l)) #內部使用的是for循環
l = ['syy','zz']
print(min(l)) #syy
#做用於字典,使用ASCII碼比較
#A-Z,65 90,a-z,95 122
d = {'syy':666,'egon':888888,'js':233}
print(min(d)) #egon
#min()函數的位置參數
d = {'syy':666,'egon':888888,'js':233}
def my_func(name):
return d[name]
print( min(d,key=my_func)) #js
#內置函數min()與lambda表達式連用
d = {'syy':666,'egon':888888,'js':233}
print(min(d,key=lambda name:d[name])) #js
map()
#map()函數
映射,把列表、元組、集合的全部元素,同等操做
#格式
map(lambda 形參:操做:做用對象)
#實例1
l = [1,2,3,4,5]
print(map(lambda x:x+1,l)) #<map object at 0x000001F55A38F860>,生成器
res = map(lambda x:x+1,l)
for i in res: #使用for循環,取出生成器中的值
print(i) #2,3,4,5,6
print(list(res)) #使用list(本質仍是for循環)
#實例二
l = {'1','2','3','4','5'}
res = map(lambda x:x+'_dsb',l)
print(set(res)) #{'4_dsb', '5_dsb', '2_dsb', '3_dsb', '1_dsb'}
zip()
#zip()函數
拉鍊,把兩個容器中對應的一對兒元素綁定到一塊兒組成元組
#格式
zip(l1,l2,...)
#實例
#元素多了無效
l1 = [11,22,33]
l2 = ['js','syy','egon']
print(zip(l1,l2)) #<zip object at 0x0000027A904D9888>,生成器
res = zip(l1,l2)
print(type(res)) #<class 'zip'>,zip數據類型
print(list(res)) #[(11, 'js'), (22, 'syy'), (33, 'egon')],數據類型轉換
l3 = ['a','b','c']
print(list(zip(l1,l2,l3))) #[(11, 'js', 'a'), (22, 'syy', 'b'), (33, 'egon', 'c')]
filter()
#filter()
過濾
#格式
filter(lambda 形參:操做,做用對象)
#實例1
l = [1,2,3,4,5]
res = filter(lambda x:x !=3,l)
print(res) #<filter object at 0x000001E546EEF860>,生成器
print(list(filter(lambda x:x !=3,l))) #[1, 2, 4, 5]
sorted()
# sorted()
排序,默認正序
能夠排列數字,也能夠排列字符串
#格式
sorted(l,reverse=False)
#實例
l = ['syy','nb','haha']
print(sorted(l)) #['haha', 'nb', 'syy'],正序
l = ['syy','nb','haha'] #['syy', 'nb', 'haha'],反序
print(sorted(l,reverse=True))
reduce()
# reduce()
取值,再操做
#格式
reduce(lambda 形參:操做,做用對象,N)
#實例1
#若是N指定了,那麼N爲初始值,若是N不指定,按照如下規律
#第一次先獲取兩個元素,相加
#以後每次獲取一個,與上一次的結果,再相加
from functools import reduce
l = [1,2,3,4,5,6]
res = reduce(lambda x,y:x+y,l)
print(res) #21
迭代器
#什麼是迭代器
迭代:更新換代(重複)的過程,每次迭代都必須基於上一次的結果
迭代器:迭代取值的工具
#爲何要用迭代器
迭代器提供了一種不依賴於索引取值的一種方式
#能夠迭代取值的數據類型
字符串、列表、元組、字典、集合
#怎麼用迭代器
#對有序的數據類型(字符串、列表、元組),實現迭代 --- while循環
l = [1,2,3,4,5]
n = 0
while n < len(l):
print(l[n])
n+=1
#對無序的數據類型(字典、集合),實現迭代 --- 使用迭代器
可迭代對象
#只要內置有__iter__方法的,都叫作可迭代對象
#雙下劃線開頭、結尾的方法,能夠讀'雙下+方法'
#可迭代對象有,字符串、列表、元組、字典、集合、文件
#不可迭代對象有,整型、浮點型、布爾值
#迭代器對象是可迭代對象使用__iter__方法的返回值
a = 1
b = 1.1
c = '哈哈'
d = [1,2,3]
e = {'name':'syy'}
f = {1,2,3}
g = (1,2,3)
h = True
i = open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8')
j = len('哈哈')
a.__i
b.__i
c.__iter__()
d.__iter__()
e.__iter__()
f.__iter__()
g.__iter__()
h.__i
i.__iter__()
j.__i
#可迭代對象執行__iter__,獲得的就是迭代器對象
res = c.__iter__()
print(res) #<str_iterator object at 0x000001A54DC24780>
res = d.__iter__()
print(res) #<list_iterator object at 0x000001A54DC24978>
res = e.__iter__()
print(res) #<dict_keyiterator object at 0x000001A54D928598>
res = f.__iter__()
print(res) #<set_iterator object at 0x000001A54DC3A360>
res = g.__iter__()
print(res) #<tuple_iterator object at 0x000001A54DC24978>
res = i.__iter__()
print(res) #<_io.TextIOWrapper name='E:\\python_test\\xxxx.txt' mode='rt' encoding='utf-8'>
#迭代器的使用
print(len(c))
print(c.__len__())
res = map(lambda x:x+1,l)
print(res) #<map object at 0x000001AF716CF860>
l1 = [1,2,3]
l2 = ['yi','er','san']
print(zip(l1,l2)) #<zip object at 0x000002D38D179888>
迭代器對象
#迭代器對象(就是迭代器)
1.內置有__iter__方法
2.內置有__next__方法
#迭代器對象必定是可迭代對象,可是可迭代對象不必定是迭代器對象
#迭代器對象的驗證
c = '哈哈'
d = [1,2,3]
e = {'name':'syy'}
f = {1,2,3}
g = (1,2,3)
i = open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8')
res = c.__iter__()
print(res) #<str_iterator object at 0x000001A54DC24780>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
res = d.__iter__()
print(res) #<list_iterator object at 0x000001A54DC24978>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
res = e.__iter__()
print(res) #<dict_keyiterator object at 0x000001A54D928598>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
res = f.__iter__()
print(res) #<set_iterator object at 0x000001A54DC3A360>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
res = g.__iter__()
print(res) #<tuple_iterator object at 0x000001A54DC24978>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
res = i.__iter__()
print(res) #<_io.TextIOWrapper name='E:\\python_test\\xxxx.txt' mode='rt' encoding='utf-8'>
iter_1 = res
iter_1.__iter__()
iter_1.__next__()
#迭代器對象的取值
l = [1,2,3,4]
iter_1 = l.__iter__()
res = iter_1.__iter__()
print(res) #<list_iterator object,自己
print(iter_1.__next__()) #1
print(iter_1.__next__()) #2
print(iter_1.__next__()) #3
print(iter_1.__next__()) #4
print(iter_1.__next__()) #StopIteration
#文件對象自己就是一個可迭代對象、迭代器對象
i = open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8')
res = i.__iter__()
res = i.__next__()
print(res) #<_io.TextIOWrapper name='E:\\python_test\\xxxx.txt' mode='rt' encoding='utf-8'>
#迭代器對象執行__iter__,獲得的仍是迭代器對象自己
i = open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8')
res = i.__iter__()
print(res is i) #True
print(i is i.__iter__().__iter__().__iter__()) #True
#問題
__iter__就是生產迭代器對象的方法
文件對象自己就是迭代器對象,爲何還內置__iter__方法呢?
答:爲了文件對象能夠和別的接迭代對象,能夠一塊兒使用for循環,若是迭代器對象沒有__iter__,那麼文件對象調用__iter__的時候就會報錯
#異常有兩大類
1.語法結構錯誤,須要當成修改,不然沒法捕獲
2.邏輯錯誤,異常捕獲能夠處理
#異常捕獲
d = [1,2,3]
iter_1 = d.__iter__()
while True:
try:
print(iter_1.__next__())
except StopIteration:
print('母雞下蛋完成')
break
#萬能異常捕獲(前提是邏輯錯誤)
while True:
try:
fve
except Exception:
break
#迭代器取值的優勢
1.不依賴於索引取值
2.內存中永遠只佔用一份空間,不會致使內存溢出
#迭代器取值的缺點
1.只能依次取值,不能後退
2.取完值以後報錯StopIteration(異常捕獲)
#ps:
__iter__() 等價於 iter()
__next__() 等價於 next()
__len__() 等價於 len()
for循環內部原理
#for循環簡單格式
#for循環後面的關鍵字in,後面跟的是一個可迭代對象
l = [1,2,3]
for i in l:
print(i)
#for循環內部本質
1.將in後面的對象調用__iter__方法,轉換成迭代器對象
2.調用__next__,迭代取值
3.內部有異常捕獲,當__next__報這個錯StopIteration,自動結束循環
#for循環完整格式
for i in 可迭代對象:
try:
循環體代碼
except StopIteration:
break
生成器(自定義迭代器)
#生成器
生成器本質上就是迭代器,只不過是用戶自定義的迭代器
使用關鍵字yield,自定義迭代器
#當函數內有yield關鍵字的時候
調用函數以前,該函數與普通函數同樣
當'調用函數的時候',不會執行函數體代碼,而是將函數初始化,變成生成器
#yield,若是函數體代碼中有yield關鍵字,那麼函數加括號執行的時候,不會觸發函數體代碼的運行
def func():
print('first')
yield
print('second')
func() #變成生成器
res = func()
print(res)
print(res.__next__())
<generator object func at 0x0000016BC5C4A728>
first
None
#yield後面跟的值,就是調用迭代器__next__,能獲得的值
def func():
print('first')
yield 233
print('second')
res = func()
print(res)
print(res.__next__())
print(res.__next__()) #StopIteration
<generator生成器 object func at 0x000001298930A728>
first
233
second
#yield,既能夠返回一個值,又能夠返回多個值(元組)
def func():
print('first')
yield 233,4,5
print('second')
res = func()
print(res)
print(res.__next__())
print(res.__next__())
print(res.__next__()) #StopIteration
<generator object func at 0x0000014569B9A728>
first
(233, 4, 5)
second
#函數體代碼中有多個yield
def func():
print('first')
yield 1
print('second')
yield 2
print('third')
yield 3
print('fourth')
res = func()
print(res)
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__()) #StopIteration
<generator object func at 0x0000021A5A67A728>
first
1
second
2
third
3
fourth
#自定義迭代器(生成器)
for i in range(1,10,2): #內置函數
print(i)
def my_range(start=0,end,step=1): #自定義迭代器(生成器)
while start < end:
print(start)
yield start
start+=step
res = range(1,10,1)
print(res.__n) #內置range不是迭代器對象
res = my_range(1,10,1) #先運行,再調用
print(res.__next__())
#函數體外部向函數體內部傳參的方式
1.位置參數
2.閉包函數
#函數體內部向函數體外部傳參的方式
1.關鍵字global
2.函數return
3.yield
#yield支持外界爲其傳參
#必須先將代碼運行到yield,才能爲其傳值
def dog(name):
print('%s 準備開吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
func = dog('js')
func.__next__() #返回空值,不能省略,含有yield的函數,調用__next__纔會執行
func.send('糖果') #send(),給yield傳參,調用__next__
func.send('包子')
js準備開吃
js吃了"糖果"
#yield
1.yield提供的是一種自定義生成器的方式
2.yield能夠將函數的運行狀態中止
3.yield能夠返回值
#yield與return之間的相同點
1.均可以返回值,而且均可以返回多個值
#yield與return之間的不一樣點
1.yield能夠返回屢次值,return只能把全部的值一次返回,而後當即結束
2.yield能夠接收外部傳入的值
生成器表達式
#做用
作成生成器,不浪費內存取值
生成器不會主動執行任何一行代碼,必須使用__next__方法,纔會觸發代碼運行
#格式
(i for i in 可迭代對象 if 條件)
#實例
res = (i for i in range(10) if i !=5)
print(res) #<generator生成器 object <genexpr> at 0x0000028E1823A728>
#生成器取值1
for i in res:
print(i)
#生成器取值2
res = (i for i in range(5) if i !=3)
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())
#應用場景1 -- 容器內的元素不少
res = (i for i in range(100000000) if i !=5)
#應用場景2 -- 統計文件中的字符個數
f = open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8')
data = f.read() #佔用內存較多
print(len(data))
f.close()
with open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8') as f:
n = 0
for line in f: #生成器的本質方法
n+=len(line)
print(n)
with open(r'E:\python_test\xxxx.txt',mode='rt',encoding='utf-8') as f:
g = (len(line) for line in f)
print(sum(g))
#sum()函數的本質
l = [1,2]
res = sum(l)
print(res) #3
l = [1,2]
n = 0
for i in l:
n+=i
print(n)
l = [1,2]
res1 = l.__iter__().__next__()
res2 = l.__iter__().__next__()
print(res1+res2)
l = [1,2]
res = (i for i in l)
for i in res:
print(i)
生成器面試題
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g = test() #0,1,2,3
for n in [1,10]:
g = (add(n,i) for i in g)
"""
第一次循環:g = (add(1,i) for i in test())
第二次循環:g = (add(10,i) for i in g)
"""
res = list(g)
"""
for i in (add(10,i) for i in test()): #上述循環的2層生成器拆分開,n=10
add(10,i)
"""
print(res) #[20, 21, 22, 23]
經常使用的內置函數
#abs(),取絕對值
res = abs(-1)
print(res) #1
#all(),所有爲True爲True
l = [0,1,2,3]
print(all(l)) #False
#any(),有一個爲True爲True
print(any(l)) #True
#十進制轉其餘進制,bin()、oct()、hex()
print(bin(10))
print(oct(10))
print(hex(10))
0b1010 #二進制
0o12 #八進制
0xa #十六進制
#其餘進制轉十進制,使用int()
print(int('1010',2))
print(int('12',8))
print(int('a',16))
#轉換爲布爾值,bool()
print(bool(1)) #True,非零數都爲True
print(bool(0)) #False
#字符串轉二進制數,encode()、bytes()
s = '哈哈'
print(s.encode('utf-8'))
print(bytes(s,encoding='utf-8'))
#二進制數轉字符串,decode()函數
s = '哈哈'
res1 = s.encode('utf-8')
res2 = res1.decode('utf-8')
print(res2)
#可調用的,就是能夠加括號執行相應功能的,callable()
l = [1,2,3]
print(callable(l)) #False
#將數字轉換成字母,使用chr()函數,可用於驗證碼
print(chr(97)) #a
print(chr(122)) #z
#將字母轉換成數字,使用ord()函數
print(ord('a')) #97
print(ord('z')) #122
print(ord('A')) #65
print(ord('Z')) #90
#函數dir(),返回對象在名稱空間中的全部有關的名字
l = [1,2,3]
print(dir(l)) #['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
import b #導入b.py文件
print(dir(b))
#divmod()函數,獲得商和餘數,可用於分頁器
print(divmod(100,10))
print(divmod(100,9))
(10, 0)
(11, 1)
total_num,more = divmod(100,9) #總數據量,每頁的數據量
if more:
total_num+=1
print('總頁數是: ',total_num)
#enumerate()函數,枚舉(一個個列出來),可用來打印msg
l = ['a','b']
for i,j in enumerate(l,1):
print(i,j)
1 a
2 b
#evel()函數,可用來識別字符串中的簡單代碼(去掉引號),不能識別字符串中的邏輯代碼
s = 'print("hello world")'
print(eval(s))
hello world
None
s = """
x = 1
y = 2
print(x+y)
"""
print(eval(s)) #SyntaxError
#exec()函數,便可以用來識別字符串中的簡單代碼,又能夠識別字符串中的邏輯代碼
s = 'print("hello world")'
print(exec(s))
s = """
x = 1
y = 2
print(x+y)
"""
print(exec(s))
hello world
None
3
None
#format()函數,三種玩法
{}佔位
{index}索引佔位
{name}指名道姓的佔位
#globals()函數,打印全局名稱空間中的變量,不管在哪
print(globals()) #{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001CE953EC2B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/python_test/a.py', '__cached__': None}
#locals()函數,打印局部名稱空間中的變量(在哪打印哪的)
def test():
x =111
print(locals())
test() #{'x': 111}
#help()函數,查看函數內的幫助
def test():
"""
:return: 沒有
"""
x =111
print(help(test))
test()
:return: 沒有
#isinstance()函數,驗證數據類型
x = 1
print(type(x)) #<class 'int'>
print(type(x) is int) #True
print(isinstance(x,int)) #True
#pow()函數,次方
print(pow(2,3)) #8
#round()函數,四捨五入
print(round(1.49)) #1
print(round(1.59)) #2
#isalpha()函數,判斷字符串中有沒有數字
s = 'syy'
print(s.isalpha()) #True
s = 'syy123'
print(s.isalpha()) #False
#數據類型的轉換
str()
int()
float()
set()
list()
dict()
tuple()
bool()
get()
open()
bytes()
面向過程編程
# 面向過程編程
就相似於設計一條流水線
#好處
將複雜的問題流程化、簡單化
#壞處
可擴展性差,一旦修改,總體都會搜到影響
#註冊功能
1.獲取用戶輸入(前端)
2.處理用戶信息(後端)
3.存儲到文件(數據庫)
def get_info():
while True:
username = input('請輸入你的用戶名>>>: ').strip()
if not username.isalpha():
print('用戶名不能包含數字')
continue
password = int(input('請輸入你的密碼>>>: ').strip())
confirm_password = int(input('請再次確認你的密碼>>>: ').strip())
if password == confirm_password:
operate_data(username,password)
print('註冊成功')
break
else:
print('2次輸入密碼不一致')
continue
def operate_data(username,password):
res = '%s|%s\n'%(username,password)
save_data(res,'filename')
def save_data(res,filename):
with open(r'filename','a',encoding='utf-8') as f:
f.write(res)
get_info()