Python學習【第5篇】:Python之函數(自定義函數,內置函數,裝飾器,迭代器,生成器、模塊)


一、為什么要使用函數?

   1.避免代碼重用

   2.提高代碼的可讀性

二、函數的定義與調用

1def  函數名(參數1,參數2):

    ''' 函數注釋'''

    print('函數體')

    return 返回值

  定義:def關鍵字開頭,空格之后接函數名和圓括號,最后還要加一個冒號。

        def是固定的,不能變。

  函數名:函數名是包含字母,數字,下划線的任意組合,但是不能以數字開頭。雖然函數名可以隨便取名,但是一般盡量定義成可以表示函數功能的。

2.函數的調用

     返回值=函數名(參數1,參數2)#記得函數名后面加括號

 函數和方法的區別

1、函數要手動傳self,方法不用傳

2、如果是一個函數,用類名去調用,如果是一個額方法,用對象去調用 

舉例說明:

復制代碼
class Foo(object):
    def __init__(self):
        self.name="haiyan"
    def func(self):
        print(self.name)

obj = Foo()
obj.func()
Foo.func(obj)
復制代碼

判斷函數和方法的方式

復制代碼
from types import FunctionType,MethodType
obj = Foo()
print(isinstance(obj.func,FunctionType))  #False
print(isinstance(obj.func,MethodType))   #True   #說明這是一個方法

print(isinstance(Foo.func,FunctionType))  #True   #說明這是一個函數。
print(isinstance(Foo.func,MethodType))  #False
復制代碼

三、函數的返回值

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

2.首先返回值可以是任意的數據類型。

3.函數可以有返回值:如果有返回值,必須要用變量接收才有效果

   也可以沒有返回值:

  沒有返回值的時候分三種情況:

    1.當不寫return的時候,函數的返回值為None

    2.當只寫一個return的時候,函數的返回值為None

    3.return None的時候,函數的返回值為None(幾乎不用)

4.return返回一個值(一個變量)

5.return返回多個值(多個變量):多個值之間用逗號隔開,以元組的形式返回。

                接收:可以用一個變量接收,也可以用多個變量接收,返回幾個就用幾個變量去接收

def firstvalue(a,b):

    c = a + b

    return c


def secondvalue(a,b):

    c = a + b

    return a,b,c

 

四、函數的參數

1.實參和形參
形參:是函數定義時候定義的參數
實參:函數調用的時候傳進來的參數
2.傳遞多個參數
可以傳遞多個參數,多個參數之間用逗號隔開。
站在傳參的角度上,調用函數時傳參數有兩種方式:
  1.按照位置傳參數
  2.按照關鍵字傳參數
用法:1.位置參數必須在關鍵字參數的前面
   2.對於一個參數只能賦值一次
def my_max(a,b):#位置參數:按順序定義參數
    if a>b:
        return a
    else:
        return b
# 站在傳參的角度上
print(my_max(20,30))
print(my_max(10,20))# 1.按照位置傳參
print(my_max(b=50,a=30))# 2.按照關鍵字傳參
print(my_max(10,b=30))#3.位置和關鍵字傳參混搭

傳遞多個參數,實現比大小的功能
View Code

3.默認參數

用法:為什么要用默認參數?將變化比較小的值設置成默認參數(比如一個班的男生多,女生就幾個,就可以設置個默認值參數)

定義:默認參數可以不傳,不傳的時候用的就是默認值,如果傳會覆蓋默認值。

   默認的值是在定義函數的時候就已經確定了的

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

默認參數
View Code

4.動態參數

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

按關鍵字傳值接受多個關鍵字參數,由kwargs接收,保存成一個典的形式

def fun(a,b,*args):
     sum=a+b
     for i in args:
            sum+=i
     return sum
 print(fun(1,5,6,4))#輸出1+5+6+4的和
*args應用
def fun(a,b,**kwargs):
    print(a,b,kwargs)

# 按照關鍵字傳參數
fun(a = 10,b = 20,cccc= 30,dddd = 50)#輸出10 20 {'cccc': 30, 'dddd': 50}





def f(a,b,*args,defult=6,**kwargs):
    #位置參數,*args, 默認參數,**kwargs
    # print(a,b,args,defult,kwargs)
    return a,b,args,defult,kwargs

#傳參數的時候:必須先按照位置傳參數,再按照關鍵字傳參數
print(f(1,2,7,8,ccc=10,der=5))

*kwargs的應用
**kwargs應用

 

1.為什么要使用裝飾器呢?

  裝飾器的功能:在不修改原函數及其調用方式的情況下對原函數功能進行擴展

  裝飾器的本質:就是一個閉包函數

import time
def wrapper(func):
        def inner():
               start=time.time()
               func()
               end=time.time()
               print(end-start)
        return inner
@wrapper
def  kkk():#相當於kkk=wrapper(kkk)
    print('aaaaa')
