一、為什么要使用函數?
1.避免代碼重用
2.提高代碼的可讀性
二、函數的定義與調用
1. def 函數名(參數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.位置和關鍵字傳參混搭 傳遞多個參數,實現比大小的功能
3.默認參數
用法:為什么要用默認參數?將變化比較小的值設置成默認參數(比如一個班的男生多,女生就幾個,就可以設置個默認值參數)
定義:默認參數可以不傳,不傳的時候用的就是默認值,如果傳會覆蓋默認值。
默認的值是在定義函數的時候就已經確定了的

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

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的應用
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) 統計多少個函數被裝飾了
內置函數
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是一個Iterator,Iterator是惰性序列,因此通過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()是將傳人的函數作用在序列的第一個元素得到結果后,把這個結果繼續與下一個元素作用(累積計算),
最終結果是所有的元素相互作用的結果。
練習:
計算:lambda和reduce實現1到100的累加 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()