裝飾器、生成式、迭代器

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()
相關文章
相關標籤/搜索