kkk()             
import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        end=time.time()
        print(end- start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def func1(a,b):
    print('in func1')
    print(a,b)

@timer   #==> func1 = timer(func1)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'

func1(1,2)
print(func2('aaaaaa'))

原函數帶多個參數的裝飾器
帶多個參數的裝飾器
import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        end=time.time()
        print(end - start)
        return re
    return inner

@timer   #==> func1 = timer(func1)
def jjj(a):
    print('in jjj and get a:%s'%(a))
    return 'fun2 over'

jjj('aaaaaa')
print(jjj('aaaaaa'))

帶返回值的裝飾器
帶返回值的裝飾器

二、開放封閉原則

1.對擴展是開放的

2.對修改是封閉的

 三、裝飾器的固定結構

import time
def wrapper(func):  # 裝飾器
    def inner(*args, **kwargs):
        '''函數執行之前的內容擴展'''
        ret = func(*args, **kwargs)
         '''函數執行之前的內容擴展'''
        return ret
    return inner

@wrapper  # =====>aaa=timmer(aaa)
def aaa():
    time.sleep(1)
    print('fdfgdg')
aaa()

四、帶參數的裝飾器

帶參數的裝飾器:就是給裝飾器傳參

        用處:就是當加了很多裝飾器的時候,現在忽然又不想加裝飾器了,想把裝飾器給去掉了,但是那么多的代碼,一個一個的去閑的麻煩,那么,我們可以利用帶參數的裝飾器去裝飾它,這就他就像一個開關一樣,要的時候就調用了,不用的時候就去掉了。給裝飾器里面傳個參數,那么那個語法糖也要帶個括號。在語法糖的括號內傳參。在這里,我們可以用三層嵌套,弄一個標識為去標識。如下面的代碼示例

# 帶參數的裝飾器:(相當於開關)為了給裝飾器傳參
# F=True#為True時就把裝飾器給加上了
F=False#為False時就把裝飾器給去掉了
def outer(flag):
    def wrapper(func):
        def inner(*args,**kwargs):
            if flag:
                print('before')
                ret=func(*args,**kwargs)
                print('after')
            else:
                ret = func(*args, **kwargs)
            return ret
        return inner
    return wrapper

@outer(F)#@wrapper
def hahaha():
    print('hahaha')

@outer(F)
def shuangwaiwai():
    print('shuangwaiwai')

hahaha()
shuangwaiwai()

給裝飾器加參數
裝飾器開關

五、多個裝飾器裝飾一個函數

def qqqxing(fun):
    def inner(*args,**kwargs):
        print('in qqxing: before')
        ret = fun(*args,**kwargs)
        print('in qqxing: after')
        return ret
    return inner

def pipixia(fun):
    def inner(*args,**kwargs):
        print('in qqxing: before')
        ret = fun(*args,**kwargs)
        print('in qqxing: after')
        return ret
    return inner
@qqqxing
@pipixia
def dapangxie():
    print('餓了嗎')
dapangxie()

'''
@qqqxing和@pipixia的執行順序:先執行qqqxing里面的 print('in qqxing: before'),然后跳到了pipixia里面的
        print('in qqxing: before')
        ret = fun(*args,**kwargs)
        print('in qqxing: after'),完了又回到了qqqxing里面的 print('in qqxing: after')。所以就如下面的運行結果截圖一樣
'''

多個裝飾器裝飾一個函數

六、統計多少個函數被裝飾了的小應用

統計多少個函數被我裝飾了
l=[]
def wrapper(fun):
    l.append(fun)#統計當前程序中有多少個函數被裝飾了
    def inner(*args,**kwargs):
        # l.append(fun)#統計本次程序執行有多少個帶裝飾器的函數被調用了
        ret = fun(*args,**kwargs)
        return ret
    return inner

@wrapper
def f1():
    print('in f1')

@wrapper
def f2():
    print('in f2')

@wrapper
def f3():
    print('in f3')
print(l)

統計多少個函數被裝飾了
View Code

 

內置函數
1.eval,exec,和compile

eval("print(456)")#吧字符串轉換成python代碼去執行(有返回值)
exec("print(7889)")#吧字符串轉換成python代碼去執行(無返回值)
2.compile#做編譯
com=compile('1+2+3','',mode = 'eval')#節省時間
print(eval(com))
print(eval('1+2+3'))#這句效果和上面的compile()效果一樣

 3.type()

 

4.round精確度
print(round(3.1415926,2))#保留兩位
5.和數據結構相關的
1.reversed()順序的反轉
l=[1,2,3,4]
print(list(reversed(l)))#是生成了一個新的列表,沒有改變原來的列表(以后能不用reversed就不用reversed,用reverse)

#l.reverse()#在現在的列表的基礎上修改了,修改的是原來的列表
5.slice切片
6.format()#除了格式化以外的作業


6.set和frozenset(不可變的集合)就像list和tuple


7.zip()
l=[1,2,3]
l2=[4,5,6,7,8]
print(zip(l,l2))
print(list(zip(l,l2)))
l3={'k':'v'}
print(list(zip(l,l3)))

8.sort和sorted
l=[1,3,5,-2,-6]
l.sort()
print(l)
l2=[1,3,5,-2,-6]
print(sorted(l2))
print(sorted(l2,key=abs))
print(sorted(l2,key=abs,reverse=True))#默認從小到大排序,修改為True,則從大到小排序

9.map():我要對我的列表當中的每一個值去做函數里面的操作
l=[1,2,3,4,5]
def pow2(x):
    return x*x
print(list(map(pow2,l)))

10.filter():從一個列表當中找到所有符合篩選條件的,在組成一個新列表
def aaa(x):
     return x%2==1
ret=list(filter(aaa,[1,2,54,3,6,8,17,9]))
print(ret)
遞歸函數

 

1.什么是遞歸:在一個函數里在調用這個函數本身

一個數,除2直到不能整除2
def  cal(num):
        if  num%2==0:#先判斷能不能整除
            num=num//2
            return cal(num)
        else:
            return num
print(cal(8))

 

匿名函數:也叫lambda表達式

1.匿名函數的核心:一些簡單的需要用函數去解決的問題,匿名函數的函數體只有一行

2.參數可以有多個,用逗號隔開

3.返回值和正常的函數一樣可以是任意的數據類型

 

請把下面的函數轉換成匿名函數
def  add(x,y)
        return x+y
add()

結果:
sum1=lambda x,y:x+y
print(sum1(5,8))
復制代碼

三、列表推導式

30以內所有被3整除的數
print(list([i for i in range(30) if i%3==0]))


將一個字典的key和value對調
mcase = {'a': 10, 'b': 34}
res1 = {i:mcase[i] for i in mcase}
res={mcase[i]:i for i in mcase }
print(res1)
print(res)

例二:合並大小寫對應的value值,將k統一成小寫

mcase = {'a':10,'b':34,'A':7}
res = {i.lower():mcase.get(i.lower(),0)+mcase.get(i.upper(),0) for i in mcase}
print(res)

四、集合推倒式

例:計算列表中每個值的平方,自帶去重功能

l=[5,-5,1,2,5]
print({i**2 for i in l})

 

高階函數

map()傳入的第一個參數是f,即函數對象本身。由於結果r是一個IteratorIterator是惰性序列,因此通過list()函數讓它把整個序列都計算出來並返回一個list

a='123'

def f(x):

return x

r=map(f,a)

print list(r)

reduce的用法。reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)


