閱讀目錄 一、模塊和包 模塊(module)的概念: 在電腦程式的開發過程中,隨著程式代碼越寫越多,在一個文件里代碼會越來越長,越來越不容易維護。 為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都採用這種組織代碼的方式。在Pytho ...
閱讀目錄
一、模塊和包
模塊(module)的概念:
在電腦程式的開發過程中,隨著程式代碼越寫越多,在一個文件里代碼會越來越長,越來越不容易維護。
為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都採用這種組織代碼的方式。在Python中,一個.py文件就稱之為一個模塊(module)。
使用模塊有哪些好處?
1、最大的好處就是大大提高了代碼的可維護性。
2、編寫代碼不必從零開始。當一個模塊編寫完成,就可以被其他地方調用。我們在編寫程式的時候,也經常飲用其他模塊,包括Python內置的模塊和來自第三方的模塊。
模塊一共分為三種:
1、python標準庫
2、第三方模塊
3、應用程式自定義模塊
註意:
使用模塊還可以避免函數名跟變數名衝突。相同名字的函數和變數完全可以分別存在不同的模塊中,因此,我們在自己編寫模塊時,不必考慮名字會與其他模塊衝突。但是也要註意,儘量不要與內置函數名字衝突。
二、模塊的導入方法
1、import語句
import module1,[module2[,...moduleN]]
當我們使用import語句的時候,Python解釋器是怎樣找到對應的文件?答案就是解釋器有自己的搜索路徑,存在sys.path里。
import sys
print(sys.path)
運行結果如下:
['G:\\python_s3\\day21', 'G:\\python_s3', 'C:\\Python35\\python35.zip', 'C:\\Python35\\DLLs', 'C:\\Python35\\lib', 'C:\\Python35', 'C:\\Python35\\lib\\site-packages', 'D:\\Program Files (x64)\\pycharm軟體安裝\\config\\PyCharm 2018.3\\helpers\\pycharm_matplotlib_backend']
因此若像我一樣在當前目錄下存在與要引入模塊同名的文件,就會把要引入的模塊沒屏蔽掉。
2、from...import ...語句
from modname import name1[,name2[, ... nameN]]
這個聲明不會把整個modulename模塊導入到當前的命名空間中,只會講它裡面的name1或name2單個引入到執行這個聲明的模塊的全局符號表。
3、from...import*語句
from modname import *
4、運行本質
1、import test
2、from test import add
無論1還是2,首先通過sys.path找到test.py,然後執行test腳本,區別是1會將test這個變數名載入到名字空間,而2只會將add這個變數名載入進來。
5、包(package)
1、如果不同的人編寫的模塊名相同怎麼辦?為了避免模塊名衝突,Python又引入了按目錄來組織模塊的方法,成為包(Package)。
舉個例子:一個abc.py的文件就是一個名字叫abc的模塊,一個simon.py的文件就是一個叫simon的模塊。
現在,假設我們的abc和simon這兩個模塊名字和其他模塊起衝突了,於是我們可以通過包來組織模塊,從而避免衝突。方法就是選擇一個頂層包名:
2、引入了包以後,只要頂層的包名不與別人衝突,那所有模塊都不會與別人衝突。現在,view.py模塊的名字就變成了hello_django.app01.views,類似的,manage.py的模塊名則是hello_django.manage。
請註意,每一個包目錄下麵都會有一個__init__.py的文件,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄(文件夾),而不是一個包。__init__.py可以是空文件,也可以有Python代碼,因為__init__.py本身就是一個模塊,而它的模塊名就是對應包的名字。
註意點(important)
調用包就是執行包下的__init__.py文件
#1--------------------------------
在node1中import hello是找不到的,有人說可以找到呀,那是因為你的pycharm為你把myapp這一層路徑加入到了sys.path裡面,所以可以找到,然而程式一旦在命令行運行,則報錯。有同學問那怎麼辦?簡單啊,自己把這個路徑加進去不就OK啦:
import sys,os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR) #臨時修改
import hello
hello.hello1()
#2、--------------
if __name__=='__main__':
print('ok')
“Make a .py both importable and executable”
如果我們是直接執行某個.py文件的時候,該文件中那麼"__name__ == '__main__' "是True,但是我們如果從另外一個.py文件通過import導入該文件的時候,這時__name__的值就是我們這個py文件的名字而不是__main__.
這個功能還有一個用處:調試代碼的時候,在"if __name__ == '__main__' "中加入一些我們的調試代碼,我們可以讓外部模塊調用的時候不執行我們的調試代碼,但是如果我們想排查問題的時候,直接執行該模塊文件,調試代碼能夠正常運行!
##-------------cal.py
def add(x,y):
return x+y
##-------------main.py
import cal #from module import cal
def main():
cal.add(1,2)
##--------------bin.py
from module import main
main.main()
註意:
# from module import cal 改成 from . import cal同樣可以,這是因為bin.py是我們的執行腳本, # sys.path里有bin.py的當前環境。即/Users/simon/Desktop/whaterver/project/web這層路徑, # 無論import what , 解釋器都會按這個路徑找。所以當執行到main.py時,import cal會找不到,因為 # sys.path里沒有/Users/simon/Desktop/whaterver/project/web/module這個路徑,而 # from module/. import cal 時,解釋器就可以找到了。
三、time模塊(* * * *)
三種時間表示
在Python中,通常有這幾種方式來表達時間:
1、時間戳(timestamp):通常來說,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。我們運行“type(time.time())”,返回的是float類型。
2、格式化的時間字元串
3、元祖(struct_time):struct_time元祖共有9個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)
import time
#1、time(): 返回當前時間的時間戳
print(time.time())
運行結果如下:
C:\Python35\python3.exe G:/python_s3/day21/example.py
1555996405.5020845
#2、localtime(secs): 將一個時間戳轉換為當前時區的struct_time。secs參數未提供,則以當前時間為準。
print(time.localtime())
運行結果如下:
C:\Python35\python3.exe G:/python_s3/day21/example.py
time.struct_time(tm_year=2019, tm_mon=4, tm_mday=23, tm_hour=13, tm_min=18, tm_sec=9, tm_wday=1, tm_yday=113, tm_isdst=0)
#3、gmtime([secs])和localtime()方法類似,gmtime()方法是將一個時間戳轉換為UTC時區(0時區)的struct_time。
print(time.gmtime())
運行結果如下:
C:\Python35\python3.exe G:/python_s3/day21/example.py
time.struct_time(tm_year=2019, tm_mon=4, tm_mday=23, tm_hour=5, tm_min=21, tm_sec=25, tm_wday=1, tm_yday=113, tm_isdst=0)
#4、mktime(t): 將一個struct_time轉化為時間戳
print(time.mktime(time.localtime())) #
運行結果如下:
C:\Python35\python3.exe G:/python_s3/day21/example.py
1555998160.0
#5、asctime([t]): 把一個表示時間的元祖或者struct_time表示為這種形式:'Tue Apr 23 13:45:49 2019'
#如果沒有參數,將會將time.localtime()作為參數傳入。
print(time.asctime())
運行結果如下:
C:\Python35\python3.exe G:/python_s3/day21/example.py
Tue Apr 23 13:45:49 2019
#6、ctime([secs]): 把一個時間戳(按秒計算的浮點數)轉化為time.asctime()的形式。如果參數未給或者為None的時候,將會預設time.time()為參數。它的作用相當於time.asctime(time.localtime(secs))。
print(time.ctime()) #Tue Apr 23 14:02:45 2019
print(time.ctime(time.time())) #Tue Apr 23 14:03:50 2019
#7、strftime(format[,t]) #把一個代表時間的元祖或者struct_time(如由time.localtime()和time.gmtime()返回) 轉化為格式化的時間字元串。如果t未指定,將傳入time.localtime()。如果元組中任何一個元素過界,ValueError的錯誤將會被拋出。
print(time.strftime("%Y-%m-%d %X",time.localtime())) #2019-04-23 14:11:12
#8、time.strptime(string[, format]) #把一個格式化時間字元串轉化為struct_time。實際上它和strftime()是逆操作。
print(time.strptime('2019-04-23 14:15:07', '%Y-%m-%d %X'))
輸出結果為:
time.struct_time(tm_year=2019, tm_mon=4, tm_mday=23, tm_hour=14, tm_min=15, tm_sec=7, tm_wday=1, tm_yday=113, tm_isdst=-1)
#在這個函數中,format預設為:"%a %b %d %H:%M:%S %Y"。
#9、sleep(sesc)
print(time.sleep(3)) #線程推遲指定的時間運行,單位為秒。
#10、clock
# 這個需要註意,在不同的系統上含義不同。在UNIX系統上,它返回的是"進程時間",它是用秒錶示的浮點數(時間戳)。而在windows中,第一次調用,返回的是進程運行的實際時間。而第二次之後的調用是自第一次調用以後到現在的運行時間,即兩次時間差。
關係圖:
四、random模塊(* *)
import random
ret=random.random()
# ret=random.randint(1,3) #[1,3]
# ret=random.randrange(1,3) #[1,3]
# ret=random.choice([11,22,33,44,55])
# ret=random.sample([11,22,33,44,55],2)
# ret=random.uniform(1,4)
# print(ret)
# ret=[1,2,3,4,5]
# random.shuffle(ret)
# print(ret)
item=[1,3,5,7,9]
random.shuffle(item)
print(item)
#隨機生成驗證碼
import random
def v_code():
ret=""
for i in range(5):
num=random.randint(0,9)
alf=chr(random.randint(65,122))
s=str(random.choice([num,alf]))
ret+=s
return ret
print(v_code())
五、os模塊(* * * *)
os模塊是與操作系統交互的介面
os.getcwd() #獲取當前工作目錄,即當前python腳本的目錄路徑
os.chdir("dirname") #改變當前腳本工作目錄,相當於shell下cd
os.cudir #返回當前目錄:(' . ')
os.pardir #獲取當前目錄的父目錄字元串名:(' . . ')
os.makedirs('dirname1/dirname2') #可生成多層遞歸目錄
os.removedirs('dirname1') #若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname') #生成單級目錄,相當於linux中mkdir dirname
os.rmdir('dirname') #刪除單級空目錄,若目錄不為空則無法刪除,報錯,相當於shell中rmdir dirname
os.listdir('dirname') #列出指定目錄下的所有文件和子目錄,包含隱藏文件,並以列表的方式列印
os.remove() #刪除一個文件
os.rename("oldname","newname") #重命名文件/目錄
os.stat('path/filename') #獲取文件/目錄信息
例:
print(os.stat("sss.py"))
C:\Python35\python3.exe G:/python_s3/day22/os_test.py
os.stat_result(st_mode=33206, st_ino=11821949021847676, st_dev=2159804260, st_nlink=1, st_uid=0, st_gid=0, st_size=10, st_atime=1556025329, st_mtime=1556025329, st_ctime=1556025302)
os.sep #輸出操作系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep #輸出當前平臺使用的行終止符,win下為"\r\n",Linux下為"\n"
os.pathsep #輸出用於分隔文件路徑的字元 win下為; ,Linux下為:
os.name #輸出字元串指示當前使用平臺。win-->'nt'; Linux-->'posix'
os.system("bash command") #運行shell命令,直接顯示
os.environ #獲取系統環境變數
例:
print(os.environ)
environ({'FP_NO_HOST_CHECK': 'NO', 'PUBLIC': 'C:\\Users\\Public', 'PYCHARM': 'D:\\Program Files (x64)\\pycharm軟體安裝\\config\\PyCharm 2018.3\\bin;', 'COMPUTERNAME': 'DELL-PC', 'PYTHONPATH': 'G:\\python_s3;D:\\Program Files (x64)\\pycharm軟體安裝\\config\\PyCharm 2018.3\\helpers\\pycharm_matplotlib_backend', 'PYCHARM_HOSTED': '1', 'PYCHARM_MATPLOTLIB_PORT'
os.path.abspath(path) #返回path規範化的絕對路徑
os.path.split(path) #將path分割成目錄和文件名二元組返回
例:
print(os.path.split(r"G:\python_s3\day22\sss.py"))
輸出結果:
('G:\\python_s3\\day22', 'sss.py')
os.path.dirname(path) #返回path的目錄。其實就是os.path.split(path)的第一個元素
例:
print(os.path.dirname(r"G:\python_s3\day22\sss.py"))
輸出結果:
G:\python_s3\day22
os.path.basename(path) #返回path最後的文件名,如果path以/ 或 \結尾,那麼就會返回空值。即os.path.split(path) 的第二個元素
例:
print(os.path.basename(r"G:\python_s3\day22\sss.py"))
輸出結果:
sss.py
os.path.exists(path) #如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) #如果path是絕對路徑,返回True
os.path.isfile(path) #如果path是一個存在的文件,返回True,否則返回False
os.path.isdir(path) #如果path是一個存在的目錄,則返回True,否則返回False
os.path.join(path1,paht2[, ...]) #將多個路徑組合後返回,第一個絕對路徑之前的參數將被忽略
例:
a="G:\python_s3\day22"
b="sss.py"
print(os.path.join(a,b))
輸出結果:
G:\python_s3\day22\sss.py
os.path.getatime(paht) #返回path所指向的文件或者目錄的最後存取時間
os.path.getmtime(path) #返回path所指向的文件或者目錄的最後修改時間
三、實現裝飾器知識儲備
裝飾器=高階函數+函數嵌套+閉包
四、高階函數
高階函數的定義: 1、函數接收的參數是一個函數名 2、函數的返回值是一個函數名 3、滿足上述條件任意一個,都可稱之為高階函數
五、函數嵌套
def father(name): print('from father %s' %name) def son(): print('from the son') def grandson(): print('from the grandson') grandson() son() father('朱銳')
六、閉包
1、閉包
def father(name): print('from father %s' %name) def son(): print('from the son') def grandson(): print('from the grandson') grandson() son() father('朱銳') ''' 閉包 ''' def father(name): def son(): # name='simon1' print('我的爸爸是%s' %name) def grandson(): print('我的爺爺是%s' %name) grandson() son() father('simon')
2、函數閉包裝飾器基本實現
import time def timmer(func): def wrapper(): # print(func) start_time=time.time() func() #就是在運行test() stop_time=time.time() print('運行時間是%s' %(stop_time-start_time)) return wrapper @timmer #語法糖,這個是重點 def test(): time.sleep(3) print('test函數運行完畢') # res=timmer(test) #返回的是wrapper的地址 # res() #執行的是wrapper() # test=timmer(test) #返回的是wrapper的地址 # test() #執行的是wrapper() test() ''' 語法糖 ''' # @timmer #就相當於 test=timmer(test)
3、函數閉包加上返回值
#未加返回值 import time def timmer(func): def wrapper(): # print(func) start_time=time.time() func() #就是在運行test() stop_time=time.time() print('運行時間是%s' %(stop_time-start_time)) return 123 return wrapper @timmer #語法糖 def test(): time.sleep(3) print('test函數運行完畢') return '這是test的返回值' res=test() #就是在運行wrapper print(res) 運行結果如下: C:\Python35\python3.exe G:/python_s3/day20/加上返回值.py test函數運行完畢 運行時間是3.000171661376953 123
#加上返回值 import time def timmer(func): def wrapper(): # print(func) start_time=time.time() res=func() #就是在運行test() ##主要修改這裡1 stop_time=time.time() print('運行時間是%s' %(stop_time-start_time)) return res ##修改這裡2 return wrapper @timmer #語法糖 def test(): time.sleep(3) print('test函數運行完畢') return '這是test的返回值' res=test() #就是在運行wrapper print(res) 運行結果如下: C:\Python35\python3.exe G:/python_s3/day20/加上返回值.py test函數運行完畢 運行時間是3.000171661376953 這是test的返回值
4、函數閉包加上參數
import time def timmer(func): def wrapper(name,age): #加入參數,name,age # print(func) start_time=time.time() res=func(name,age) ##加入參數,name,age stop_time=time.time() print('運行時間是%s' %(stop_time-start_time)) return res return wrapper @timmer #語法糖 def test(name,age): #加入參數,name,age time.sleep(3) print('test函數運行完畢,名字是【%s】,年齡是【%s】' % (name,age)) return '這是test的返回值' res=test('simon',18) #就是在運行wrapper print(res)
使用可變長參數代碼如下:達到的效果是傳參靈活
import time def timmer(func): def wrapper(*args,**kwargs): #test('simon',18) args=('simon') kwargs={'age':18} # print(func) start_time=time.time() res=func(*args,**kwargs) #就是在運行test() func(*('simon'),**{'age':18}) stop_time=time.time() print('運行時間是%s' %(stop_time-start_time)) return res return wrapper @timmer #語法糖 def test(name,age): time.sleep(3) print('test函數運行完畢,名字是【%s】,年齡是【%s】' % (name,age)) return '這是test的返回值' def test1(name,age,gender): time.sleep(1) print('test函數運行完畢,名字是【%s】,年齡是【%s】,性別是【%s】' % (name,age,gender)) res=test('simon',18) #就是在運行wrapper print(res) test1('simon',18,'male')
5、裝飾器的使用
#無參裝飾器 import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print('from foo') foo()
#有參裝飾器 def auth(driver='file'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == 'file': if name == 'simon' and pwd == '123': print('login successful') res=func(*args,**kwargs) return res elif driver == 'ldap': print('ldap') return wrapper return auth2 @auth(driver='file') def foo(name): print(name) foo('simon')
#驗證功能裝飾器
#驗證功能裝飾器 user_list=[ {'name':'simon','passwd':'123'}, {'name':'zhurui','passwd':'123'}, {'name':'william','passwd':'123'}, {'name':'zhurui1','passwd':'123'}, ] current_dic={'username':None,'login':False} def auth_func(func): def wrapper(*args,**kwargs): if current_dic['username'] and current_dic['login']: res=func(*args,**kwargs) return res username=input('用戶名:').strip() passwd=input('密碼:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username current_dic['login']=True res=func(*args,**kwargs) return res else: print('用戶名或者密碼錯誤') # if username == 'simon' and passwd == '123': # user_dic['username']=username # user_dic['login']=True # res=func(*args,**kwargs) # return res # else: # print('用戶名或密碼錯誤') return wrapper @auth_func def index(): print('歡迎來到某寶首頁') @auth_func def home(name): print('歡迎回家%s' %name) @auth_func def shopping_car(name): print('%s購物車裡有[%s,%s,%s]' %(name,'餐具','沙發','電動車')) print('before----->',current_dic) index() print('after---->',current_dic) home('simon') # shopping_car('simon')
#帶參數驗證功能裝飾器
#帶參數驗證功能裝飾器 user_list=[ {'name':'simon','passwd':'123'}, {'name':'zhurui','passwd':'123'}, {'name':'william','passwd':'123'}, {'name':'zhurui1','passwd':'123'}, ] current_dic={'username':None,'login':False} def auth(auth_type='filedb'): def auth_func(func): def wrapper(*args,**kwargs): print('認證類型是',auth_type) if auth_type == 'filedb': if current_dic['username'] and current_dic['login']: res = func(*args, **kwargs) return res username=input('用戶名:').strip() passwd=input('密碼:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username current_dic['login']=True res = func(*args, **kwargs) return res else: print('用戶名或者密碼錯誤') elif auth_type == 'ldap': print('這玩意沒搞過,不知道怎麼玩') res = func(*args, **kwargs) return res else: print('鬼才知道你用的什麼認證方式') res = func(*args, **kwargs) return res return wrapper return auth_func @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一個auth_type --->index=auth_func(index) def index(): print('歡迎來到某寶主頁') @auth(auth_type='ldap') def home(name): print('歡迎回家%s' %name) # @auth(auth_type='sssssss') def shopping_car(name): print('%s的購物車裡有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) # print('before-->',current_dic) # index() # print('after--->',current_dic) # home('simon') shopping_car('simon')