1. 程式人生 > >函式物件,函式巢狀,名稱空間與作用域,閉包函式

函式物件,函式巢狀,名稱空間與作用域,閉包函式

函式是第一類物件: 指的是函式名指向的值(函式)可以被當作資料去使用

def func(): # func=函式的內地址
print('from func')

print(func)

age=10
1. 可以被引用
x=age
print(x,age)

f=func
print(f)
f()

2. 可以當作引數傳給另外一個函式
def bar(x):
print(x)

bar(age)
bar(func)

3. 可以當作一個函式的返回值
def bar(x):
return x

res=bar(age)
print(res)

res=bar(func)
print(res)

4. 可以當作容器型別的元素
l=[age,func,func()]

print(l)


def login():
print('login')

def register():
print('register')

def shopping():
print('shopping')

def pay():
print('pay')


def transfer():
print('transfer')

func_dic={
'1':login,
'2':register,
'3':shopping,
'4':pay,
'5':transfer
}
# print(func_dic)

msg="""
0 退出
1 登陸
2 註冊
3 購物
4 支付

5 轉賬
"""

while True:
print(msg)
choice=input('請輸入您的操作: ').strip()
if choice == '0':break
# if choice == '1':
# login()
# elif choice == '2':
# register()
# elif choice == '3':
# shopping()
# elif choice == '4':
# pay()
# else:
# print('輸入錯誤指令,請重新輸入')

if choice in func_dic:
func_dic[choice]()
else:
print('輸入錯誤指令,請重新輸入')



函式巢狀分為兩大類

一:函式的巢狀呼叫:在呼叫一個函式過程中,其內部程式碼又呼叫了其他函式
def bar():
print('from bar')

def foo():
print('from foo')
bar()

foo()

def max2(x,y):
if x > y:
return x
else:
return y

def max4(a,b,c,d):
res1=max2(a,b)
res2=max2(res1,c)
res3=max2(res2,d)
return res3

print(max4(1,2,3,4))

二:函式的巢狀定義:一個函式內部又定義了另外一個函式
def outter():
x=1
print('from outter')
def inner():
print('from inner')
# print(x)
# print(inner)
inner()

# outter()
# inner

outter()

def f1():
print('from f1')
def f2():
print('from f2')
def f3():
print('from f3')
f3()
f2()

f1()



1 什麼是名稱空間namespace
名稱空間就是用來存放名字與值記憶體地址繫結關係的地方(記憶體空間)

age=18
但凡查詢值一定要通過名字,訪問名字必需去查詢名稱空間


2 名稱空間分為三大類
內建名稱空間:存放的是python直譯器自帶的名字
例如:
len
max
print

全域性名稱空間:存放的是檔案級別的名字
例如:以下名字中x\y\z\b\foo都會存放於全域性名稱空間中
x=1
y=2
if x == 1:
z=3

while True:
b=4
break

def foo():
m=3

區域性名稱空間:在函式內定義的名字
例如:
foo內的m這個名字一定是存放於一個區域性名稱空間中


生命週期:
內建名稱空間:在直譯器啟動時則生效,直譯器關閉則失效
全域性名稱空間:在直譯器解釋執行python檔案時則生效,檔案執行完畢後則失效
區域性名稱空間:只在呼叫函式時臨時產生該函式的區域性名稱空間,改函式呼叫完畢則失效

載入順序:
內建->全域性->區域性

查詢名字的順序:
基於當前所在位置往上查詢
假設當前站在區域性,查詢順序:區域性->全域性->內建
假設當前站在全域性,查詢順序:全域性->內建





案列一:
# len=111

def foo():
len=222
print(len)

foo()
print('站在全域性找len: ',len)


x=111

def f1():
x=222
def f2():
def f3():
# x=444
print(x)
x=333
f3()
f2()
f1()

(******)名字的查詢順序,在函式定義階段就已經固定死了(即在檢測語法時就已經確定了名字的查詢順序),與函式的呼叫位置無關,也就是說無論在任何地方呼叫函式,都必須回到
當初定義函式的位置去確定名字的查詢關係

案列二:
x=111
def outer():
def inner():
print('from inner',x) # x訪問的時全域性名稱空間中x
return inner

f=outer()
# print(f)

x=222
f()


案列三:
x=111
def outer():
def inner():
print('from inner',x) # x訪問的時全域性名稱空間中x
return inner

f=outer()

# x=222
def func():
x=333
f()

x=444

func()


案列四:
x=111
def outer():
def inner():
print('from inner',x) # x是來自於當前層的名字
x=2222222222
return inner

f=outer()

f()


作用域:
域指的是範圍,作用域指的就是作用的範圍,分為兩種
全域性作用域:包含的是內建名稱空間與全域性名稱空間中的名字
特點:全域性有效,全域性存活

區域性作用域:包含的是區域性名稱空間中的名字
特點:區域性有效,臨時存活


x=1

def foo():
y=2
print(x)

def bar():
print(x)

foo()
bar()


global,nonlocal

x=1
def foo():
x=2

foo()
print(x)


l=[]
def foo():
l.append(1)
# l=33333
foo()
print(l)

global:在區域性宣告一個名字是來自於全域性作用域的,可以用來在區域性修改全域性的不可變型別
x=1
def foo():
global x
x=2

foo()
print(x)

nonlocal:宣告一個名字是來自於當前層外一層作用域的,可以用來在區域性修改外層函式的不可變型別
x=0
def f1():
x=111
def f2():
# global x
nonlocal x
x=222
f2()
print(x)

f1()
print(x)




1 什麼是閉包函式
閉:指的是閉包函式是定義在一個函式內部的函式
包:該內部函式包含對外層函式作用域名字的引用

需要結合函式物件的概念將閉包函式返回到全域性作用域去使用,從而打破函式的層級限制
def outter():
x=111
def inner():
print(x)
return inner

f=outter() #f=outter內的inner

# x=22222
# f()
def func():
x=3333
f()

func()
2 為何要用閉包函式
閉包函式提供了一種為函式體傳值的解決方案

3 如何用閉包函式



為函式體傳值的方式一:引數
def func(x,y):
print(x+y)

func(1,2)

為函式體傳值的方式二:閉包
def outter(x,y):
# x=1
# y=2
def func():
print(x+y)
return func

f=outter(1,2)
f()
f()
f()

pip3 install requests

import requests

需求
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)


解決方案一:引數
def get(url):
response=requests.get(url)
if response.status_code == 200:
print(len(response.text))

get('https://www.baidu.com')
get('https://www.baidu.com')
get('https://www.baidu.com')
get('https://www.tmall.com')
get('https://www.tmall.com')

url1='https://www.baidu.com'
url2='https://www.tmall.com'

get(url1)
get(url1)
get(url1)

get(url2)
get(url2)
get(url2)





解決方案二:閉包
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
if response.status_code == 200:
print(len(response.text))
return get

baidu=outter('https://www.baidu.com')
baidu()
baidu()
baidu()

tmall=outter('https://www.tmall.com')
tmall()
tmall()
tmall()