1. 程式人生 > >week3 函數知識整理

week3 函數知識整理

alex 方式 code wap 字母 都是 war 形參 出現

一、函數的定義:

定義:def 關鍵詞開頭,空格之後接函數名稱和圓括號(),最後還有一個":"。

   def 是固定的,不能變,必須是連續的def三個字母,不能分開。。。

   空格 為了將def關鍵字和函數名分開

   函數名:必須由字母下劃線數字組成,不能是關鍵字,不能是數字開頭,函數名還是要有一定的意義能夠簡單說明函數的功能

   括號:是必須加的

註釋:每一個函數都應該對功能和參數進行相應的說明,應該寫在函數下面第一行。以增強代碼的可讀性。

調用:就是 函數名() 要記得加上括號

def 函數名(參數1,參數2,*args,默認參數,**kwargs):
        """註釋:函數功能和參數說明
""" 函數體 …… return 返回值

二、函數的返回值


1.return xxx  返回一個值(一個變量)
2.return a,b 返回多個值(多個變量),多個值之間用逗號區分
接收:可以用一個變量接收,以元組的形式返回
也可以用多個變量接收,返回幾個就用幾個變量去接收
3.返回值為None
函數的返回值為None有三種情況
a.不寫返回值
b.只寫一個return
c.return None (幾乎不用)

return的作用:結束一個函數的執行

函數的返回值不為None,有返回值

def
func(): a = 111 b = [1,2,3] #首先 返回值可以是任意的數據類型 return b #如果有返回值:必須要用變量接收才會有效果 # ret = func() # print(ret) def func1(): a = 111 b = [1,2,3] # ret = func1() # print(ret) #函數可以沒有返回值 #當不寫return的時候,一個函數默認的返回值是‘None‘ def func2(): a = 111 b = [1,2,3] return # ret = func2()
# print(ret) #當只寫一個return的時候,函數的返回值為None def func3(): a = 111 b = [1,2,3] return None # ret = func3() # print(ret) #return None的時候函數的返回值也為None(幾乎不用) def func4(): print(1111) return print(2222) # func4() def func5(): for i in range(20): if i == 5: return else: print(i) # func5() #函數要先定義 後 調用 def func6(): ‘‘‘返回一個值‘‘‘ #return 111 #return ‘abc‘ return [abc,123] def func7(): ‘‘‘返回多個值‘‘‘ a = 123 b = abc return a,b,[1,2,3] # ret = func7() # print(ret) # m,n,k = func7() # print(m) # print(n) # print(k) def func8(): l = [1,2,3,4] return l[-1] # ret = func8() # print(ret)

三、參數:

1.實參:函數調用時我們傳入的參數就叫做實參

2.形參:函數定義時我們定義的參數就叫做形參

站在實參的角度看:

參數有位置參數和關鍵字參數

註意:位置參數必須放在關鍵字參數前面

#位置參數
def fun(a,b):
    print(a,a,"b",b)
    if a>b:
        return a
    else:
        return b
#位置參數
l1=fun(10,20)
#關鍵字參數
l2=fun(a=20,b=10)
print(l1)
print(l2)
__author__ = ctz
def fun(name,addr,sex="male"):
    return name,addr,sex
a=fun("ctz","km")
b=fun(name="cmq",addr="xw",sex="female")
c=fun("sss",addr="bj")
d=fun(addr="sss",name="ccc")
print(a)
print(b)
print(c)
print(d)
__author__ = ctz
def fun(name,addr,sex="male"):
    return name,addr,sex
#位置傳參
a=fun("ctz","km")
#關鍵字傳參
b=fun(name="cmq",addr="xw",sex="female")
#位置傳參和關鍵字傳參混用
c=fun("sss",addr="bj")
#關鍵字傳參
d=fun(addr="sss",name="ccc")
print(a)
print(b)
print(c)
print(d)

動態傳參

def fun2(*args):#*args代表把散列的元素拼成元組
    print(args)
t = (1,2,3,4)
l = [1,2,3,4]
# fun2(t[0],t[1],t[2],t[3])
fun2(*t)  #*代表把一個元組、列表拆了
fun2(*l)  #*代表把一個元組、列表拆了

def fun3(**kwargs):#*args代表把按關鍵字傳來的參數拼成字典
    print(kwargs)
fun3(a = 10, b = 20)
d = {a: 10, b: 20}
fun3(**d)  #*代表把一個字典拆了

站在形參角度看