filter()把傳入的函數依次作用於每個元素,然后根據返回值是True還是False決定保留還是丟棄該元素。

defis_odd(n): returnn % 2== 1list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))


排序也是在程序中經常用到的算法。無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小。如果是數字,我們可以直接比較,但如果是字符串或者兩個dict呢?直接比較數學上的大小是沒有意義的,因此,比較的過程必須通過函數抽象出來

Python內置的sorted()函數就可以對list進行排序:

sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

從參數方面來講:

map()函數:

  map()包含兩個參數,第一個是參數是一個函數,第二個是序列(列表或元組)。其中,函數(即map的第一個參數位置的函數)可以接收一個或多個參數。

reduce()函數:

reduce() 第一個參數是函數,第二個是 序列(列表或元組)。但是,其函數必須接收兩個參數。

從對傳進去的數值作用來講:

map()是將傳入的函數依次作用到序列的每個元素,每個元素都是獨自被函數“作用”一次;

reduce()是將傳人的函數作用在序列的第一個元素得到結果后,把這個結果繼續與下一個元素作用(累積計算),

最終結果是所有的元素相互作用的結果。

練習:

計算:lambdareduce實現1100的累加 fromfunctools importreduce print(reduce(lambdax,y:sum([x,y]),range(1,101))) #第一個參數是一個函數,第二個參數是一個序列print(map(lambdax,y:sum([x,y]),range(1,101))) #第一個參數是一個函數,第二個參數是一個序列print(list(map(lambdax,y:sum([x,y]),range(1,101),range(1,101)))) #第一個參數是一個函數,第二個參數是一個序列

 

模塊

同一個目錄 引入模塊

import

from..import

這兩種都會把函數執行一遍

import Firstmoudle

Firstmoudle.func(1,2)

# from Firstmoudle import func(全部*

from Firstmoudle import s 分成2行寫

模塊內容執行1次 只是把變量或者函數拿出來

# func(1,2)

reload(Firstmoudle)

Firstmoudle.func()

import sys

print sys.getdefaultencoding()

reload(sys)

sys.setdefaultencoding('utf_8')

print sys.getdefaultencoding()

不同文件夾下引用需要添加絕對路徑或者相對路徑

import sys

sys.path.append('C:\\Users\\thinkpad\\PycharmProjects\\untitled\\test\\test2')

import Firstmoudle

Firstmoudle.func()

 

 

 
         
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM