Python 子產品(Module),是一個 Python 檔案,以 .py 結尾,包含了 Python 對象定義和Python語句。
子產品讓你能夠有邏輯地組織你的 Python 代碼段。
把相關的代碼配置設定到一個子產品裡能讓你的代碼更好用,更易懂。
子產品能定義函數,類和變量,子產品裡也能包含可執行的代碼。
通俗的講:
子產品,用一堆代碼實作了某個功能的代碼集合。
類似于函數式程式設計和面向過程程式設計,函數式程式設計則完成一個功能,其他代碼用來調用即可,提供了代碼的重用性和代碼間的耦合。而對于一個複雜的功能來,可能需要多個函數才能完成(函數又可以在不同的.py檔案中),n個 .py 檔案組成的代碼集合就稱為子產品。
如:os 是系統相關的子產品;file是檔案操作相關的子產品
子產品分為三種:
- 自定義子產品
- 内置子產品
- 開源子產品
自定義子產品
1、定義子產品
情景一:
情景二:
情景三:
2、導入子產品
Python之是以應用越來越廣泛,在一定程度上也依賴于其為程式員提供了大量的子產品以供使用,如果想要使用子產品,則需要導入。導入子產品有一下幾種方法:
import module
from module.xx.xx import xx
from module.xx.xx import xx as rename
from module.xx.xx import *
導入子產品其實就是告訴Python解釋器去解釋那個py檔案
- 導入一個py檔案,解釋器解釋該py檔案
- 導入一個包,解釋器解釋該包下的 __init__.py 檔案
那麼問題來了,導入子產品時是根據那個路徑作為基準來進行的呢?即:sys.path
import sys
print(sys.path)
['C:\Users\Administrator\PycharmProjects\suanfa', 'C:\Users\Administrator\PycharmProjects\suanfa', 'E:\python\python3\python35.zip', 'E:\python\python3\DLLs', 'E:\python\python3\lib', 'E:\python\python3', 'C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages', 'E:\python\python3\lib\site-packages', 'E:\python\python3\lib\site-packages\win32', 'E:\python\python3\lib\site-packages\win32\lib', 'E:\python\python3\lib\site-packages\Pythonwin']
如果sys.path路徑清單沒有你想要的路徑,可以通過 sys.path.append('路徑') 添加。
通過os子產品可以擷取各種目錄,例如:
import sys
import os
pre_path = os.path.abspath('../')
sys.path.append(pre_path)
View Code
開源子產品
一、下載下傳安裝
下載下傳安裝有兩種方式:
1.
yum
pip
apt-get
2.
下載下傳源碼
解壓源碼
進入目錄
編譯源碼 python setup.py build
安裝源碼 python setup.py install
在使用源碼安裝時,需要使用到gcc編譯和python開發環境,是以,需要先執行:
yum install gcc
yum install python-devel
或
apt-get python-dev
安裝成功後,子產品會自動安裝到 sys.path 中的某個目錄中,如:
/usr/lib/python2.7/site-packages/
二、導入子產品
同自定義子產品中導入的方式
三、子產品 paramiko
paramiko是一個用于做遠端控制的子產品,使用該子產品可以對遠端伺服器進行指令或檔案操作,值得一說的是,fabric和ansible内部的遠端管理就是使用的paramiko來現實。
1、下載下傳安裝
pip3 install paramiko
或
# pycrypto,由于 paramiko 子產品内部依賴pycrypto,是以先下載下傳安裝pycrypto
# 下載下傳安裝 pycrypto
wget http://files.cnblogs.com/files/wupeiqi/pycrypto-2.6.1.tar.gz
tar -xvf pycrypto-2.6.1.tar.gz
cd pycrypto-2.6.1
python setup.py build
python setup.py install
# 進入python環境,導入Crypto檢查是否安裝成功
# 下載下傳安裝 paramiko
wget http://files.cnblogs.com/files/wupeiqi/paramiko-1.10.1.tar.gz
tar -xvf paramiko-1.10.1.tar.gz
cd paramiko-1.10.1
python setup.py build
python setup.py install
# 進入python環境,導入paramiko檢查是否安裝成功
View Code
2、使用子產品
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.14.50', 22, 'liu', '123')
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
ssh.close();
執行指令 - 通過使用者名和密碼連接配接伺服器
import paramiko
private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('主機名 ', 端口, '使用者名', key)
stdin, stdout, stderr = ssh.exec_command('ls')
print stdout.read()
ssh.close()
執行指令 - 過密鑰連結伺服器
import os,sys
import paramiko
t = paramiko.Transport(('192.168.14.50',22))
t.connect(username='liu',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test.py','/tmp/test.py')
t.close()
import os,sys
import paramiko
t = paramiko.Transport(('192.168.14.50',22))
t.connect(username='liu',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test.py','/tmp/test2.py')
t.close()
上傳或者下載下傳檔案 - 通過使用者名和密碼
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.14.51',22))
t.connect(username='liu',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test3.py','/tmp/test3.py')
t.close()
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.14.51',22))
t.connect(username='liu',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test3.py','/tmp/test4.py')
t.close()
上傳或下載下傳檔案 - 通過密鑰
内置子產品
一、os
用于提供系統級别的操作
os.getcwd() 擷取目前工作目錄,即目前python腳本工作的目錄路徑
os.chdir("dirname") 改變目前腳本工作目錄;相當于shell下cd
os.curdir 傳回目前目錄: ('.')
os.pardir 擷取目前目錄的父目錄字元串名:('..')
os.makedirs('dirname1/dirname2') 可生成多層遞歸目錄
os.removedirs('dirname1') 若目錄為空,則删除,并遞歸到上一級目錄,如若也為空,則删除,依此類推
os.mkdir('dirname') 生成單級目錄;相當于shell中mkdir dirname
os.rmdir('dirname') 删除單級空目錄,若目錄不為空則無法删除,報錯;相當于shell中rmdir dirname
os.listdir('dirname') 列出指定目錄下的所有檔案和子目錄,包括隐藏檔案,并以清單方式列印
os.remove() 删除一個檔案
os.rename("oldname","newname") 重命名檔案/目錄
os.stat('path/filename') 擷取檔案/目錄資訊
os.sep 輸出作業系統特定的路徑分隔符,win下為"\",Linux下為"/"
os.linesep 輸出目前平台使用的行終止符,win下為"
",Linux下為"
"
os.pathsep 輸出用于分割檔案路徑的字元串
os.name 輸出字元串訓示目前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 運作shell指令,直接顯示
os.environ 擷取系統環境變量
os.path.abspath(path) 傳回path規範化的絕對路徑
os.path.split(path) 将path分割成目錄和檔案名二進制組傳回
os.path.dirname(path) 傳回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path) 傳回path最後的檔案名。如何path以/或結尾,那麼就會傳回空值。即os.path.split(path)的第二個元素
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[, path2[, ...]]) 将多個路徑組合後傳回,第一個絕對路徑之前的參數将被忽略
os.path.getatime(path) 傳回path所指向的檔案或者目錄的最後存取時間
os.path.getmtime(path) 傳回path所指向的檔案或者目錄的最後修改時間
View Code
二、sys
用于提供對解釋器相關的操作
sys.argv 指令行參數List,第一個元素是程式本身路徑
sys.exit(n) 退出程式,正常退出時exit(0)
sys.version 擷取Python解釋程式的版本資訊
sys.maxint 最大的Int值
sys.path 傳回子產品的搜尋路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform 傳回作業系統平台名稱
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
View Code
三、hashlib
用于加密相關的操作,代替了md5子產品和sha子產品,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
廢棄的md5
import md5
hash = md5.new()
hash.update('admin')
print hash.hexdigest()
廢棄的sha
import sha
hash = sha.new()
hash.update('admin')
print hash.hexdigest()
新寫法
import hashlib
# ######## md5 ########
hash = hashlib.md5()
hash.update('admin')
print hash.hexdigest()
# ######## sha1 ########
hash = hashlib.sha1()
hash.update('admin')
print hash.hexdigest()
# ######## sha256 ########
hash = hashlib.sha256()
hash.update('admin')
print hash.hexdigest()
# ######## sha384 ########
hash = hashlib.sha384()
hash.update('admin')
print hash.hexdigest()
# ######## sha512 ########
hash = hashlib.sha512()
hash.update('admin')
print hash.hexdigest()
View Code
以上加密算法雖然依然非常厲害,但時候存在缺陷,即:通過撞庫可以反解。是以,有必要對加密算法中添加自定義key再來做加密。
import hashlib
# ######## md5 ########
hash = hashlib.md5('898oaFs09f')
hash.update('admin')
print hash.hexdigest()
python 還有一個 hmac 子產品,它内部對我們建立 key 和 内容 再進行處理然後再加密
import hmac
h = hmac.new('wueiqi')
h.update('hellowo')
print h.hexdigest()
View Code
四、json 和 pickle
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基于ECMAScript的一個子集。 JSON采用完全獨立于語言的文本格式,但是也使用了類似于C語言家族的習慣(包括C、C++、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的資料交換語言。易于人閱讀和編寫,同時也易于機器解析和生成(一般用于提升網絡傳輸速率)。
JSON在python中分别由list和dict組成。
pickle子產品實作了python的所有資料序列和反序列化。基本上功能使用和JSON子產品沒有太大差別,方法也同樣是dumps/dump和loads/load。
與JSON不同的是pickle不是用于多種語言間的資料傳輸,它僅作為python對象的持久化或者python程式間進行互相傳輸對象的方法,是以它支援了python所有的資料類型。
pickle反序列化後的對象與原對象是等值的副本對象,類似與deepcopy。
簡易來講就是這兩個子產品是用于序列化的
- json,用于字元串 和 python資料類型間進行轉換
- pickle,用于python特有的類型 和 python的資料類型間進行轉換
Json子產品提供了四個功能:dumps、dump、loads、load
pickle子產品提供了四個功能:dumps、dump、loads、load
import json
dic = {"name":"liu"}
data = json.dumps(dic)
f = open("Json_test","w")
f.write(data)
f.close()
import json
f = open("Json_test","r")
json.load(f)
f.close()
import pickle
def foo():
print("ok")
f = open("Pickle_test","wb")
data = pickle.dump(foo,f)
f.close()
import pickle
def foo():
print("ok")
f = open("Pickle_test","rb")
pickle.load(f)
f.close()
dumps: 将對象序列化
import json
# 簡單編碼===========================================
print json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
# ["foo", {"bar": ["baz", null, 1.0, 2]}]
#字典排序
print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
# {"a": 0, "b": 0, "c": 0}
#自定義分隔符
print json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':'))
# [1,2,3,{"4":5,"6":7}]
print json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=('/','-'))
# [1/2/3/{"4"-5/"6"-7}]
#增加縮進,增強可讀性,但縮進空格會使資料變大
print json.dumps({'4': 5, '6': 7}, sort_keys=True,indent=2, separators=(',', ': '))
# {
# "4": 5,
# "6": 7
# }
# 另一個比較有用的dumps參數是skipkeys,預設為False。
# dumps方法存儲dict對象時,key必須是str類型,如果出現了其他類型的話,那麼會産生TypeError異常,如果開啟該參數,設為True的話,會忽略這個key。
data = {'a':1,(1,2):123}
print json.dumps(data,skipkeys=True)
#{"a": 1}
dump: 将對象序列化并儲存到檔案
#将對象序列化并儲存到檔案
obj = ['foo', {'bar': ('baz', None, 1.0, 2)}]
with open(r"c:json.txt","w+") as f:
json.dump(obj,f)
loads: 将序列化字元串反序列化
import json
obj = ['foo', {'bar': ('baz', None, 1.0, 2)}]
a= json.dumps(obj)
print json.loads(a)
# [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
load: 将序列化字元串從檔案讀取并反序列化
with open(r"c:json.txt","r") as f:
print json.load(f)
json四個功能
自定義複雜資料類型編解碼
例如我們碰到對象datetime,或者自定義的類對象等json預設不支援的資料類型時,我們就需要自定義編解碼函數。有兩種方法來實作自定義編解碼。
方法一:自定義編解碼函數
import datetime,json
dt = datetime.datetime.now()
def time2str(obj):
#python to json
if isinstance(obj, datetime.datetime):
json_str = {"datetime":obj.strftime("%Y-%m-%d %X")}
return json_str
return obj
def str2time(json_obj):
#json to python
if "datetime" in json_obj:
date_str,time_str = json_obj["datetime"].split(' ')
date = [int(x) for x in date_str.split('-')]
time = [int(x) for x in time_str.split(':')]
dt = datetime.datetime(date[0],date[1], date[2], time[0],time[1], time[2])
return dt
return json_obj
a = json.dumps(dt,default=time2str)
print a
# {"datetime": "2016-10-27 17:38:31"}
print json.loads(a,object_hook=str2time)
# 2016-9-2 17:38:31
View Code
方法二:繼承JSONEncoder和JSONDecoder類,重寫相關方法
import datetime,json
dt = datetime.datetime.now()
dd = [dt,[1,2,3]]
class MyEncoder(json.JSONEncoder):
def default(self,obj):
#python to json
if isinstance(obj, datetime.datetime):
json_str = {"datetime":obj.strftime("%Y-%m-%d %X")}
return json_str
return obj
class MyDecoder(json.JSONDecoder):
def __init__(self):
json.JSONDecoder.__init__(self, object_hook=self.str2time)
def str2time(self,json_obj):
#json to python
if "datetime" in json_obj:
date_str,time_str = json_obj["datetime"].split(' ')
date = [int(x) for x in date_str.split('-')]
time = [int(x) for x in time_str.split(':')]
dt = datetime.datetime(date[0],date[1], date[2], time[0],time[1], time[2])
return dt
return json_obj
# a = json.dumps(dt,default=time2str)
a =MyEncoder().encode(dd)
print a
# [{"datetime": "2016-10-27 18:14:54"}, [1, 2, 3]]
print MyDecoder().decode(a)
# [datetime.datetime(2016, 9, 27, 18, 14, 54), [1, 2, 3]]
View Code
dumps/dump序列化
from datetime import date
try:
import cPickle as pickle #python 2
except ImportError as e:
import pickle #python 3
src_dic = {"date":date.today(),"oth":([1,"a"],None,True,False),}
det_str = pickle.dumps(src_dic)
print det_str
# (dp1
# S'date'
# p2
# cdatetime
# date
# p3
# (S'x07xe0
x1b'
# tRp4
# sS'oth'
# p5
# ((lp6
# I1
# aS'a'
# aNI01
# I00
# tp7
# s.
with open(r"c:pickle.txt","w") as f:
pickle.dump(src_dic,f)
loads/load反序列化
from datetime import date
try:
import cPickle as pickle #python 2
except ImportError as e:
import pickle #python 3
src_dic = {"date":date.today(),"oth":([1,"a"],None,True,False),}
det_str = pickle.dumps(src_dic)
with open(r"c:pickle.txt","r") as f:
print pickle.load(f)
# {'date': datetime.date(2016, 9, 27), 'oth': ([1, 'a'], None, True, False)}
pickle 功能
JSON和pickle子產品的差別
1、JSON隻能處理基本資料類型。pickle能處理所有Python的資料類型。
2、JSON用于各種語言之間的字元轉換。pickle用于Python程式對象的持久化或者Python程式間對象網絡傳輸,但不同版本的Python序列化可能還有差異。
五、執行系統指令
可以執行shell指令的相關子產品和函數有:
- os.system
- os.spawn*
- os.popen* --廢棄
- popen2.* --廢棄
- commands.* --廢棄,3.x中被移除
import commands
result = commands.getoutput('cmd')
result = commands.getstatus('cmd')
result = commands.getstatusoutput('cmd')
commands
以上執行shell指令的相關的子產品和函數的功能均在 subprocess 子產品中實作,并提供了更豐富的功能。
call
執行指令,傳回狀态碼
ret = subprocess.call(["ls", "-l"], shell=False)
ret = subprocess.call("ls -l", shell=True)
shell = True ,允許 shell 指令是字元串形式
check_call
執行指令,如果執行狀态碼是 0 ,則傳回0,否則抛異常
subprocess.check_call(["ls", "-l"])
subprocess.check_call("exit 1", shell=True)
check_output
執行指令,如果狀态碼是 0 ,則傳回執行結果,否則抛異常
subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)
subprocess.Popen(...)
用于執行複雜的系統指令
參數:
- args:shell指令,可以是字元串或者序列類型(如:list,元組)
- bufsize:指定緩沖。0 無緩沖,1 行緩沖,其他 緩沖區大小,負值 系統緩沖
- stdin, stdout, stderr:分别表示程式的标準輸入、輸出、錯誤句柄
- preexec_fn:隻在Unix平台下有效,用于指定一個可執行對象(callable object),它将在子程序運作之前被調用
-
close_sfs:在windows平台下,如果close_fds被設定為True,則新建立的子程序将不會繼承父程序的輸入、輸出、錯誤管道。
是以不能将close_fds設定為True同時重定向子程序的标準輸入、輸出與錯誤(stdin, stdout, stderr)。
- shell:同上
- cwd:用于設定子程序的目前目錄
- env:用于指定子程序的環境變量。如果env = None,子程序的環境變量将從父程序中繼承。
- universal_newlines:不同系統的換行符不同,True -> 同意使用
-
startupinfo與createionflags隻在windows下有效
将被傳遞給底層的CreateProcess()函數,用于設定子程序的一些屬性,如:主視窗的外觀,程序的優先級等等
import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)
執行普通指令
終端輸入的指令分為兩種:
- 輸入即可得到輸出,如:ifconfig
- 輸入進行某環境,依賴再輸入,如:python
import subprocess
obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
View Code
import subprocess
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
obj.stdin.write('print 1
')
obj.stdin.write('print 2
')
obj.stdin.write('print 3
')
obj.stdin.write('print 4
')
obj.stdin.close()
cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()
print (cmd_out)
print (cmd_error)
View Code
import subprocess
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
obj.stdin.write('print 1
')
obj.stdin.write('print 2
')
obj.stdin.write('print 3
')
obj.stdin.write('print 4
')
out_error_list = obj.communicate()
print (out_error_list)
View Code
import subprocess
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out_error_list = obj.communicate('print "hello"')
print(out_error_list)
View Code
六、logging
用于便捷記錄日志且線程安全的子產品
組成
主要分為四個部分:
- Loggers:提供應用程式直接使用的接口
- Handlers:将Loggers産生的日志傳到指定位置
- Filters:對輸出日志進行過濾
- Formatters:控制輸出格式
import logging
logging.basicConfig(filename='log.log',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=10)
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')
等級:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
隻有大于目前日志等級的操作才會被記錄。
七、time
時間相關的操作,時間有三種表示方式:
- 時間戳 1970年1月1日之後的秒,即:time.time()
- 格式化的字元串 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d')
- 結構化時間 元組包含了:年、日、星期等... time.struct_time 即:time.localtime()
print time.time()
print time.mktime(time.localtime())
print time.gmtime() #可加時間戳參數
print time.localtime() #可加時間戳參數
print time.strptime('2014-11-11', '%Y-%m-%d')
print time.strftime('%Y-%m-%d') #預設目前時間
print time.strftime('%Y-%m-%d',time.localtime()) #預設目前時間
print time.asctime()
print time.asctime(time.localtime())
print time.ctime(time.time())
import datetime
'''
datetime.date:表示日期的類。常用的屬性有year, month, day
datetime.time:表示時間的類。常用的屬性有hour, minute, second, microsecond
datetime.datetime:表示日期時間
datetime.timedelta:表示時間間隔,即兩個時間點之間的長度
timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
strftime("%Y-%m-%d")
'''
import datetime
print datetime.datetime.now()
print datetime.datetime.now() - datetime.timedelta(days=5)
View Code
八、re
re子產品用于對python的正規表達式的操作。
字元:
. 比對除換行符以外的任意字元
w 比對字母或數字或下劃線或漢字
s 比對任意的空白符
d 比對數字
比對單詞的開始或結束
^ 比對字元串的開始
$ 比對字元串的結束
次數:
* 重複零次或更多次
+ 重複一次或更多次
? 重複零次或一次
{n} 重複n次
{n,} 重複n次或更多次
{n,m} 重複n到m次
1、match(pattern, string, flags=0)
從起始位置開始根據模型去字元串中比對指定内容,比對單個
- 正規表達式
- 要比對的字元串
- 标志位,用于控制正規表達式的比對方式
import re
obj = re.match('d+', '123uuasf')
if obj:
print(obj.group())
2、search(pattern, string, flags=0)
根據模型去字元串中比對指定内容,比對單個
import re
obj = re.search('d+', 'u123uu888asf')
if obj:
print (obj.group())
3、group和groups
import re
a = "123abc456"
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))
print (re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())
結果
123abc456
123abc456
123
abc
('123', 'abc', '456')
4、findall(pattern, string, flags=0)
上述兩中方式均用于比對單值,即:隻能比對字元串中的一個,如果想要比對到字元串中所有符合條件的元素,則需要使用 findall。
import re
obj = re.findall('d+', 'fa123uu888asf')
print (obj)
結果
['123', '888']
5、sub(pattern, repl, string, count=0, flags=0)
用于替換比對的字元串
content = "123abc456"
new_content = re.sub('d+', 'sb', content)
# new_content = re.sub('d+', 'sb', content, 1)
print (new_content)
結果
sbabcsb
相比于str.replace功能更加強大
6、split(pattern, string, maxsplit=0, flags=0)
根據指定比對進行分組
content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('[+-*/]+', content)
# new_content = re.split('*', content, 1)
print (new_content)
結果:
["'1 ", ' 2 ', ' ((60', '30', '1', '(9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14))', '(', '4', '3)', '(16', '3', "2) )'"]
inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))'
inpp = re.sub('s*','',inpp)
new_content = re.split('(([+-*/]?d+[+-*/]?d+){1})', inpp, 1)
print (new_content)
結果:
['1-2*((60-30+', '-40-5', '*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
該電腦思路:
1、遞歸尋找表達式中隻含有 數字和運算符的表達式,并計算結果
2、由于整數計算會忽略小數,所有的數字都認為是浮點型操作,以此來保留小數
使用技術:
1、正規表達式
2、遞歸
執行流程如下:
******************** 請計算表達式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ********************
before: ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
-40.0/5=-8.0
after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953
after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
60-30+-8.0*173545.880953=-1388337.04762
after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
-4*3=-12.0
after: ['1-2*(-1388337.04762--12.0/(16-3*2))']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762--12.0/(16-3*2))']
16-3*2=10.0
after: ['1-2*(-1388337.04762--12.0/10.0)']
========== 上一次計算結束 ==========
before: ['1-2*(-1388337.04762--12.0/10.0)']
-1388337.04762--12.0/10.0=-1388335.84762
after: ['1-2*-1388335.84762']
========== 上一次計算結束 ==========
我的計算結果: 2776672.69524
"""
import re
def compute_mul_div(arg):
""" 操作乘除
:param expression:表達式
:return:計算結果
"""
val = arg[0]
mch = re.search('d+.*d*[*/]+[+-]?d+.*d*', val)
if not mch:
return
content = re.search('d+.*d*[*/]+[+-]?d+.*d*', val).group()
if len(content.split('*'))>1:
n1, n2 = content.split('*')
value = float(n1) * float(n2)
else:
n1, n2 = content.split('/')
value = float(n1) / float(n2)
before, after = re.split('d+.*d*[*/]+[+-]?d+.*d*', val, 1)
new_str = "%s%s%s" % (before,value,after)
arg[0] = new_str
compute_mul_div(arg)
def compute_add_sub(arg):
""" 操作加減
:param expression:表達式
:return:計算結果
"""
while True:
if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__('-+') or arg[0].__contains__("--"):
arg[0] = arg[0].replace('+-','-')
arg[0] = arg[0].replace('++','+')
arg[0] = arg[0].replace('-+','-')
arg[0] = arg[0].replace('--','+')
else:
break
if arg[0].startswith('-'):
arg[1] += 1
arg[0] = arg[0].replace('-','&')
arg[0] = arg[0].replace('+','-')
arg[0] = arg[0].replace('&','+')
arg[0] = arg[0][1:]
val = arg[0]
mch = re.search('d+.*d*[+-]{1}d+.*d*', val)
if not mch:
return
content = re.search('d+.*d*[+-]{1}d+.*d*', val).group()
if len(content.split('+'))>1:
n1, n2 = content.split('+')
value = float(n1) + float(n2)
else:
n1, n2 = content.split('-')
value = float(n1) - float(n2)
before, after = re.split('d+.*d*[+-]{1}d+.*d*', val, 1)
new_str = "%s%s%s" % (before,value,after)
arg[0] = new_str
compute_add_sub(arg)
def compute(expression):
""" 操作加減乘除
:param expression:表達式
:return:計算結果
"""
inp = [expression,0]
# 處理表達式中的乘除
compute_mul_div(inp)
# 處理
compute_add_sub(inp)
if divmod(inp[1],2)[1] == 1:
result = float(inp[0])
result = result * -1
else:
result = float(inp[0])
return result
def exec_bracket(expression):
""" 遞歸處理括号,并計算
:param expression: 表達式
:return:最終計算結果
"""
# 如果表達式中已經沒有括号,則直接調用負責計算的函數,将表達式結果傳回,如:2*1-82+444
if not re.search('(([+-*/]*d+.*d*){2,})', expression):
final = compute(expression)
return final
# 擷取 第一個 隻含有 數字/小數 和 操作符 的括号
# 如:
# ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
# 找出:(-40.0/5)
content = re.search('(([+-*/]*d+.*d*){2,})', expression).group()
# 分割表達式,即:
# 将['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
# 分割更三部分:['1-2*((60-30+( (-40.0/5) *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
before, nothing, after = re.split('(([+-*/]*d+.*d*){2,})', expression, 1)
print 'before:',expression
content = content[1:len(content)-1]
# 計算,提取的表示 (-40.0/5),并活的結果,即:-40.0/5=-8.0
ret = compute(content)
print '%s=%s' %( content, ret)
# 将執行結果拼接,['1-2*((60-30+( -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
expression = "%s%s%s" %(before, ret, after)
print 'after:',expression
print "="*10,'上一次計算結束',"="*10
# 循環繼續下次括号處理操作,本次攜帶者的是已被處理後的表達式,即:
# ['1-2*((60-30+ -8.0 *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
# 如此周而複始的操作,直到表達式中不再含有括号
return exec_bracket(expression)
# 使用 __name__ 的目的:
# 隻有執行 python index.py 時,以下代碼才執行
# 如果其他人導入該子產品,以下代碼不執行
if __name__ == "__main__":
#print '*'*20,"請計算表達式:", "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" ,'*'*20
#inpp = '1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) '
inpp = "1-2*-30/-12*(-20+200*-3/-200*-300-100)"
#inpp = "1-5*980.0"
inpp = re.sub('s*','',inpp)
# 表達式儲存在清單中
result = exec_bracket(inpp)
print result
大王版電腦
#__author__:Administrator
#__date__:2016/9/13
import re
def mi(arg):
while True:
relust = re.split("(d+.?d*-?[*]{2}-?d+.?d*)", arg, 1)
if len(relust) == 3:
x = relust[0]
y = relust[1]
z = relust[2]
if "**" in y:
start,end = y.split("**")
finlly = float(start) ** float(end)
arg = x + str(finlly) + z
else:
return arg
def chengchu(arg):
while True: #while循環每一次傳進來的運算
arg = arg.replace("++","+")
arg = arg.replace("+-","-")
arg = arg.replace("-+","-")
arg = arg.replace("--","+")
arg = arg.replace("*+","*")
arg = arg.replace("/+","/")
relust = re.split("(d+.?d*-?[*/]-?d+.?d*)",arg,1) #把從左往右第一次比對到得乘法
if len(relust) ==3:
x = relust[0]
y = relust[1]
z = relust[2]
if "*" in y :
start,end = y.split("*") #用“*”把分割開指派給start,end
finlly = float(start) * float(end) #運算出乘法
arg = x+str(finlly)+z #替換原來的運算式
else:
start, end = y.split("/") #用/分割開指派給start,end
finlly = float(start) / float(end)
arg = x + str(finlly) + z #替換原來的元算式
else:
return arg #将運算結果傳回去
def jiajian(arg):
result = re.findall("[+-]?d+.?d*",arg) #列出所有的元素
start = 0 #定義空值依次去加
for i in result:
start += float(i) #所有元素相加
return start #傳回運算結果
def jisuan(source):
while True:
source = source.replace(" ", "") #去掉空格
res = re.split("(([^()]*))",source,1) #先取出括号裡面的值
if len(res) ==3:
x = res[0] #分别将元素指派給三個值
y = res[1]
z = res[2]
powe = mi(y)
ch = chengchu(powe) #執行乘除
jj = jiajian(ch) #執行加減
res = x + str(jj) + z #運算結果替換原來等式
source = res #指派給其他傳進來元素
else: #沒括号得等式
powe = mi(source)
ch = chengchu(powe) #計算乘法法
jj = jiajian(ch) #計算加法
source = jj
return source
while True:
choice = input("請輸入計算等式(q退出):")
if choice =="q":
print("再見!")
break
elif choice == "":
print("-----請輸入算式-----")
continue
elif re.findall("[a-zA-Z@#¥%&]", choice):
print("--輸入不規範,請輸入算式!--")
continue
else:
value = jisuan(choice)
print("計算結果為:%s" % value)
print("eval結果為:%s" % eval(choice))
自己版電腦
九、random
随機數
import random
print (random.random())
print (random.randint(1,2))
print (random.randrange(1,10))
import random
checkcode = ''
for i in range(4):
current = random.randrange(0,4)
if current != i:
temp = chr(random.randint(65,90))
else:
temp = random.randint(0,9)
checkcode += str(temp)
print (checkcode)
随機驗證碼執行個體