可以傳遞0個或多個參數,
傳參順序必須為:位置參數,*args,默認參數,**kwargs
傳參數的時候:必須先按照位置傳參數,再按照關鍵字傳參數
 

1.位置參數必須傳值,按順序定義參數

def mymax(x,y):
    #此時x = 10,y = 20
    print(x,y)
    the_max = x if x > y else y
    return the_max

#調用mymax不傳遞參數
ma = mymax()
print(ma)

#結果
TypeError: mymax() missing 2 required positional arguments: x and y
2.默認參數
首先,不要設置可變數據類型的默認參數 對於變化小的參數可以設置默認參數 默認參數可以不傳,不傳的時候用的就是默認值 如果傳,會覆蓋默認值 默認的值是在定義函數的時候就已經確定了的

def stu_info(name,sex = "male"):
    """打印學生信息函數,由於班中大部分學生都是男生,
        所以設置默認參數sex的默認值為‘male‘
    """
    print(name,sex)


stu_info(alex)
stu_info(eva,female)

3.動態參數:

a.*args

按位置傳值多余的參數都由args統一接收,保存成一個元組的形式

def func(a,b,*c):
    my_sum = a+b
    for i in c:
        my_sum += i
    return my_sum

#按位置傳參數
# print(func(3,2))
# print(func(1,2,5,6))

b.**kwargs

def fun(a,b,**kwargs):
    print(a,b,kwargs)

# 按照關鍵字傳參數
#fun(a = 10,b = 20,cccc= 30,dddd = 50)

四、函數的命名空間

命名空間一共分為三種:

  全局命名空間

  局部命名空間

  內置命名空間

*內置命名空間中存放了python解釋器為我們提供的名字:input,print,str,list,tuple...它們都是我們熟悉的,拿過來就可以用的方法。

三種命名空間之間的加載與取值順序:

加載順序:內置命名空間(程序運行前加載)->全局命名空間(程序運行中:從上到下加載)->局部命名空間(程序運行中:調用時才加載)

取值:

  在局部調用:局部命名空間->全局命名空間->內置命名空間

x = 1
def f(x):
    print(x)

print(10)

在全局調用:全局命名空間->內置命名空間

def fun(a,b,c):
    return max(a,b,c)#用的是內置命名空間的max
print(fun(1,2,3))


def max(a,b):
    c=a  if a>b else b
    return c
print(max(1,5))#用的1是自己定義的max 全局作用域裏面的

五、函數的作用域:

作用域

作用域就是作用範圍,按照生效範圍可以分為全局作用域和局部作用域。

全局作用域:包含內置命名空間、全局命名空間,在整個文件的任意位置都能被引用、全局有效

局部作用域:局部命名空間,只能在局部範圍生效

小範圍的可以用大範圍的,但是大範圍的不能用小範圍的

範圍從大到小在小範圍內,如果要用一個變量,是當前這個小範圍有的,就用自己的如果在小範圍內沒有,就用上一級的,上一級沒有就用上上一級的,以此類推。如果都沒有,報錯

globals和locals方法

a = 20
b = 50
def haha():
x = 1
y = 2
print(globals()) #全局作用域中的名字
print(locals()) #局部作用域中的名字

# haha()
# print(globals()) #全局作用域中的名字
# print(locals()) #全局的局部還是全局

global關鍵字

a = 10
def func():
    global a
    a = 20

print(a)
func()
print(a)

六、函數的嵌套和作用域鏈

函數嵌套

def f1():
    def f2():
        def f3():
            print("in f3")
        print("in f2")
        f3()
    print("in f1")
    f2()
    
f1()

函數作用域鏈

def f1():
    a = 1
    def f2():
        def f3():
            print(a)
        f3()
    f2()

f1()
def f1():
    a = 1
    def f2():
        a = 2
    f2()
    print(a in f1 : ,a)

f1()

nonlocal關鍵字

def f():
    a = 3
    def f1():
        a = 1
        def f2():
            nonlocal a
            # 1.外部必須有這個變量
            # 2.在內部函數聲明nonlocal變量之前不能再出現同名變量
            # 3.內部修改這個變量如果想在外部有這個變量的第一層函數中生效

            a = 2
        f2()
        print(a in f1 : , a)
    f1()
    print(a in f : ,a)

f()

七、函數名的本質

函數名本質上就是函數的內存地址

1.可以被引用

def func():
    print(in func)

f = func
print(f)

