#什麼是模塊 模塊就是一系列功能的結合體 #模塊的三種來源 1.內置模塊 (python解釋器自帶的) 2.第三方模塊 (別人寫的,requests) 3.自定義模塊 (本身寫的) #模塊的四種表現形式 1.使用python編寫的py文件(一個py文件也能夠成爲一個模塊) 2.已被編譯爲共享庫或DLL的C或C++擴展 3.把一系列模塊組織到一塊兒的文件夾(文件夾下有一個__int__.py文件,該文件夾稱之爲包,包就是一系列py文件的集合體) 4.使用C編寫,並鏈接到python解釋器的內置模塊 #爲何用模塊 1.用別人寫好的模塊(內置的、第三方的),能夠拿來就用,極大地提升開發效率 2.使用本身寫的模塊(自定義的) 當程序比較大的時候,全部項目不可能只在一個py文件中 當多個文件中都須要使用相同的方法的時候,能夠將該公共的方法寫到一個py文件中 其餘的文件以模塊的形式導過去直接調用便可 達到減小代碼冗餘的目的 3.項目結構更加清晰 #怎麼用模塊 注意,必定要區分哪一個是執行文件,哪一個是被執行文件(導入文件) 使用關鍵字import導入模塊 import md,模塊名(文件名)叫md.py,可是導入的時候只須要寫md,不要加.py後綴 屢次導入一個模塊文件,只有第一次有效 #執行文件的流程 鼠標右鍵運行a.py文件 首先會建立一個a.py的名稱空間 若是import導入模塊(md.py): 1.執行模塊文件md.py,運行模塊文件md.py中的代碼 2.將產生的名字與值存放到該模塊文件的名稱空間中 3.在執行文件a.py中,定義一個變量名md,指向md.py的名稱空間 #使用import導入模塊 #0.訪問該模塊名稱空間中的變量名的統一句式爲:模塊名.變量名 import md #1.指名道姓的訪問模塊中的名字,永遠不會與執行文件中的名字衝突 print(md.x) #2.只要能拿到函數名,不管在哪均可以經過函數名加括號來調用這個函數(調用函數,會回到函數定義階段,依次執行代碼) #3.函數在定義階段,名字的查找順序就已經固定死了,不會由於調用位置的改變而改變 print(md.read1) #<function read1 at 0x000001EBC20AFF28> md.change() #可使用import一次導入多個模塊,可是不推薦使用(會致使代碼的結構不清晰) #只有當幾個模塊有相同部分或者屬於一個模塊,能夠一次導入 #當幾個模塊沒有聯繫的狀況下,應該分屢次導入 #一般導入模塊的句式會寫在文件開頭 import md,time,os import md import time import os #當模塊名比較複雜的時候能夠給模塊起別名 import testtttttttttttttttt as test #from ... import ... #屢次導入,只有第一次有效 from md import x from md import x #只會導入該模塊的指定的一個變量名,不會導入別的變量名 #訪問模塊中的名字,不須要加模塊名前綴(當心覆蓋當前名稱空間中的變量名) print(x) #from md import *一次性將md模塊中的變量名所有加載(不推薦使用,佔用內存) #__all__能夠指定當前所在py文件被當作模塊導入的時候,執行文件使用*,能夠拿到的變量名(__all__ = ['x']),默認x爲* from md import * print(x) print(y) #NameError: name 'y' is not defined
#循環導入問題 #若是程序出現循環導入問題,那麼必定是程序設計的不合理 #循環導入問題在程序設計階段就應該避免 m1.py文件 from m2 import y #第一次導入(導入、執行代碼,但不執行函數) print('正在導入m1') x = 1 m2.py文件 from m1 import x #第二次導入,此事x未定義 print('正在導入m2') y = 2 a.py文件 import m1 #ImportError #解決循環導入問題的方式: #1.方式1 將循環導入的句式寫在文件最下方 m1.py文件 print('正在導入m1') x = 1 from m2 import y m2.py文件 print('正在導入m2') y = 2 from m1 import x #2.方式2 在函數內導入模塊 m1.py文件 print('正在導入m1') def f1(): from m2 import y #第一次導入 print('m1,f1>>>y') x = 1 m2.py文件 print('正在導入m2') def f2(): from m1 import x #第二次導入,此時x已經定義 print('m2,f2>>>x') y = 2 import m1 m1.f1() 正在導入m1 正在導入m2 m1,f1>>>y #3.方式3 從新設計項目,拆分循環導入的代碼
#當文件被當作執行文件執行的時候,__name__打印的結果是__main__ #當文件被當作模塊導入的時候,__name__打印的結果是被執行文件名(沒有後綴) def f1(): print('f1') def f2(): print('f2') f1() f2() print(__name__) f1 f2 __main__/m1 #使用__name__,測試自定義模塊功能 def f1(): print('f1') def f2(): print('f2') if __name__ == '__main__': (快捷寫法,main+TAB) f1() f2()
# 模塊的查找順序 1.先從內存中找 2.再從內置模塊中找 3.再從sys.path中找(至關於當前文件的環境變量) #模塊sys #sys.path就是一個大列表,裏面放了一堆文件路徑,第一個路徑永遠是執行文件所在的文件夾 import sys print(sys.path) #['E:\\python_test', 'E:\\python_test', 'C:\\Program Files\\JetBrains\\PyCharm 2020.1.3\\plugins\\python\\helpers\\pycharm_display', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\17575\\AppData\\Roaming\\Python\\Python36\\site-packages', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages', 'C:\\Users\\17575\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages\\pip-20.2.3-py3.6.egg', 'C:\\Program Files\\JetBrains\\PyCharm 2020.1.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend'] #驗證查找順序 -- 先從內存中找 1.鼠標右鍵運行 2.刪除f1() import time import m1 time.sleep(10) m1.f1() #驗證查找順序 -- 從內置模塊中找 1.鼠標右鍵運行 2.能夠看到,導入了內置模塊 import time print(time.time()) #變量名應該避免與模塊名衝突 #驗證查找順序 -- 從sys.path中找(執行文件所在文件夾) 當執行文件所在文件夾下,存在該文件時,直接導入 當執行文件所在文件夾下,不存在該文件時(#不會查找目錄) 可使用from dir import xx,from dir.dir1.dir2 import xx導入指定文件 把被執行文件夾添加到環境變量,再導入(#項目文件夾) import sys sys.path.append(r'E:\python_test\m1.py') import m1 #注意 1.文件名不該該與模塊名(內置、第三方)衝突
#相對導入不能在被執行文件中使用,能夠在被導入文件中使用 (模塊文件) #相對導入不須要考慮絕對路徑,只須要知道與被導入文件的兩個路徑之間的關係便可 #點 . 當前路徑 .. 上一級路徑 ... 上上一級路徑
#絕對路徑不管在執行文件仍是被執行文件中都適用 #絕對導入必須依據執行文件所在的文件夾路徑爲基準 #通常狀況下,一個項目只會有一個執行文件,其餘文件都是模塊,因此相對導入的的應用是很普遍的
#優勢 1.項目結構更加清晰 2.便於管理 3.擴展性高 #start.py(啓動文件,該文件能夠放到項目根目錄下) import os import sys BASE_dir = os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_dir) from core import src if __name__ == '__main__': src.run() #settings.py(配置文件) #把一個目錄放到環境變量裏面,那麼,該目錄下的文件可使用相對路徑導入 #若是項目目錄就是一級目錄(頂級目錄),那麼不須要把該目錄添加到環境變量(pycharm自動添加) #不要使用%s拼接路徑,要使用os模塊,以適用於把不一樣的用戶 #添加環境變量的操做盡可能保留,以適用於不一樣的系統 import os BASE_dir = os.path.dirname(os.path.dirname(__file__)) LOG_path = os.path.join(BASE_dir,'log') #src.py(核心文件) from lib import comman db_username = 'syy' db_password = 123 user_dic = { 'is_login':None } @comman.login_auth def register(): print('reigster') def login(): while True: username = input('請輸入用戶名>>>: ').strip() password = int(input('請輸入用戶密碼>>>: ').strip()) if username == db_username and password == db_password: user_dic['is_login'] = True run() else: print('輸入錯誤,請從新輸入') def shopping(): print('shopping') def transfer(): print('transfer') @comman.login_auth def pay(): print('pay') def withdraw(): print('withdraw') @comman.login_auth def pay_bak(): print('pay_bak') def check_record(): print('check_record') my_dict = { '1':register, '2':login, '3':shopping, '4':transfer, '5':pay, '6':withdraw, '7':pay_bak, '8':check_record } def run(): while True: print(""" 1 register(註冊) 2 login(登陸) 3 shopping(購物) 4 transfer(轉帳) 5 pay(支付) 6 withdraw(提現) 7 pay_bak(還款) 8 check_record(查看流水) """) choice = input('please choice func to operate>>>: ').strip() if choice not in my_dict: print('相關功能還在開發中') my_dict.get(choice)() break #comman.py(公共的功能) from core import src def login_auth(func): def inner(*args,**kwargs): if src.user_dic.get('is_login'): res = func(*args,**kwargs) return res else: print('請先登陸') src.login() return inner #Readme.py 對這款軟件的介紹 本軟件是一個結合了ATM+購物的一個多功能的購物應用程序 用戶能夠經過bin目錄下的啓動程序啓動程序 #db文件夾下面的userinfo.py(數據庫數據) #log文件夾下面的文件(日誌)
正則表達式匹配手機號html
正則表達式匹配身份證號python
#正則 在編寫處理字符串的程序或網頁時,常常有查找符合某些複雜規則的字符串的須要。正則表達式就是用於描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。 正則就是篩選字符串中的特定的內容的規則的代碼 接觸到的,以reg開頭的單詞,一般與正則有關(正則測試:http://tool.chinaz.com/regex) 正則表達式默認都是貪婪匹配,能夠經過在量詞的後面加上一個?,就能夠將貪婪匹配變成非貪婪匹配(惰性匹配) #正則的應用場景(推薦: 《正則指引》) 爬蟲 數據分析 #普通的python腳本 while True: phone_number = input('please input your phone number>>>: ').strip() if len(phone_number) == 11 \ and phone_number.isdigit() \ and (phone_number.startswith('13') \ or phone_number.startswith('14') or phone_number.startswith('15') or phone_number.startswith('16') or phone_number.startswith('17') or phone_number.startswith('18') ): print('手機號合法') else: print('輸入的手機號不合法') #使用re模塊寫的python腳本 import re while True: phone_number = input('please input your phone number>>>: ').strip() if re.match('^(13|14|15|16|17|18)[0-9]{9}$',phone_number): print('手機號合法') else: print('輸入的手機號不合法') import re while True: phone_number = input('please input your phone number>>>: ').strip() if re.match('^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$',phone_number): #?:將貪婪匹配變成非貪婪匹配 print('手機號合法') else: print('輸入的手機號不合法') #身份證號碼 身份證號碼是一個長度爲15或者18個字符的字符串 若是是15位,則所有由數字組成,而且首位不能爲0 若是是18位,則前17位所有都是數字,末位多是數字,也多是X import re while True: phone_number = input('please input your phone number>>>: ').strip() if re.match('\^[1-9]\d{14}(\d{2}[0-9x])?$\',phone_number): print('身份證號碼合法') else: print('身份證號碼不合法') import re while True: phone_number = input('please input your phone number>>>: ').strip() if re.match('^[1-9]\d{16}[0-9x]|^[1-9]\d{14}$',phone_number): print('身份證號碼合法') else: print('身份證號碼不合法')
經常使用元字符git
代碼 | 說明 |
---|---|
. | 匹配除換行符之外的任意一個字符 |
\w | 匹配字母或數字或下劃線、漢字(w是word的縮寫) |
\s | 匹配任意的空白符(space)(空格或TAB鍵,不包括換行符) |
\d | 匹配數字(digit) |
N\b | 匹配單詞的結束 |
^N | 匹配字符串的開始(相似於startswith) |
N$ | 匹配字符串的結束(相似於endswith) |
\n | 匹配一個換行符 |
\t | 匹配一個製表符 |
a|b | 匹配字符a,或者字符b (注意ab|abc匹配abc是ab的做用,abc|ab是abc的做用) |
() | 匹配括號內的表達式,也表示一個組,使用.group()訪問組匹配 |
分組:當多個正則符號須要重複屢次的時候,或者當作一個總體進行其餘操做,那麼就要使用分組,分組使用一對括號() 表示正則表達式
經常使用限定符 (量詞)算法
代碼/語法 | 說明 |
---|---|
* | 當前字符重複零次或更屢次(a*b) |
N+ | 左邊字符重複一次或更屢次(貪婪匹配),N+? (惰性匹配) |
N? | 左邊字符重複零次或一次 |
N{n} | 重複n次 |
N{n,} | 重複n次或更屢次 |
N{n,m} | 重複n到m次(貪婪匹配),N{n,m}? (惰性匹配) |
量詞中的多:貪婪匹配,儘可能匹配知足條件的最多的字符,能夠經過在量詞的後面加上一個?,就能夠將貪婪匹配變成非貪婪匹配(惰性匹配)shell
量詞中的少:量詞只做用於左邊的第一個字符,也就是說只能跟在字符的後面數據庫
經常使用反義詞編程
代碼/語法 | 說明 |
---|---|
\W | 匹配任意不是字母,數字,下劃線,漢字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非數字的字符 |
\B | 匹配不是單詞結束的單詞 |
[^x] | 匹配除了x之外的任意字符 |
[^aeiou] | 匹配除了aeiou這幾個字母之外的任意字符 |
轉義符json
正則 | 待匹配字符 | 解釋 |
---|---|---|
'\n' | 匹配一個換行符 | |
'\\n' | \n | 轉義符轉移後面的\ |
'\\\\n' | \\n | 轉義符轉移後面的\ |
r'\\n' | \n | r,讓整個字符串不轉義 |
非貪婪匹配 (惰性匹配)數組
正則 | 解釋 |
---|---|
*?、.**? | 重複任意次,可是儘量的少重複 |
N+? | 重複一次或更屢次,可是儘量的少重複 |
?? | 重複0次或一次,可是儘量的少重複 |
N{n,m}? | 重複n到m此,可是儘量的少重複 |
N{n,}? | 重複0次以上,可是儘量的少重複 |
#re模塊與正則表達式之間的關係 正則表達式不是python獨有的,他是一門獨立的技術 全部的編程語言均可以使用正則 若是想在python中使用正則,就必須依賴於re模塊,來達到書寫正則表達式目的 #re.findall('正則表達式','字符串') 找到字符串中符合正則表達式的所有內容,返回一個列表,列表中就是正則匹配到的內容 import re res = re.findall('s','syyttsry') print(res) #['s', 's'] import re res = re.findall('k','syyttsry') print(res) #[],找不到的話,返回空列表 import re res = re.findall('[a-z]','syyttsry') print(res) #['s', 'y', 'y', 't', 't', 's', 'r', 'y'] import re res = re.findall('[a-z]+','syyttsry') print(res) #['syyttsry'] import re res = re.findall('[a-z]+','syyttsry yys') print(res) #['syyttsry', 'yys'] #re.search('正則表達式','字符串') search會匹配字符串開頭、中間、結尾的部分,只返回找到的第一個單詞 search不會給你直接返回匹配到的結果,而是給你返回一個對象 使用.group(),才能看到匹配的結果 注意,search只會根據正則查找目標一次,找到即停,若是找不到的話,返回None import re res = re.search('s','syytrihys si op') print(res) #<_sre.SRE_Match object; span=(0, 1), match='s'> print(res.group()) #s import re res = re.search('syyi','syytrihys syyi opa') print(res) #<_sre.SRE_Match object; span=(10, 14), match='syyi'> print(res.group()) #syyi import re res = re.search('k','syytrihys si op') print(res) #None print(res.group()) #AttributeError,不存在的話(None)直接報錯 import re res = re.search('k','syytrihys si op') print(res) if res: print(res.group()) #re.match('正則表達式','字符串') match只會匹配字符串的開頭,只返回一個 match不會給你直接返回匹配到的結果,而是給你返回一個對象 使用.group(),才能看到匹配的結果 注意,match只會根據正則查找目標一次,找到即停,若是找不到的話,返回None import re res = re.match('syy','syytrihys si op') print(res) #<_sre.SRE_Match object; span=(0, 3), match='syy'> print(res.group()) #syy import re res = re.match('k','syytrihys si op') print(res) #None print(res.group()) #AttributeError import re res = re.match('k','syytrihys syyi op') print(res) if res: print(res.group()) #防止報錯 #re.split('正則表達式','字符串') 切割字符串 import re res = re.split('[ab]','1a2bcd') print(res) #['1', '2', 'cd'] import re res = re.split('(\d)','1a2bcd') print(res) #['', '1', 'a', '2', 'bcd'],保留切割的數字 #re.sub('正則表達式','新的內容','字符串',N) 替換字符 import re res = re.sub('\d','H','1a2b3c4d',2) print(res) #HaHb3c4d #re.subn('正則表達式','新的內容','字符串',N) 替換字符 返回的是一個元組,內容是替換後的字符串和替換的個數 import re res = re.subn('\d','H','1a2b3c4d',2) print(res) #('HaHb3c4d', 2) #re.compile('正則表達式') 編譯正則表達式 import re obj = re.compile('\d{3}') #將正則表達式編譯成一個正則表達式對象 res = obj.search('abc123eee111ttt') #正則表達式對象調用search,參數爲待匹配的字符串 print(res.group()) #123 res = obj.findall('abc123eee111ttt') print(res) #['123', '111'] #re.finditer('正則表達式') 與findall相似,不一樣點在於結果是一個迭代器 import re res = re.finditer('\d','1n2j3kL') print(res) #<callable_iterator object at 0x000002CF41AFF898> print(next(res)) #<_sre.SRE_Match object; span=(0, 1), match='1'> print(next(res)) #<_sre.SRE_Match object; span=(2, 3), match='2'> print(next(res)) #<_sre.SRE_Match object; span=(4, 5), match='3'> print(next(res)) #StopIteration #re模塊中的分組 findall會優先把匹配結果組裏面的結果返回,若是想要匹配結果,使用?:取消權限便可 import re res = re.findall('^[1-9]\d{14}(\d{2}[0-9x])?$','94596847739994375x') print(res) res = re.findall('^[1-9]\d{14}(?:\d{2}[0-9x])?$','94596847739994375x') print(res) res = re.search('^[1-9]\d{14}(\d{2}[0-9x])?$','94596847739994375x') print(res) print(res.group()) print(res.group(1)) res = re.match('^[1-9]\d{14}(\d{2}[0-9x])?$','94596847739994375x') print(res) print(res.group()) print(res.group(1)) ['75x'] ['94596847739994375x'] <_sre.SRE_Match object; span=(0, 18), match='94596847739994375x'> 94596847739994375x 75x <_sre.SRE_Match object; span=(0, 18), match='94596847739994375x'> 94596847739994375x 75x #re模塊中的分組與別名(?P<別名>) import re res = re.findall('^[1-9]\d{14}(\d{2}[0-9x])?$','94596847739994375x') print(res) res = re.search('^[1-9]\d{14}(?P<password>\d{2}[0-9x])?$','94596847739994375x') print(res) print(res.group()) print(res.group(1)) print(res.group('password')) res = re.match('^[1-9]\d{14}(?P<password>\d{2}[0-9x])?$','94596847739994375x') print(res) print(res.group()) print(res.group(1)) print(res.group('password')) ['75x'] <_sre.SRE_Match object; span=(0, 18), match='94596847739994375x'> 94596847739994375x 75x 75x <_sre.SRE_Match object; span=(0, 18), match='94596847739994375x'> 94596847739994375x 75x 75x
#爬蟲就是爬取網頁的html代碼(就是一堆字符串) 1.研究網站是否有反爬措施 2.研究該網站頁面URL的規律 3.想要什麼內容,寫出對應的正則表達式,爬取代碼 4.從這一堆字符串中篩選出你想要的的內容
#typing模塊 輸入提示,只會提示 from typing import List ,Tuple def test1( name: str, age :int, balance :float, user_info :List pawass: tuple ) -> Tuple[int,float,str,list,dict,tuple]: return (name ,age ,balance ,user_info) res = test1('111' ,'2' ,3.3 ,[4,4,4]) print(res)
#python的基本數據類型有整形、浮點型、字符串、列表、元組、字典、布爾值、集合 #collection模塊提供別的數據類型 namedtuple :具名元組,生成使用名字來訪問元素內容的tuple deque :雙端隊列,能夠快速的從另一側追加和推出對象 counter :計數器,主要用來計數 ordereddict :有序字典 defaultdict :帶有默認值的字典 #具名元組,namedtuple('註釋','['']') from collections import namedtuple point = namedtuple('座標',['x','y']) #使用列表(可迭代對象)表示座標 p = point(1,2) #注意元素數量要保持一致 print(p) #座標(x=1, y=2) print(p.x) #1 print(p.y) #2 from collections import namedtuple point = namedtuple('座標','x,y') #使用字符串表示座標(以空格或逗號分隔) p = point(1,2) print(p) print(p.x) print(p.y) #打印撲克 from collections import namedtuple card = namedtuple('撲克牌','color number') A = card('♠','A') print(A) print(A.color) print(A.number) 撲克牌(color='♠', number='A') ♠ A #表示圓 from collections import namedtuple card = namedtuple('圓','x y r') #雙端隊列,deque() 隊列,先進先出(FIFO) 堆棧,先進後出 import queue q = queue.Queue() q.put('first') #先進 q.put('second') q.put('third') print(q) #<queue.Queue object at 0x0000020F9FAFA908> print(q.get()) #first print(q.get()) #second print(q.get()) #third print(q.get()) #若是隊列中的值取完了,程序會在原地等待,知道從隊列中拿到值才中止 雙端隊列 from collections import deque q = deque(['a','b',1,2]) q.append(3) q.appendleft('A') print(q.pop()) #3 print(q.popleft()) #A #雙端隊列,能夠根據索引,在任意位置插入值,而隊列不支持在任意位置插值,只能在首尾插值(不能插隊) from collections import deque q = deque(['a','b',1,2]) q.insert(3,'哈哈哈') print(q.pop()) #2 print(q.pop()) #哈哈哈 print(q.pop()) #1 print(q.pop()) #b print(q.pop()) #a #有序字典,ordereddict() normal_d = dict([('a',1),('b',2),('c',3)]) print(normal_d) from collections import OrderedDict order_d = OrderedDict([('a',1),('b',2),('c',3)]) print(order_d) order_d = OrderedDict([]) order_d['x'] = 1 order_d['y'] = 2 order_d['z'] = 3 print(order_d) {'a': 1, 'b': 2, 'c': 3} #無順序 OrderedDict([('a', 1), ('b', 2), ('c', 3)]) #有順序 OrderedDict([('x', 1), ('y', 2), ('z', 3)]) #有順序 #默認值字典,defaultdict() 普通字典 values = [11,22,33,44,55,66,77,88,99] my_dict = {} for value in values: if value > 66: if 'k1' in my_dict.keys(): my_dict['k1'].append(value) else: my_dict['k1'] = [value] else: if 'k2' in my_dict.keys(): my_dict['k2'].append(value) else: my_dict['k2'] = [value] print(my_dict) #{'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]} 默認值字典 from collections import defaultdict values = [11,22,33,44,55,66,77,88,99] my_dict = defaultdict(list) #在該字典中新建key,對應的value默認值就是列表 # print(my_dict) #defaultdict(<class 'list'>, {}) for value in values: if value > 66: my_dict['k1'].append(value) else: my_dict['k2'].append(value) print(my_dict) #{'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]} 普通字典 s = 'sfregersggggggrvsdesdfrrrrrr' d = {} for i in s: if i in d.keys(): d[i]+= 1 else: d[i] = 1 print(d) from collections import Counter s = 'sfregersggggggrvsdesdfrrrrrr' res = Counter(s) print(res) #Counter({'r': 9, 'g': 7, 's': 4, 'e': 3, 'f': 2, 'd': 2, 'v': 1})
#py文件名應該避免跟已有的模塊名相同,防止導入衝突 #OS模塊是跟操做系統打交道的模塊,使用該模塊可使APP跨平臺使用 #目錄列表 import os print(os.listdir(r'E:\python_test\ATM')) #['bin', 'conf', 'core', 'db', 'lib', 'log', 'Readme'] import os #當前文件所在當前目錄 BASE_DIR = os.path.dirname(__file__) #根據獲取的當前目錄,拼接處指定目錄 MOVE_DIR = os.path.join(BASE_DIR,'老師們的做品') #獲取指定目錄下的文件名,結果是列表 movie_list = os.listdir(MOVE_DIR) #計算列表內的元素的個數,也就是指定目錄下的文件數 file_num = len(movie_list) while True: #打印開頭用戶能夠參考的信息 for i,j in enumerate(movie_list,1): print(i,j) choise = input('請輸入想看的資源序號>>>: ').strip() #判斷用戶輸入是否爲純數字 if choise.isdigit(): choise = int(choise) #判斷用戶輸入數字是否有意義 if choise in range(1,file_num+1): #列表索引取值,獲得文件名 target_file = movie_list[choise-1] target_path = os.path.join(MOVE_DIR,target_file) print(target_path) with open(target_path,mode='r',encoding='utf-8') as f: #不能使用r'' print(f.read()) break else: print('輸入數字無效,請從新輸入,數字範圍爲>>>: 1-%s'%file_num) else: print('輸入無效,請輸入指定的數字序號') #mkdir(),建立單級目錄 import os os.mkdir('test目錄') #與當前的python文件同級 #makedirs(),建立多級目錄 import os os.makedirs('T1/T2') #與當前的python文件同級 #rmdir(),removedirs(),刪除單級空目錄 import os os.rmdir(r'E:\python_test\test') os.removedirs(r'E:\python_test\test目錄\testdir') #刪除多級目錄,要刪除的目錄下不能有文件(目錄不爲空就報錯) import os os.removedirs(r'E:\python_test\T1\T2') #exists(),判斷文件或目錄是否存在 import os print(os.path.exists(r'E:\python_test\test目錄')) #True print(os.path.exists(r'E:\python_test\a.py')) #True #isfile(),判斷文件是否存在 import os print(os.path.isfile(r'E:\python_test\老師們的做品')) #False,目錄只返回True print(os.path.isfile(r'E:\python_test\a.py')) #True #remove(),刪除一個文件 import os os.remove(r'E:\python_test\m2.py') #重命名目錄/文件 import os os.rename(r'E:\python_test\a.py',r'E:\python_test\aaa.py') #重命名文件 os.rename(r'E:\python_test\老師們的做品',r'E:\python_test\老師們的做品哈') #重命名目錄 #stat(),獲取文件/目錄的信息 import os res = os.stat((r'E:\python_test\aaa.py')) #獲取文件的信息 print(res) #os.stat_result(st_mode=33206, st_ino=19140298416324717, st_dev=2122398715, st_nlink=1, st_uid=0, st_gid=0, st_size=1406, st_atime=1605492292, st_mtime=1605492292, st_ctime=1604305169) res = os.stat((r'E:\python_test\老師們的做品哈')) #獲取目錄的信息 print(res) #os.stat_result(st_mode=16895, st_ino=119345390125318349, st_dev=2122398715, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1605492215, st_mtime=1605433594, st_ctime=1605255301) #getcwd(),查看當前文件的工做目錄 import os print(os.getcwd()) #E:\python_test #chdir(),改變當前文件的工做目錄,至關於shell下的cd import os print(os.getcwd()) #E:\python_test os.chdir(r'E:\python_test\老師們的做品哈') print(os.getcwd()) #E:\python_test\老師們的做品哈 #system(),運行shell命令 import os os.system('mkdir TT') #popen(),運行shell命令,獲取執行結果 import os os.popen('mkdir T').read() #getsize(),獲取文件大小 import os res = os.path.getsize(r'E:\python_test\老師們的做品哈\小澤老師') print(res) #7,字節 with open(r'E:\python_test\老師們的做品哈\小澤老師',mode='r',encoding='utf-8') as f: print(len(f.read())) #5,字符
#sys模塊,是跟python解釋器打交道的模塊 #append(),將某個目錄添加到系統的環境變量中 import sys sys.path.append(r'E:\python_test\老師們的做品哈') #platform,查看當前的操做系統 import sys print(sys.platform) #win32 #version,查看python解釋器的版本 import sys print(sys.version) #argv[n],獲取終端的命令行的參數 import sys username = sys.argv[1] password = sys.argv[2] if username == 'syy' and password == '123': print('當前代碼') else: print('用戶名或密碼錯誤') E:\python_test>python E:\python_test\aaa.py syy 123 #實例 import sys if len(sys.argv) != 3: print('請輸入用戶名和密碼') else: username = sys.argv[1] password = sys.argv[2] if username == 'syy' and password == '123': print('當前代碼') else: print('用戶名或密碼錯誤')
#time的三種表現形式 1.時間戳 2.格式化時間(給人看的) 3.結構化時間 #時間戳 import time print(time.time()) #1605249911.3957567 #格式化時間 print(time.strftime('%Y-%m-%d')) #2020-11-13 print(time.strftime('%Y-%m-%d %H:%M:%S')) #2020-11-13 14:47:11 print(time.strftime('%Y-%m-%d %X')) #等價,2020-11-13 14:48:58 print(time.strftime('%m/%d %H:%M:%S')) #拼接,11/13 14:48:05 #結構化時間 print(time.localtime()) #time.struct_time(tm_year=2020, tm_mon=11, tm_mday=13, tm_hour=14, tm_min=50, tm_sec=50, tm_wday=4, tm_yday=318, tm_isdst=0) #三種時間的轉化 #時間戳轉結構化時間 import time print(time.localtime(1605249911.3957567)) #time.struct_time(tm_year=2020, tm_mon=11, tm_mday=13, tm_hour=6, tm_min=45, tm_sec=11, tm_wday=4, tm_yday=318, tm_isdst=0) import time print(time.gmtime(1605249911.3957567)) #結構化時間轉時間戳 import time res = time.localtime(time.time()) print(time.mktime(res)) #1605250876.0 print(time.time()) #1605250876.6250167 #格式化時間轉結構化時間 import time res = time.strftime('%Y-%m-%d %H:%M:%S') print(time.strptime(res,'%Y-%m-%d %H:%M:%S')) #結構化時間轉格式化時間 import time print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) #2020-11-13 15:10:12 #time.sleep() import time print('倒計時: 3...') print(time.sleep(1)) print('倒計時: 2..') print(time.sleep(1)) print('倒計時: 1.') print(time.sleep(1)) print('倒計時: 0') 倒計時: 3... None 倒計時: 2.. None 倒計時: 1. None 倒計時: 0
#datatime模塊 import datetime print(datetime.date.today()) #2020-11-13(年月日) print(datetime.datetime.today()) #2020-11-13 15:18:02.062366(年月日時分秒) print(res1.year) #2020 print(res1.month) #11 print(res1.day) #13 print(res1.weekday()) #4(用0-6表示) print(res1.isocalendar()) #(2020, 46, 5)(星期用1-7表示,7表示週日) #時間能夠相加減 #日期對象 = 日期對象 +/- timedelta對象 import datetime corrent_time = datetime.date.today() timetel_t = datetime.timedelta(days=3) print(corrent_time+timetel_t) #2020-11-16 #timedelta對象 = 日期對象 +/- 日期對象 #UTC時間 import datetime dt_today = datetime.datetime.today() dt_now = datetime.datetime.now() dt_utcnow = datetime.datetime.utcnow() print(dt_today,dt_now,dt_utcnow) 2020-11-13 15:34:25.711797 2020-11-13 15:34:25.711797 2020-11-13 07:34:25.711797
#序列化 序列: 字符串 序列化: 其餘數據類型轉換成字符串的過程 反序列化: 字符串轉換成其餘數據類型 #爲何要使用序列化 數據有指定的數據類型,轉換成字符串(序列化),才能str.encoding轉化爲二進制數據(基於網絡傳輸的數據必須是二進制數據),進而寫入文件 #json模塊的優勢 全部編程語言均可以使用json格式,也就是說,json代碼能夠跨語言、跨平臺使用 #json模塊的缺點: 支持的數據類型少(json只能夠轉字符串、列表、字典,不能轉對象、索引、函數等) #json可以支持的python的數據類型,python中其餘的數據類型json都不支持 import json json.JSONEncoder +-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object |對象(字符串) +-------------------+---------------+ | list, tuple | array |數組(字符串) +-------------------+---------------+ | str | string |字符串 +-------------------+---------------+ | int, float | number |數值 +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+ #dumps()序列化,將其餘的數據類型轉換成json格式的字符串 #loads()反序列化,將json格式的字符串轉換成其餘的數據類型 import json d = {"name":"syy"} print(d) #{'name': 'syy'},只有json格式的數據打印出來是雙引號 res = json.dumps(d) print(res) #{"name": "syy"},等效於'{"name": "syy"}' print(type(res)) #<class 'str'> res = json.loads(res) print(res) #{'name': 'syy'} print(type(res)) #<class 'dict'> #dump(),load() import json d = {"name":"syy"} with open(r'userinfo','w',encoding='utf-8') as f: json.dump(d,f) #轉換成字符串,而且自動寫入 with open(r'userinfo','r',encoding='utf-8') as f: res = json.load(f) print(res,type(res)) #{'name': 'syy'} <class 'dict'> #反序列化中的問題,以及解決方法 import json d = {"name":"syy"} with open(r'userinfo','w',encoding='utf-8') as f: json.dump(d,f) json.dump(d,f) with open(r'userinfo','r',encoding='utf-8') as f: res = json.load(f) #不能屢次反序列化 print(res,type(res)) #json.decoder.JSONDecodeError: #解決方法 import json d = {"name":"syy"} with open(r'userinfo','w',encoding='utf-8') as f: json_str = json.dumps(d) json_str2 = json.dumps(d) f.write('%s\n'%json_str) f.write('%s\n'%json_str2) with open(r'userinfo','r',encoding='utf-8') as f: for line in f: res = json.loads(line) print(res,type(res)) #將元組轉換成數組 import json t = (1,2,3) res = json.dumps(t) print(res,type(res)) #[1, 2, 3] <class 'str'> #中文轉json的時候的轉碼問題 import json d = {'name':'豬堅強'} print(json.dumps((d))) #{"name": "\u732a\u575a\u5f3a"} print(json.dumps(d,ensure_ascii=False)) #{"name": "豬堅強"}
#pickle模塊 python全部的數據類型都支持pickle模塊(包括對象、索引、函數) #pickle模塊 只能本身跟本身玩,不支持跨語言傳輸 只有python才能使用pickle模塊 #dumps(),loads() import pickle d = {'name':'syy'} res = pickle.dumps(d) print(res) #b'\x80\x03}q\x00X\x04\x00\x00‘,將對象直接轉換成二進制 res = pickle.loads(res) print(res,type(res)) #{'name': 'syy'} <class 'dict'> #dump(),load() #使用pickle操做文件的時候,文件的打開模式必須是b模式 import pickle d = {'name':'syy'} with open(r'userinfo','wb') as f: pickle.dump(d,f) with open(r'userinfo','rb') as f: res = pickle.load(f) print(res,type(res)) #{'name': 'syy'} <class 'dict'>
#隨機數 import random print(random.randint(1,6)) #1,包括首尾 import random print(random.random()) #0.5979006446755478,取0-1之間的小數 import random print(random.choice([1,2,3,4,5,6])) #2,從列表中隨機取值 import random res = [1,2,3,4,5,6] random.shuffle(res) print(res) #[2, 1, 3, 6, 5, 4],打亂順序 #生成隨機驗證碼 驗證碼由大寫字母、小寫字母、數字組成 import random def get_code(n): code = '' for i in range(n): upper_str = chr(random.randint(65,90)) lower_str = chr(random.randint(97,122)) random_int = str(random.randint(0,9)) code +=random.choice([upper_str,lower_str,random_int]) return code res = get_code(5) print(res) #驗證碼忽略大小寫 使用upper()、lower()統一轉換成大寫或者小寫 s = 'rigllllllllllllf' res = s.upper() print(res) res = s.lower() print(res)
#日誌 日誌本質上是就是一個文本文件,咱們能夠直接寫入,可是太麻煩,因此使用logging模塊封裝了日誌的編輯 #logging模塊也叫日誌模塊 記錄程序的輸入與輸出 #日誌分爲5個等級 import logging file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',) logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[file_handler,], level=logging.ERROR ) logging.error('你好') logging.debug('debug日誌') #10 logging.info('info日誌') #20 logging.warning('warning日誌') #30 logging.error('error日誌') #40 logging.critical('critical日誌') #50 2020-11-17 15:37:47 PM - root - ERROR -aaa: 你好 2020-11-17 15:37:47 PM - root - DEBUG -aaa: debug日誌 2020-11-17 15:37:47 PM - root - INFO -aaa: info日誌 2020-11-17 15:37:47 PM - root - WARNING -aaa: warning日誌 2020-11-17 15:37:47 PM - root - ERROR -aaa: error日誌 2020-11-17 15:37:47 PM - root - CRITICAL -aaa: critical日誌 #問題 1.亂碼 2.日誌格式 3.如何既打印到終端,又寫入到文件 #學習logging模塊須要瞭解的幾個核心的對象(角色) 1.logger對象:負責產生日誌 2.filter對象:過濾日誌 3.handler對象:控制日誌輸出的位置(文件/終端) 4.formmater對象:規定日誌內容的格式 #參數 logging.basicConfig()函數中可經過具體參數來更改logging模塊默認行爲,可用參數有: filename:用指定的文件名建立FiledHandler,這樣日誌會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。 format:指定handler使用的日誌顯示格式。 datefmt:指定日期時間格式。 level:設置rootlogger(後邊會講解具體概念)的日誌級別 stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。 format參數中可能用到的格式化串: %(name)s Logger的名字 %(levelno)s 數字形式的日誌級別 %(levelname)s 文本形式的日誌級別 %(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有 %(filename)s 調用日誌輸出函數的模塊的文件名 %(module)s 調用日誌輸出函數的模塊名 %(funcName)s 調用日誌輸出函數的函數名 %(lineno)d 調用日誌輸出函數的語句所在的代碼行 %(created)f 當前時間,用UNIX標準的表示時間的浮 點數表示 %(relativeCreated)d 輸出日誌信息時的,自Logger建立以 來的毫秒數 %(asctime)s 字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進程ID。可能沒有 %(message)s用戶輸出的消息 #logger對象配置 import logging logger = logging.getLogger() # 建立一個handler,用於寫入日誌文件 fh = logging.FileHandler('test.log',encoding='utf-8') # 再建立一個handler,用於輸出到控制檯 ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setLevel(logging.DEBUG)fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) #logger對象能夠添加多個fh和ch對象 logger.addHandler(ch) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message') #日誌切割 import time import logging from logging import handlers sh = logging.StreamHandler() rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5) fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8') logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', handlers=[fh,sh,rh], level=logging.ERROR ) for i in range(1,100000): time.sleep(1) logging.error('KeyboardInterrupt error %s'%str(i))
#sub 子 #process 進程 # import subprocess while True: cmd = input('please input your command>>>: ').strip() obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) print('stdout',obj.stdout.read().decode('gbk')) #正確命令的返回結果 print('stderr',obj.stderr.read().decode('gbk')) #錯誤命令返回的提示信息 #過程分析 1.用戶經過網絡,鏈接電腦 2.用戶輸入相應的命令,基於網絡發送給這臺電腦上的某個程序 3.獲取用戶輸入的命令,python解釋器經過subprocess模塊執行用戶的命令 4.將執行結果再基於網絡發送給用戶,這樣就實現了用戶的遠程操做
#模塊的三種來源 1.內置的 2.第三方的 3.自定義的 #模塊的四種表現形式 1.py文件 2.共享庫 3.文件夾/包(一系列模塊的結合體) 4.C++編譯鏈接到python內置的 #使用import導入模塊 1.產生一個執行文件的名稱空間 2.建立模塊文件的名稱空間 3.執行模塊文件中的代碼,將產生的名字放入模塊文件的名稱空間中 4.在執行文件的名稱空間中,建立一個指向模塊文件名稱空間的名字 #模塊與包 #能夠站在兩個角度來分析不一樣的問題 1.模塊的開發者 2.模塊的使用者 #包 包是一系列模塊文件的結合體,他的表現形式就是一個文件夾 該文件夾內部一般會有一個__init__.py文件 包的本質仍是一個模塊 #導入包 1.產生一個執行文件的名稱空間 2.建立包下面的__init__.py文件的名稱空間 3.執行包下面的__init__.py文件中的代碼,將產生的名字放入包下面的__init__.py文件的名稱空間中 4.在執行文件中,建立一個指向包下面的__init__.py文件的名稱空間的名字 #導入包的時候,.號的左邊永遠是包(文件夾) #看成爲包的設計者來講 1.當模塊的功能特別多的狀況下,應該分文件管理,也就是作成包 2.每一個模塊之間爲了不後期模塊更名的問題,可使用相對導入,由於包裏面的文件都應該是被導入的模塊 # import m1 # import m2 # import m3 # import m1.f1 #不支持,import只能導入模塊 # import bao.m1 # import bao.m2 # import bao.m3 # import bao.bao2.m4 #支持 # from bao import m1 # from bao import m2 # from bao import m3 # from bao.bao2 import m4 #支持 # from bao.m1 import f1 #支持 # import m4 #不報錯 import bao2.m4 #報錯 # from bao.bao2 import m4 #不報錯 # import .m4 #報錯 # from .m4 import m4 #報錯 #站在包的開發者來講,若是使用絕對路徑來管理本身的模塊,那麼他只須要以包爲基準,依次導入模塊 #站在包的使用者來講,必須將包所在的那個文件夾路徑添加到system.path中 #python2中,若是要導入包,包下面必需要有__init__.py文件 #python3中,若是要導入包,包下面沒有__init__.py文件也不會報錯 #當刪除代碼中沒必要要的文件的時候,千萬不要隨意刪除__init__.py文件
#算法模塊、加密模塊 該模塊只能加密,不能解密 相同的加密數據,獲得的密文必定相同,密文相同,加密數據必定相同 不一樣的加密方法,加密過程相同 密文的長度越長,對應的算法越複雜,可是時間消耗越長,佔用空間越大,一般使用md5加密算法(32位) 要加密的數據能夠分屢次傳入 #md5() import hashlib md = hashlib.md5() #生成一個造密文的對象 md.update('hello'.encode('utf-8')) #向對象中傳明文數據 # md.update(b'hello') #等效 print(md.hexdigest()) #5d41402abc4b2a76b9719d911017c592 #sha3_256() import hashlib md = hashlib.sha3_256() md.update('hello'.encode('utf-8')) # md.update(b'hello') print(md.hexdigest()) #3338be694f50c5f338814986cdf0686453a888b84f424d792a #加密對象的屢次傳入 import hashlib md = hashlib.md5() md.update('he'.encode('utf-8')) md.update('ll'.encode('utf-8')) md.update('o'.encode('utf-8')) print(md.hexdigest()) #5d41402abc4b2a76b9719d911017c592 #hashlib模塊的應用場景 1.密碼的密文傳輸 2.校驗文件的內容是否一致 #加鹽處理、動態加鹽 import hashlib md = hashlib.md5() md.update('加鹽'.encode('utf-8')) md.update('hello'.encode('utf-8')) print(md.hexdigest()) #7e17f9d744b7f40b93c22fa9da785d40 import hashlib md = hashlib.md5() md.update('加鹽hello'.encode('utf-8')) print(md.hexdigest()) #7e17f9d744b7f40b93c22fa9da785d40 #實例 import hashlib def get_md5(data): md = hashlib.md5() md.update('加鹽'.encode('utf-8')) md.update(data.encode('utf-8')) return md.hexdigest() password = input('請輸入你的密碼>>>: ').strip() res = get_md5(password) print('密碼密文爲:加鹽%s',%res)
#操做Excel表格的模塊 Excel文件在03版本以前,後綴名叫xls Excel文件在03版本以後,後綴名叫xlsx #xlwd模塊 寫Excel #xlrt模塊 讀Excel #xlwd模塊、xlrt模塊,既支持03版本以前的Excel文件,也支持03版本以後的文件 #openyxl模塊,只支持03版本以後的文件 #openpyxl模塊 from openpyxl import Workbook wb = Workbook() #先生成一個工做蒲 wb1 = wb.create_sheet('index0',0) #指定sheet名,初始化sheet位置 wb2 = wb.create_sheet('index1',1) wb3 = wb.create_sheet('index2',2) wb1.append(['username','age','hobby']) #添加表頭 wb1.append(['syy',18,'study']) #添加數據 wb1['A3'] = 666 #在指定的sheet中寫入內容 wb1['A4'] = 777 wb2['G6'] = 888 wb3.cell(row=6,column=3,value=999) wb1['A5'] = '=sum(A3:A4)' #求和 wb1.title = 'login' #修改sheet名 wb.save('test.xlsx') #指定文件名
#淺拷貝 #淺拷貝中不可變數據類型指向的是同一個 #淺拷貝中可變數據類型拷貝指向的仍是原來的拷貝對象,而深拷貝指向的是新的 #深拷貝 #深拷貝中,全部的id指向的都是對應的同一個值 #深淺拷貝的本質在於新的變量名指向的值,的指向是原來的內存地址仍是原來的值 #鏈式變量 l = [1,2,[1,2]] l1 = l print(id(l),id(l1)) #2422474796744 2422474796744 l[0] = 222 print(l,l1) #[222, 2, [1, 2]] [222, 2, [1, 2]] #copy模塊 import copy l = [1,2,[1,2]] l1 = copy.copy(l) print(id(l),id(l1)) #1742143678728 1742143677768 l[0] = 222 #這部分是深拷貝 print(l,l1) #[222, 2, [1, 2]] [1, 2, [1, 2]] l[2].append(666) #這部分是淺拷貝 print(l,l1) #[1, 2, [1, 2, 666]] [1, 2, [1, 2, 666]] #深拷貝 import copy l = [1,2,[1,2]] l1 = copy.deepcopy(l) print(id(l),id(l1)) l[2].append(666) print(l,l1) 2493117098248 2493117097288 [1, 2, [1, 2, 666]] [1, 2, [1, 2]]