博客參考老師文章:http://m.survivalescaperooms.com/wupeiqi/
#python name is test.py#-------------------------------def func1(): passdef func2(): passdef func3(): passdef func4(): func1() func2() func3()if __name__ == '__main__' #調用上面的函數,判斷了、循環了調用等! #函數里也可以調用函數例子:def func4():#__name__ 這個是用來判斷,如果你是把這個程序當模塊導入的話他的__name__就等于這個程序的文件名,如果是手動執行這個腳本比如:python test.py 那么__name__ 就等于__main__所以,我們可以用他來做判斷,如果你是手動執行我就運行我調函數執行if下面的語句,如果你是調用模塊我下面的if判斷后面的語句就不執行!僅當模塊使用!
#如果函數當模塊導入的時候,他導入的是函數的名稱,內容沒有被導入,當你去調用的時候他才去導入函數里的信息。
一、背景
在學習函數之前,一直遵循:面向過程編程,即:根據業務邏輯從上到下實現功能,其往往用一長段代碼來實現指定功能,開發過程中最常見的操作就是粘貼復制,也就是將之前實現的代碼塊復制到現需功能處,如下
while True: if cpu利用率 > 90%: #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接 if 硬盤使用空間 > 90%: #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接 if 內存占用 > 80%: #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接
上面的代碼是就面向過程的編程,但是如果報警多了的話成百的代碼需要添加如何操作呢?復制粘貼那會死人的!在看下下面的代碼:
def 發送郵件(內容) #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接 while True: if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存占用 > 80%:
第二次必然比第一次的重用性和可讀性要好,其實這就是函數式編程和面向過程編程的區別:
二、函數式編程
函數式編程最重要的是增強代碼的重用性和可讀性:
def 函數名(參數): ... 函數體 ...
函數的定義主要有如下要點:
1、返回值
函數是一個功能塊,該功能到底執行成功與否,需要通過返回值來告知調用者。
def 發送短信(): 發送短信的代碼... if 發送成功: return True else: return False while True: # 每次執行發送短信函數,都會將返回值自動賦值給result # 之后,可以根據result來寫日志,或重發等操作 result = 發送短信() if result == False: 記錄日志,短信發送失敗...
2、參數
為什么要有參數?看下下面的例子:
如果不定義參數,用函數的話:(每個有相同功能的都寫個函數,說好的代碼簡化呢?)
def CPU報警郵件() #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接def 硬盤報警郵件() #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接def 內存報警郵件() #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接 while True: if cpu利用率 > 90%: CPU報警郵件() if 硬盤使用空間 > 90%: 硬盤報警郵件() if 內存占用 > 80%: 內存報警郵件()
使用函數:(代碼明顯少了很多,把重復的內用改為參數調用?。?/p>
def 發送郵件(郵件內容) #發送郵件提醒 連接郵箱服務器 發送郵件 關閉連接 while True: if cpu利用率 > 90%: 發送郵件("CPU報警了。") if 硬盤使用空間 > 90%: 發送郵件("硬盤報警了。") if 內存占用 > 80%: 發送郵件("內存報警了。")
函數的有三中不同的參數:
普通參數:
# ######### 定義函數 ######### # name 叫做函數func的形式參數,簡稱:形參def func(name): PRint name# ######### 執行函數 ######### # 'luotianshuai' 叫做函數func的實際參數,簡稱:實參func('luotianshuai')
但是普通參數有個問題!你在定義參數的時候定義了幾個參數,你在調用的時候必須給他幾個參數否則就報錯!
def func(name,shuai): print name,shuai#func('luotianshuai')func('luotianshuai')#報錯內容:TypeError: func() takes exactly 2 arguments (1 given)
默認參數:
在你沒有給他指定參數的時候他就會使用默認的參數!
def func(name, age = 18): print "%s:%s" %(name,age)# 指定參數func('luotianshuai', 19)# 使用默認參數func('luotianshuai')
注:默認參數需要放在參數列表最后,要不就會報錯!原因是:他的參數賦值是一個一個的賦值。如果提供了默認值的形參,你默認一定要往后排序為了就是你給那些沒有陪默認值的參數 !動態參數:
動態參數顧名思義就是可以動態的去擴展函數參數的數量!
例子:1 (多個單個變量,整合成元組)
def func(*args): print args# 執行方式一func(11,33,4,4454,5)#輸出結果:11,33,4,4454,5# 執行方式二 li = [11,2,2,3,3,4,54]func(li)#輸出結果:([11,2,2,3,3,4,54]) #如果想輸入的列表,不想讓列表稱謂元組里的僅一個元素而是讓列表的元素成為元組的元素加*即可func(*li)#輸出結果:(11,2,2,3,3,4,54)#############################################################1、接受多個參數2、內部自動構造元組3、序列,*,避免內部構造元組
例子:2(整合為字典變量)
def func(**kwargs): print args# 執行方式一func(name='luotianshuai',age=18)# 執行方式二li = {'name':'luotianshuai', age:18, 'gender':'male'}func(**li)
例子:3(整合了*args,**args)
def func(*args, **drgs): print args print dargs#例子:func(11,22,33,44,k1='luotianshuai',k2='shuaige')(11, 22, 33, 44){'k2': 'shuaige', 'k1': 'luotianshuai'}
擴展:發郵件實例
import smtplibfrom email.mime.text import MIMETextfrom email.utils import formataddrdef email(message): msg = MIMEText("郵件報警測試", 'plain', 'utf-8') msg['From'] = formataddr(["shuaige",'shuaige@test.com']) #發件人和發件郵箱 msg['To'] = formataddr(["帥哥",'451161316@QQ.com']) msg['Subject'] = message #這里我調用了參數 server = smtplib.SMTP("smtp.test.com", 25) server.login("shuaige@126.com", "pwdnq.buzhidao") server.sendmail('shuaige@126.com', ['451161316@qq.com',], msg.as_string()) server.quit()if __name__ == u'__main__': cpu = 100 disk = 500 ram = 50 for i in range(1): if cpu > 90: alert = u'CPU出問題了' #這里設置了一個變量 email(alert) #這里調用函數的時候引用了上面的變量,當執行函數的時候形參講會被替換掉,message='CPU出問題了' 發送郵件! if disk > 90: alert = u'硬盤出問題了' email(alert) if ram> 80: alert = u'內存出問題了' email(alert)

內置函數:(就是python把各個模塊中常用的一些方法給拿出來方便使用)
常用的記住之后,要知道怎么去查:
>>> li = [11,22,33,44]>>> type(li) #查看數據類型<type 'list'> >>> dir(list) #查看類型包含的那些方法>>>help(list) #查看類型中包含的方法的詳細說明
看下面的例子:
def say(): name = "tianshuai" print namesay() 這個輸出:tianshuai # 是沒有問題的,那么看下下面的例子:def say(): name = "tianshuai" print namesay()print name # 這個能不能調用呢,不能,會報錯!函數的作用域就是在函數里定義的變量不能被外面使用!
在看下面的例子:
name2 = "shuaige"def say(): name = "tianshuai" print name print name2say()輸出結果:tianshuaishuaige
問題:我在外面定義的全局變量在函數內可以改他嗎? #看下面的例子:
name2 = "shuaige"def say(): name = "tianshuai" name2 = "shuaige is shuaige" print name,name2say()print name2#輸出結果:tianshuai shuaige is shuaige #在函數內改變了shuaige #但是外面調用還是沒有改變!
但我就是想在函數里改變全局變量是否可以呢?可以!
#但是我就想在函數內改掉這個變量怎么辦呢?在函數內調用global參數?。ㄌ峁┻@個功能,但是不建議用!你在局部變量改全局變量很容易引起混亂)name2 = "shuaige"def say(): global name2 name = "tianshuai" name2 = "shuaige is shuaige" print name,name2say()print name2輸出結果:tianshuai shuaige is shuaigeshuaige is shuaige
def count(): for i in range(1,10): if i = 5: return else: print i print "Hello World" #所以當i=5的時候就直接跳出了函數了,這里是不會被打印出來了!不是循環!!!count()輸出結果:1234
return 一般寫在函數的末尾,一般你想看函數的執行結果!然后判斷后面的程序??聪旅娴睦?/span>
def count(): name = "tianshuai" for i in range(1,10): if i == 5: print "hello" else: print i return name #在這里加了一個return user = count()if user == "tianshuai": #然后判斷,看下執行結果! print "oh shuaige is coming" 執行結果:1234hello6789oh shuaige is coming #這里看下! 上面的判斷執行了!所以return這個把name的值輸出了!
操作文件時,一般需要經歷如下步驟:
一、打開文件
文件句柄 = file('文件路徑', '模式')#python中打開文件有兩種方式,即:open(...) 和 file(...) ,本質上前者在內部會調用后者來進行文件操作,推薦使用 open。3.0以后file方法講被用做其他,open方法會自動的去幫你找他調用得方法在那里!
打開文件時,需要指定文件路徑和以何等方式打開文件,打開后,即可獲取該文件句柄,日后通過此文件句柄對該文件操作。
打開文件的模式有:
"+" 表示可以同時讀寫某個文件
"U"表示在讀取時,可以將 /r /n /r/n自動轉換成 /n (與 r 或 r+ 模式同使用)
"b"表示處理二進制文件(如:FTP發送上傳ISO鏡像文件,linux可忽略,windows處理二進制文件時需標注)
二、操作操作
class file(object): def close(self): # real signature unknown; restored from __doc__ 關閉文件 """ close() -> None or (perhaps) an integer. Close the file. Sets data attribute .closed to True. A closed file cannot be used for further I/O Operations. close() may be called more than once without error. Some kinds of file objects (for example, opened by popen()) may return an exit status upon closing. """ def fileno(self): # real signature unknown; restored from __doc__ 文件描述符 """ fileno() -> integer "file descr""" return 0 def flush(self): # real signature unknown; restored from __doc__ 刷新文件內部緩沖區 """ flush() -> None. Flush the internal I/O buffer. """ pass def isatty(self): # real signature unknown; restored from __doc__ 判斷文件是否是同意tty設備 """ isatty() -> true or false. True if the file is connected to a tty device. """ return False def next(self): # real signature unknown; restored from __doc__ 獲取下一行數據,不存在,則報錯 """ x.next() -> the next value, or raise StopIteration """ pass def read(self, size=None): # real signature unknown; restored from __doc__ 讀取指定字節數據 """ read([size]) -> read at most size bytes, returned as a string. If the size argument is negative or omitted, read until EOF is reached. Notice that when in non-blocking mode, less data than what was requested may be returned, even if no size parameter was given. """ pass def readinto(self): # real signature unknown; restored from __doc__ 讀取到緩沖區,不要用,將被遺棄 """ readinto() -> Undocumented. Don't use this; it may go away. """ pass def readline(self, size=None): # real signature unknown; restored from __doc__ 僅讀取一行數據 """ readline([size]) -> next line from the file, as a string. Retain newline. A non-negative size argument limits the maximum number of bytes to return (an incomplete line may be returned then). Return an empty string at EOF. """ pass def readlines(self, size=None): # real signature unknown; restored from __doc__ 讀取所有數據,并根據換行保存值列表 """ readlines([size]) -> list of strings, each a line from the file. Call readline() repeatedly and return a list of the lines so read. The optional size argument, if given, is an approximate bound on the total number of bytes in the lines returned. """ return [] def seek(self, offset, whence=None): # real signature unknown; restored from __doc__ 指定文件中指針位置 """ seek(offset[, whence]) -> None. Move to new file position. Argument offset is a byte count. Optional argument whence defaults to 0 (offset from start of file, offset should be >= 0); other values are 1 (move relative to current position, positive or negative), and 2 (move relative to end of file, usually negative, although many platforms allow seeking beyond the end of a file). If the file is opened in text mode, only offsets returned by tell() are legal. Use of other offsets causes undefined behavior. Note that not all file objects are seekable. """ pass def tell(self): # real signature unknown; restored from __doc__ 獲取當前指針位置 """ tell() -> current file position, an integer (may be a long integer). """ pass def truncate(self, size=None): # real signature unknown; restored from __doc__ 截斷數據,僅保留指定之前數據 """ truncate([size]) -> None. Truncate the file to at most size bytes. Size defaults to the current file position, as returned by tell(). """ pass def write(self, p_str): # real signature unknown; restored from __doc__ 寫內容 """ write(str) -> None. Write string str to file. Note that due to buffering, flush() or close() may be needed before the file on disk reflects the data written. """ pass def writelines(self, sequence_of_strings): # real signature unknown; restored from __doc__ 將一個字符串列表寫入文件 """ writelines(sequence_of_strings) -> None. Write the strings to the file. Note that newlines are not added. The sequence can be any iterable object producing strings. This is equivalent to calling write() for each string. """ pass def xreadlines(self): # real signature unknown; restored from __doc__ 可用于逐行讀取文件,非全部 """ xreadlines() -> returns self. For backward compatibility. File objects now include the performance optimizations previously implemented in the xreadlines module. """ pass
三、with方法
為了避免打開文件后忘記關閉,可以通過管理上下文,即:(建議使用此方法打開文件)
with open('log','r') as f: ...
如此方式,當with代碼塊執行完畢時,內部會自動關閉并釋放文件資源。
在Python 2.7 后,with又支持同時對多個文件的上下文進行管理,即:
with open('log1') as obj1, open('log2') as obj2: pass
例子:比如要修改nginx.conf 文件然后還的回滾怎么做?
with open('nginx.conf','r') as obj1,open('nginx.conf.new','w') as obj2: for i in obj1.readlines(): i = i.strip() print i obj2.write(i) obj2.write('/n')#讀取nginx.conf每行然后存儲到新的文件nginx.conf.new里!
新聞熱點
疑難解答