2.可以被當作容器類型的元素

def f1():
    print(f1)


def f2():
    print(f2)


def f3():
    print(f3)

l = [f1,f2,f3]
d = {f1:f1,f2:f2,f3:f3}
#調用
l[0]()
d[f2]()

3.可以當作函數的參數和返回值

__author__ = Administrator
def f():
    print("so good")
    return 1+2
l=f#函數名實際上就是普通的變量名
#print(l())

def g(f):#函數名可以做參數
    print(f)#結果是函數名所指向的那塊內存地址
    print("so good g")
    return 2+5
print(g(f))



def l():
    return f#函數名可用作返回值

ll=l()
print(ll())

八.閉包

閉包
1.閉 內部的函數
2.包 包含了對外部函數作用域中變量的引用

閉包的作用:

就是能夠引用外部函數的變量,並且可以保證外部函數的變量控制在一個局部作用域中

#閉包的常用形式
def hei():
    x = 20
    def inner():
        print(x)  #局部的
    return inner

# i = hei()
# i()  #全局
__author__ = Administrator
# from urllib.request import urlopen
# def fun():
#     url="http://www.sina.com.cn/"
#     def op():
#         return urlopen(url).read()
#     return op
# l=fun()
# print(l())
from urllib.request import urlopen
def fun(url):
    def op():
        return urlopen(url).read()
    return op
url="http://www.sina.com.cn/"
l=fun(url)
print(l())

判斷閉包函數的方法__closure__

#輸出的__closure__有cell元素 :是閉包函數
def func():
    name = eva
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#輸出的__closure__為None :不是閉包函數
name = egon
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()
#閉包嵌套
def wrapper():
    money = 1000
    def func():
        name = eva
        def inner():
            print(name,money)
        return inner
    return func
 
f = wrapper()
i = f()
i()

九、裝飾器

裝飾器的本質 :閉包函數
功能:就是在不改變原函數調用方式的情況下,在這個函數前後加上擴展功能

實際上是一種設計模式,開放封閉原則,對擴展是開放的,對修改是封閉的

通用版本
def timmer(func):
    def inner(*args,**kwargs):
        ‘‘‘添加函數調用之前的擴展代碼‘‘‘
        ret = func(*args,**kwargs)
        ‘‘‘添加函數調用之後的擴展代碼‘‘‘
        return ret
    return inner
__author__ = Administrator
def sw(fun):
    def inner(*args,**kwargs):
        ret=fun(*args,**kwargs)
        print(ret)
        return ret
    return inner
@sw#語法糖------>a=sw(a)
def a(m):
    return m
@sw
def b(m,n,**kwargs):
    return m,n,kwargs
a(1)
b(2,3,name="ctz",paw="ahgfggf")

被裝飾函數沒參數

def zsq(fun):
    def inner():
        fun()
    return  inner

def a():
    print("aaaaaa")

a=zsq(a)
a()

被裝飾函數有一個參數

__author__ = Administrator
import  time
def f(fun):
    def inner(x):
        fun(x)
    return  inner

def b(a):
    print(a)

b=f(b)
b(4)

被裝飾參數有兩個參數

__author__ = Administrator
def fun(f):
    def inner(x,y):
        f(x,y)
    return  inner

@fun
def c(a,b):
    print(a,b)
c(5,6)

帶參數的裝飾器(開關)

__author__ = Administrator
F=True
def outer(F):
    def wap(fun):
        def inner(*args,**kwargs):
            if F:
                print("inner   before")
                ret=fun(*args,**kwargs)
                print("inner   after")
            else:
                ret=fun(*args,**kwargs)
            return  ret
        return inner
    return wap

@outer(F)
def gg():
    print("gg............")
gg()

多個裝飾器裝飾一個函數
__author__ = Administrator
def yn(fun):#fun=sc_inner
    def yn_inner(*args,**kwargs):
        print("yun..........before")
        ret=fun(*args,**kwargs)#sc_inner()
        print("yn...........after")
        return ret
    return yn_inner

def sx(fun):#fun=china
    def sx_inner(*args,**kwargs):
        print("sx..........before")
        ret=fun(*args,**kwargs)#china()
        print("sx...........after")
        return ret
    return sx_inner

@yn #china=yn(china)-----china=yn(sx(china))----china=yn(sx_inner)---->china=yn_ineer
@sx  #china=sx(china)----china=
def china():
    print("china is good ")

china()#yn_inner()

 

week3 函數知識整理