# 全局變量
""" 全局變量: global關鍵字添加 只有不可變的類型才需要添加global int float str bool () 可變的類型不需要添加global list dist set() 列表、字典、集合 局部變量: 僅限於函數內部 可變和不可變: 可變: list dist set() 列表、字典、集合 不可變: 當改變變量的值,地址發生改變,就認為此類型不可變: int float str bool () """
# 不可變 int float str bool ()
a = 1
print(id(a))
a = 2
print(id(a))
a = ''
print(id(a))
a = 'str'
print(id(a))
a = (1, 2, 3)
print(id(a))
a = (1, 2)
print(id(a))
# 可變
a = [1, 2, 3]
print(id(a))
a.remove(3)
print(id(a))
print('局部變量和全局變量'.center(30, '-'))
x = 100
# 局部
def pr():
x = 8
y = 10
print(x)
print(y)
# 全局
def pr2():
print(x)
# 修改全局
def pr3():
global x # 必須聲明了才可以動
x = x - 80 # 不能輕易動全局變量
print(x)
pr()
pr2()
pr3()
pr2()
# 局部變量
""" 可變參數 *args :默認裝進一個元組();就是一個容器 *kwargs argument 一顆星:* 拆裝包 裝包: def 函數(*arg): ---------->此時會出現裝包操作 pass 拆包:list、tuple、set 函數調用時:函數(*list)|函數(*tuple)|函數(*set) print(sm(1, *ram_lst)) # 調用加一個* 拆包 拆包過程 兩顆星:** #<class 'dict'> *kwargs:key word 關鍵字參數 關鍵字參數賦值才可以;只要不是關鍵字參數會報錯 只有傳遞參數時key=value形式,才可以裝包放進放到字典中 只有** 才會裝包 """
# 多參數:求和
def sm(a, *args):
print(type(args)) # args:是元組 <class 'tuple'>
return a + sum(args)
print(sm(1, 2, 3, 4, 5))
x, *y, z = 1, 2, 3, 4, 5
print(x, y, z) # 默認是放到列表中:1 [2, 3, 4] 5
# 拆包
x, y, z = (7, 8, 9)
print(x, y, z)
# 先拆包、後裝包
x, *y, z = (7, 8, 9, 2, 3, 4, 5) # 先拆包、後裝包
print(x, y, z)
# 列表中元素的和
ram_lst = [12, 4, 6, 8, 345, 678, 24, 67, 1, 23]
print(sum(ram_lst))
print(sm(1, *ram_lst)) # 調用加一個* 拆包
print("兩顆星:**".center(30, "—"))
def show_book(**kwargs): # <class 'dict'> # 關鍵字參數賦值才可以;只要不是關鍵字參數會報錯
print(type(kwargs))
print(kwargs)
for k, v in kwargs.items():
print(k, v, sep='->')
# 字典裝包
show_book(name='張三', age=18, sex='男') # 關鍵字參數賦值才可以;只要不是關鍵字參數會報錯
# 字典拆包
book = {
'name': '西游記', 'author': '曹雪芹', 'number': 5}
show_book(**book) # 拆包
print("單星* 和兩顆星:**都存在".center(50, "—"))
def show_all_book(*args, **kwargs):
print(type(args))
print(type(kwargs))
print(args) # ()
print(kwargs) # {}
book = {
'name': '紅樓夢', 'author': '曹雪芹'}
show_all_book('張三', '李四', **book)
show_all_book('張三', '李四', **{
'name': '紅樓夢', 'author': '曹雪芹'}) # 只有** 才會裝包
print('{}{}{}'.format('AA', 'BB', 'CC'))
print('{name}->{age}'.format(**{
'name': '張三', 'age': 18}))
result = '#'.join('A', 'B', 'C')
print(result)
# 參數:就是在調用函數時,就是向函數中傳值的作用
""" 無參: def 函數名() pass 有參: def 函數名(參數1,參數2,參數3) 函數體 pass 帶多個參數的函數: 多個參數 默認值、關鍵字參數 默認值參數:(屬於缺省參數,) def 函數名(參數1,參數2,參數3=值) pass def 函數名(參數1,參數2,*args,參數3=值) pass 調用可以不給默認值參數賦值: 函數名(值1,值2) 注意: 定義函數:普通參數要位於默認參數之前 正確:def 函數名(參數1,參數2,參數3=值) 錯誤:def 函數名(參數1,參數3=值,參數2) """
# 最多登錄三次:retry_num:重試次數,默認三次
def login(retry_num=3):
error_num = 1
while error_num <= retry_num:
username = input('請輸入用戶名:')
password = input('請輸入密碼:')
if 'admin'.__eq__(username) and '1234'.__eq__(password):
return '登錄成功'
else:
if retry_num - error_num > 0:
print('用戶名或者密碼錯誤允許錯誤{}次,還有{}次'.format(retry_num, retry_num - error_num))
error_num += 1 # 每錯一次加1
else:
break
return '用戶名或者密碼錯誤次數過多,請稍後重試!'
rst = login(4)
print(rst)
''' 求 1-n之間和;但是n必須是參數 '''
def sm(n):
return sum(i for i in range(n + 1))
# 兩個數求和
def get_sm(a, b):
if type(a) == type(b) and isinstance(a, int) and isinstance(b, int): # isinstance:類型判斷
return a + b
else:
return "類型不一致!"
# 調用
print(sm(100))
print(get_sm(1, 2))
# 借書
1. 什麼是函數
# 函數基本操作
import random
""" 函數:復用 定義調用: def 函數名([參數,...]): # [] 代表可有可無 代碼 函數名: get_name() 多個單詞下劃線分割 search() 單詞 代碼: 封裝重復內容 調用機制:(函數名) 1、先加載導內存 2、使用必須調用 注意: 1. 參數傳遞:類型屬於對象,對象有不同類型的區分,變量是沒有類型的: 2. 默認參數的順序都是固定的,在賦值如果順序不固定,需要關鍵字參數:參數名=value 如 login(name, password='1234') 參數: 單參數、多參數 形參、實參 """
# 函數也是一個變量
def create_verification_code():
code = ''
while len(code) < 4:
result = random.randint(0, 127)
if ord('a') <= result <= ord('z') or ord('A') <= result <= ord('Z'):
code += chr(result)
elif 0 <= result <= 9:
code += str(result)
print(code)
print(create_verification_code) # <function create_verification_code at 0x00000218317180D8>:函數也是一個變量,分配內存空間
# 驗證函數是否可用
create_verification_code()
''' 定義一個login函數 admin 1234 輸入用戶名密碼驗證正確 '''
# 定義一個登錄函數
def login(username, password, is_remember=False): # 默認值參數
if 'admin'.__eq__(username) and '1234'.__eq__(password):
return '登錄成功'
else:
return '用戶名或者密碼錯誤,登錄失敗!'
name = input('請輸入用戶名:')
pwd = input('請輸入密碼:')
rst = login(name, pwd)
print(rst)
rst = login(name, password='1234') # 默認參數賦值
print(rst)
# 形參、實參
library = ['西游記', '紅樓夢', '三國演義', '水浒傳']
# 添加書
def add_book(book_name):
library.append(book_name)
# 打印書
def show_book(books):
for book in books:
print(book)
add_book('明清那些事') # 添加書
print(show_book(library))
2. 函數參數注釋
# 函數參數說明
""" 函數參數說明: def 函數名(參數1、參數2、參數3...): 基本注釋 ”注釋內容“ 高級注釋: ”“” 參數說明: :param username: 用戶名 :param password: 密碼 返回值說明: :return: 是否登錄成功 “”“ """
def login(username, password):
""" 用戶名密碼登錄 :param username: 用戶名 :param password: 密碼 :return: 返回成功、失敗 """
if username == 'admin' and password == '1234':
"返回成功後業務邏輯"
print("登錄成功!")
else:
"返回失敗後業務邏輯"
print("登錄失敗!")
login("admin", "1234")
練習
# 練習 函數文檔注釋
""" 局部變量:臨時保存數據,函數調用完就回收 全局變量:外側,(global) 注意: 變量同名問題,局部變量>全局變量 """
import datetime
lst = ['西游記', '紅樓夢', '三國演義', '水浒傳']
def show_book(books):
return [book for book in books if book == '三國演義'] # 列表推導式
print(show_book(lst))
num_lst = [1, 4, 90, 35, 79, 34, 89, 12, 90, 34, 89, 26, 90, 99]
# 刪除小於50
def remove_element():
[num_lst.remove(n) for n in num_lst[::-1] if n < 50] # 造成遺漏所以反向刪除,那樣即使下標變化不影響整體結果
print(num_lst)
remove_element() # 刪除小於50
print(num_lst)
print('函數使用練習'.center(50, '-'))
''' 需求: 驗證時候登錄:is_login 自定義一個函數is_login: 參數:username 、password 函數體: 判斷用戶輸入的用戶名和密碼是否正確,如果正確則返回True,否則返回False 借書:定義一個函數borrow_book 參數:書名:book_name 函數體: 判斷是否登錄,如何登錄則可以借書 如果沒有登錄則提示:還未登錄不能借書 '''
# 是否登錄
is_rem = False
def is_login(username, password, is_remember=False):
global is_rem # 使用了全局變量名
if username == 'admin' and password == '1234':
is_rem = is_remember
return True
else:
return False
# 借書
def borrow_book(book_name):
if is_rem or login():
print("登錄成功,成功借閱%s!" % book_name)
else:
print("未登錄不能借書,請登錄!")
n = 3
while n > 0:
if login():
print("登錄成功,您可以借書了!")
else:
n -= 1
print("用戶名/密碼錯誤,您還有{}次重試機會!".format(n))
def login():
name = input("請輸入用戶名:")
pwd = input("請輸入密碼:")
is_remember = bool(input("是否記住用戶名密碼(True/False):"))
# 登錄
return is_login(name, pwd, is_remember)
# 借書
borrow_book('紅樓夢!') # 第一次需要登錄,可以is_remember 不輸入或者輸入True
borrow_book('西游記!') # 不需要再登錄了
''' 全局變量: 停車費: 1小時4塊錢、計算停車費 15分鐘一塊錢 {車牌:[進入時間,離開時間]} def enter(): # 鍵盤輸入車牌號 pass def go_out(): # 鍵盤輸入車牌號 pass def car_billing(): # 計費 pass '''
start_time = datetime.datetime.now()
end_time = datetime.datetime.now()
# car_park = [{'陝A1234': [start_time, end_time]}]
car_park = []
def enter():
""" 進入停車場:開始計費 :return: NONE """
print("歡迎進入xxx停車場".center(30, '-'))
car_num = input('鍵盤輸入車牌號:')
global start_time
start_time = datetime.datetime.now()
print(start_time)
car_info = {
car_num: [start_time, end_time]}
car_park.append(car_info)
print("{}已經進入停車場".format(car_num))
def go_out():
""" 出車計費 :return: 返回計費信息 """
print("退出xxx停車場".center(30, '-'))
car_num = input('鍵盤輸入車牌號:')
global end_time
global car_park
global end_time
for car in car_park:
if isinstance(car, dict): # 可以替換(字典默認和key 比較): for car_num in car
# 字典默認和key 比較
for key in car.keys():
if car_num == key:
end_time = datetime.datetime.now()
car.update({
key: [start_time, end_time]})
print(car_billing(car_num))
def car_billing(car_num):
spend_time = 0
for car in car_park:
if isinstance(car, dict):
car_time = car.get(car_num)
print(car_time)
if isinstance(car_time, list):
print(car_time[1], car_time[0])
spend_time = car_time[1] - (car_time[0])
print("spend_time:", spend_time)
return '停車時常{},總車費{}。'.format(spend_time, spend_time / 60 * 4)
enter()
go_out()
# 匿名函數 + 高級函數
""" 匿名函數定義: lambda 參數列表:運算表達式 可以接受任何參數,但是只能返回一個表達式的值 使用場景:高階函數(一個函數的參數是另一個函數,俗稱高階函數) 1. 匿名函數作為參數使用 2. 系統高階函數:max min sorted 3. filter(匿名函數要求返回bool類型,且bool 類型為真才是過濾) 4. map:提取、加工數據,組成迭代 5. reduce 6. zip """
from functools import reduce
def su(a):
return a + 1
print(su)
print(su(5))
r = lambda b: b + 1
print(r)
print(r(5))
print("匿名函數:使用場景->高級函數".center(30, "-"))
def test(n):
print("-------test----->", n)
def func(a, f):
print("----func---->", a)
f(a)
func(6, test)
print("--------------------------------------------------")
print("-------------匿名函數作為參數使用------------")
def func1(a, f):
print("++++++++++", a)
print("=========>", f(a))
func1(5, lambda x: x ** 2) # 匿名函數作為參數傳遞
print("-------------系統高階函數------------")
lst = [("tom", 20), ("Tony", 23), ("rose", 30), ("Lily", 10)]
result = max(lst, key=lambda x: x[1])
print(result)
result = min(lst, key=lambda x: x[1])
print(result)
result = sorted(lst, key=lambda x: x[1])
print(result)
result = sorted(lst, key=lambda x: x[1], reverse=True) # 從達到小
print(result)
result = filter(lambda x: x[1] > 18, lst) # filter過濾
print(list(result))
result = map(lambda x: x[1] + 1, lst) # map 映射,提取出來
print(result)
print(list(result))
result = map(lambda x: x[0].title(), lst) # map 映射,提取,加工出來
print(result)
print(list(result))
resu = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]) # 就是一種運算
print(resu)
result = zip(lst)
print(result)
# 函數返回值
""" 參數:外界向裡面傳值 返回值:裡面的內容向外界傳值 def 函數名(參數名): 函數體 return 返回值 調用: 通告return 向外返回值;只要返回就需要接受數據 注意:Python獨有的特性: 返回多個值:會以元組形式返回(a,b) return:可以結束調用 """
def get_sum(*args):
return sum(args)
print(get_sum(*[1, 1, 2, 3, 4, 5])) # 解包
lst = [1, 3, 2, 9, 4, 5, 13, 56, 34, 23, 67]
# 求最大最小值:返回兩個值:元組()
def get_max_min(num_lst):
return min(num_lst), max(num_lst)
print(get_max_min(lst)) # (1, 9)
a, b = get_max_min(lst)
print(a, b) # (1, 9)
print('冒泡排序'.center(30,'-'))
# 冒泡排序
for i in range(len(lst) - 1):
for j in range(len(lst) - i - 1):
if lst[j] > lst[j + 1]:
lst[j], lst[j + 1] = lst[j + 1], lst[j]
print("升序:", lst)
for i in range(len(lst) - 1):
for j in range(len(lst) - i - 1):
if lst[j] < lst[j + 1]:
lst[j], lst[j + 1] = lst[j + 1], lst[j]
print("降序:", lst)
# 遞歸函數
""" 文件遍歷 """
# 1-10 數字的累加
def count(n):
if n > 0:
n -= 1
else:
return n # 考慮結束
return n + count(n)
print(count(10 + 1)) # 通過遞歸求1-10 的和
print(count(100 + 1)) # 通過遞歸求1-100 的和
print("遞歸實現斐波那契數列".center(30, '-'))
# 遞歸實現斐波那契數列,並打印
def fibonacci(n):
if 0 < n <= 2:
return 1
result = fibonacci(n - 1) + fibonacci(n - 2)
return result
for i in range(1, 10):
print("------------>", fibonacci(i))
# 函數閉包+嵌套
"""" 嵌套: 注意: 1. 內部函數可以使用外部函數的變量 2. 內部函數不能修改外部函數的變量,nonlocal a 可以修改外部函數變量需要再內部函數中,添加nolocal 閉包:(函數、變量都是如下順序) 內層函數-------> 全局函數--------->外層函數-------->系統函數(builtins) 閉包三個特點: 1. 嵌套函數 2. 內部函數引用了外部函數的變量 3. 返回值是內部函數 使用場景: 裝飾器使用 """
def outer():
a = 100
def inner():
nonlocal a # 引用外函數變量
b = 200
b += a
a += b
print("我是內函數!", b)
result = locals() # 局部變量查看,以字典形式返回:{'a': 100, 'inner': <function outer.<locals>.inner at 0x00000247463281F8>}
print(result)
print(a)
print(inner) # <function outer.<locals>.inner at 0x0000017531E381F8>
inner() # 調用
print(a) # a 被 nonlocal 局部函數修改
return inner
r = outer() # <function outer.<locals>.inner at 0x00000236F60381F8>
print(r)
print("閉包".center(30, '*'))
r() # 調用內部函數
# 裝飾器
""" 裝飾器: 原則:遵循開放封閉原則,在不改變原函數的情況下,擴展了函數功能 特點: 1. 日志、權限校驗、緩存 2. 統計 定義: def aaa(func): def xxx(參數,...): .... func() ... return xxx 裝飾: @aaa def 原函數(): pass 代參數裝飾器:*arg,**kwargs 原函數有參數,裝飾器必須也有參數 *arg:可變參數 **kwargs:關鍵字參數 裝飾器修飾有返回值的函數: 原函數有返回值,wrapper中必須有返回值 再入裝飾器: """
def foo():
print("foo")
def func():
print("func")
foo = func # 函數名僅僅是一個變量,相當於變量賦值,地址發生改變
foo()
print("裝飾器".center(20, "#"))
def deco_house(fu):
""" 1. 定義裝飾器:裝修房子 :param fu : 被裝飾著的引用 :return wrapper : 返回被裝飾後的對象 的地址 ;相當於house_a 裝飾前後的地址發生變化 相當於house_a = house-----地址指向發生改變----->house_a = wrapper """
def wrapper():
fu()
print("安裝家電----->")
print("安裝床沙發----->")
print("精裝修完成----->")
return wrapper # 返回內部函數
@deco_house # 就會調用deco_house函數--->house_a = deco_house(house_a)
def house_a():
print("毛坯房A")
@deco_house
def house_b():
print("毛坯房B")
house_a()
house_b()
print("帶參數的裝飾器".center(30, '*'))
def de_house(fu):
def wrapper(*args, **kwargs): # wrapper() got an unexpected keyword argument 'name':(name="香格裡拉大酒店") 修改添加**kwargs
fu(*args, **kwargs) # fu 就是house;元組拆包(帶星拆元組):*args
print("安裝家電----->")
print("安裝床沙發----->")
print("精裝修完成----->")
return wrapper # 返回內部函數
@de_house
def house(address):
print("房子的地址在:{},是一個毛坯房".format(address))
@de_house
def chang_fang(address, area):
print("房子的地址在:{},是一個毛坯房。建築面積是:{}平米".format(address, area))
@de_house
def hotel(name, address, area=40):
print("{}的地址在:{},是一個毛坯房。單間建築面積是:{}平米".format(name, address, area))
house("西安鐘樓")
print("--------------------------")
chang_fang("西安雁塔區", 130)
print("------------默認參數--------------")
hotel("全季大酒店", "西安雁塔區")
print("------------指定默認參數--------------")
hotel("全季大酒店", "西安雁塔區", 80)
print("----------關鍵字參數----------------")
hotel(name="全季大酒店", address="西安雁塔區", area=80)
print("----------關鍵字參數:修改順序----------------")
hotel(address="西安高新區", name="香格裡拉大酒店", area=150)
print("裝飾器修飾有返回值的函數".center(30, '*'))
def make_house(fu):
def wrapper(*args, **kwargs): # wrapper() got an unexpected keyword argument 'name':(name="香格裡拉大酒店") 修改添加**kwargs
r = fu(*args, **kwargs) # fu 就是house;元組拆包(帶星拆元組):*args
print("預計裝修費用是:{}元".format(r))
print("安裝家電----->")
print("安裝床沙發----->")
print("精裝修完成----->")
return r # 原函數有返回值,wrapper中必須有返回值
return wrapper
@make_house
def new_house():
print("毛坯房....")
return 50000
result = new_house()
print(result)
# 函數復習
import sys
""" 函數返回值 : return return 返回一個或者多個值,也可以單獨使用return關鍵字 return :表示函數結束調用 類似於break;是不過 break 中斷當前循環還會執行循環後面的操作,而return 直接結束函數,後面不執行 return a return a,b ------------>(a,b) 全局變量和局部變量 全局變量 1. 什麼是全局變量、全局變量的位置 全局變量可以直接用,但是不能再函數中修改 2. 全局變量是不可變類型: 不可再函數中修改,如果要修改必須加global 關鍵字聲明 3. 全局變量是可變類型 函數中可以修改 4. globals() 函數:可以查看全局變量 局部變量(函數): 1. 函數內部定義的便令 2. 使用范圍僅限函數內部;當函數調用結束就會回收變量(生命周期就在內部) 3. 通絡 locals 查看局部變量----> 字典 4. 內部函數也可以看成局部變量 可變參數和不可變參數: 當前的值和地址的關系: 可變:值變了,地址沒變; dict list set 不可變:值變了 地址也變了; int str bool tuple float 地址引用:傳遞一個地址 1. 普通的賦值關系: 調函數也會出現一次引用 2. 函數參數 函數參數類型是什麼:可變還是不可變 函數嵌套: 閉包(裝飾器): 1. 必須是嵌套函數 2. 內部函數引用外部函數變量 3. 返回值是內部函數 """
print(globals()) # 查看全局變量:返回格式字典:1.系統的全局變量 2. 自定義的全局變量
lst = [1, 2, 3]
lst1 = lst
print(sys.getrefcount(lst1)) # 因為調用會引用一次,所以結果是3
# 總結
""" 函數: 作用域:LFGB L: local 本地 局部變量 F:encloseing 嵌套 G:Global 全局 B:built-in 內置函數 嵌套函數: 閉包: 1. 內層函數 2. 內層函數引用外層函數的變量 3. 返回內層函數 4. 函數作為外層函數的參數 使用裝飾器: @ 裝飾器名 def 函數名(): pass # 總結函數 普通函數 1. 無參數: def func(): pass 2. 有參數 一般參數: def func(a,b): pass 可變參數: def func(*args,**kwargs): args 單個元素; kwargs:關鍵字參數 pass func() 、func(1) 、func(a=1) 默認值: def func(a=1,b=2): pass func(a=100) #關鍵字參數 func(900) #默認給a賦值 3. 返回值 沒有返回值 def func(): pass x = func() ------->X=None 有返回值: def func(): return 'a','b' # 返回多個值 x = func() ---------> x= ('a','b') 嵌套函數:------->閉包--------> 裝飾器 1.閉包: def func(): def wrapper(): pass return wrapper() 2. 裝飾器: 單層裝飾器: def decorate(func): def wrapper(*args,**kwargs): # 有參數和無參數都可以 pass return wrapper @decorate def house(): pass @decorate() def new_house(a,b): 多層裝飾器: @deco2() @deco1() def func(a,b): pass 裝飾器帶參數: def outer(a): def decorate(func): def wrapper(*args,**kwargs): pass return wrapper return decorate @outer(10) def house(10): pass @outer(100) def house(10): pass 匿名函數:lambada 函數:返回值 遞歸函數:自己調用自己 變量的作用域: global nonlocal globals locals LFGB """