自動化運維Python系列(三)之基礎函數和文件操作

函數作用

 增強代碼的重用性和可讀性

 在沒有使用函數編程之前,我們可能一直遵循的都是面向過程編程,即根據業務邏輯從上到下實現各個功能,這樣的做的壞處是代碼可讀性不強,大量冗餘代碼,而且執行效率不高;有了函數後,我們就可以將多次使用到的相同代碼模塊放在單獨的函數定義中,在任何想要調用它的地方隨時調用,這就叫做函數式編程。

 面向對象編程其實就是對函數進行再分類和封裝,讓開發"更快更好更強..."

 

函數的定義


def 函數名(參數):

       

    ...

    函數體

    ...

    返回值

函數的定義主要有如下要點:

1)def:表示函數的關鍵字

2)函數名:函數的名稱,日後根據函數名調用函數

3)函數體:函數中進行一系列的邏輯計算,如:發送郵件、計算出 [11,22,38,888,2]中的最大數等...

4)參數:爲函數體提供數據

5)返回值:當函數執行完畢後,可以給調用者返回數據

     

函數參數

可以對Python函數傳以下幾種形式的參數:

1、普通參數(嚴格按照順序,將實際參數賦值給形式參數)

2、默認參數(必須放置在參數列表的最後)

3、指定參數(將實際參數賦值給指定的形式參數)

4、動態參數:

   *        默認將傳入的參數,全部放置在元組中

   **       默認將傳入的參數,全部放置在列表中

5、萬能參數 *args,**kwargs

   

這幾種參數原理有點類似字符串的格式化輸出

str.format() 格式化輸出
s1 = "i am {0}, age {1}".format("kobe",18)
print(s1)
s2 = "i am {0}, age {1}".format(*["kobe",18])
print(s2)
s3 = "i am {name}, age {age}".format(name='kobe',age='18')
print(s3)
dic_01 = {'name':'kobe','age':18}
s4 = "i am {name}, age {age}".format(**dic_01)
print(s4)
輸出:
i am kobe, age 18
i am kobe, age 18
i am kobe, age 18
i am kobe, age 18

  

1)普通參數

def login(user,pwd):
  print(user,pwd)
login(user,pwd)

  

2)默認參數

def login(user="kobe", pwd=123):
    print(user,pwd)
login()

  

3)指定參數

def login(user, pwd):    print(user,pwd)
login(pwd=123, user="kobe")
#指定參數的話,參數順序就可以隨便

  

4)動態參數

*args 一個星號

def f1(*args):
   print(args,type(args))
f1(11,22,'hhhh')
li = [22,33,'hehe']
f1(li,'44')
f1(*li)  # 給全部的參數作爲元組的每一個元素添加
lii = 'kobe'
f1(*lii)  # 循環字符串每一個元素
輸出
(11, 22, 'hhhh') <class 'tuple'>  # 函數接受所有參數,還是原來的元組
([22, 33, 'hehe'], '44') <class 'tuple'> # 函數接受列表元素,並將他的整體作爲一個元組的一部分
(22, 33, 'hehe') <class 'tuple'> # 用一個星號可以將列表中的每一個元素添加進元組
('k', 'o', 'b', 'e') <class 'tuple'> # 字符串循環的話,是每一個字符

   

**args 兩個星號

def f2(**args):    
     print(args,type(args))
f2(n1="kobe")
dic = {'k1':'v1','k2':'v2'}
f2(kk=dic)   # 只有一個鍵值對f2(**dic)
輸出
{'n1': 'kobe'} <class 'dict'> # 兩個星號動態參數會將鍵值保存爲字典
{'kk': {'k1': 'v1', 'k2': 'v2'}} <class 'dict'> # 傳字典參數要是不加兩個**,只會出現一個鍵值對
{'k1': 'v1', 'k2': 'v2'} <class 'dict'> # 傳字典參數,正確做法是加兩個**

  

混合傳參

def f3(*args,**kwargs):     # 萬能參數只能放置在args後    
print(args)    
print(kwargs)
f3(11,22,33,k1="v1",k2="v2")
輸出
(11, 22, 33) # Python會自動將列表通過*args接收爲元組
{'k1': 'v1', 'k2': 'v2'} # 鍵值對會自動通過**args接收爲字典

  

函數擴展01:重複函數定義

def f4(a1,a2):    
     return a1 + a2def 
f4(a1,a2):    
     return a1 * a2
ret = f4(8,8)
print(ret)
輸出
64
# 原因是因爲Python執行代碼自上而下,之前被執行的 a1+a2 =16由於在內存中沒人使用,很快會被Python的垃圾回收機制所回收

  

函數擴展02:函數傳參是原值引用還是重新創建的新值?

def f5(a1):    
     a1.append(999)
li_01 = [11,22,33]
f5(li_01)
print(li_01)
輸出
[11, 22, 33, 999]
# 結果表明函數傳參是使用的引用,增加的話會改變原列表

  

函數擴展03:全局變量

NAME = "kobe"      
# 全局變量(潛規則:全局變量都用大寫)
def f6():    
    age = 18       
# 局部變量    
    global NAME    
# 修改全局變量
# 如果需要修改的變量是一個列表,則在函數裏面可以讀,可以append添加
但是不可以修改或者賦值    
    name = "jordan"    
    print(NAME,age)
f6()
輸出
kobe 18

 

Python的內置函數

425762-20160115210339553-378378117.png

 

1、 abs取絕對值

n = abs(-1)

 

2、all()所有元素爲真則爲真

n = all([1, 2, 3, 4])
print(n)

# any() 只要有真則爲真

n = any([1, 0, None])
print(n)

   

3、ascii()自動執行對象的__repr__方法
 

4、進制轉化   

# bin() 10進制轉換成2進制
# oct() 10進制轉換成8進制
# hex() 10進制轉換成16進制

  

5、bool值

# 0,None,"",[],{},() 都爲False
print(bool(0))

  

6、 bytes()

# bytes()字符串轉換字節類型
# bytearray()字符串轉換字節生成列表
# utf-8 一個漢字佔用3個字節
# gbk 一個漢字佔用2個字節
# 真是這個原因才導致很多gbk文件用utf-8打開會出現亂碼
s = "李傑"
n = bytes(s, encoding="utf-8")
print(n)
輸出
b'\xe6\x9d\x8e\xe6\x9d\xb0'

  

7、將字節轉換成字符串

n = str(bytes(s, encoding="utf-8"), encoding="utf-8")
print(n)
輸出
李傑

  

8、 定義的函數功能模塊是否可以被調用

def f1(a, b):
    return a + b
a = 100
b = 10
print(callable(f1))
輸出:
True

  

9、 ACSII碼轉換數字

print(chr(65))
print(ord('A'))
輸出:
A
65

 

10、 利用random生成6位數字加字母隨機驗證碼

import random
li = []
for i in range(6):
    r = random.randrange(0, 5)
    if r == 2 or r == 4:
        num = random.randrange(0, 9)
        li.append(str(num))
    else:
        temp = random.randrange(65, 91)
        c = chr(temp)
        li.append(c)
result = "".join(li)  # 使用join時元素必須是字符串
print(result)
輸出
335HQS
VS6RN5
...

  

11、 將字符串編譯後執行 compile → exec + eval

s = "print(123)"r = compile(s, "<string>", "exec")  # 將字符串編譯成Python代碼
exec(r)
輸出:
123

 

12、 exec 和 eval 都可以執行,通常exec功能更強大(可以接受代碼或者字符串)

# 但是 eval 有返回值,exec沒有
s = "8*8"ret = eval(s)
print(ret)
輸出:
64

  

13、 查看對象提供的功能

print(dir(dict))
輸出:
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
help(list) # 讀模塊源碼

  

14、 共97,每頁顯示10條,需要最少頁

r = divmod(97, 10)
n1, n2 = divmod(97, 10)
print(n1, n2)
輸出:
9 7

  

15、 判斷某一對象是否是某類的實例

s = [1, 2, 3]
print(isinstance(s, list))
輸出:
True

 

16、篩選函數filter

# 函數返回True,將元素添加到結果中
# filter(函數, 可迭代對象)
# 循環第二個參數,讓每一個參數去執行函數,如果返回True,表示元素合法
def f2(a):
    if a > 22:
        return True
li = [11, 22, 33]
ret = filter(f2, li)
print(list(ret))
輸出:
[33]
 
或者用lambda代替
result = filter(lambda a: a > 22, li)
print(list(result))
 
# lambda 會自動 return
f1 = lambda a: a > 30
ret = f1(90)
print(ret)

  

17、篩選函數 map

# 將函數返回值添加到結果中
# 對可迭代對象內的元素做統一操作
li = [11, 22, 33, 44]
result = map(lambda a: a+100, li)
print(list(result))
輸出:
[111, 122, 133, 144]

 

18、所有的全局變量、局部變量

NAME = 'AAA'
def show():
    a = 123
    b = 456
    print(locals())
    print(globals())
show()

 

19、hash值

# 將一個對象轉換成他的hash值
s = 'hhh'
print(hash(s))
輸出:
3160577387536464976

  

20、len長度計算

# python 3 裏面按照字符查找,返回2
# Python 2 裏面按照字節查找,返回6
s = '李傑'
print(len(s))

 

21、round取相鄰整數

print(round(1.4))
print(round(1.8))
輸出:
1
2

 

22、zip 並行迭代

l1 = ["kobe", 11, 22, 33]
l2 = ["is", 11, 22]
l3 = ["boy", 11, 22, 33]
r = zip(l1, l2, l3)
tmp = list(r)[0]
print(" ".join(tmp))
輸出:
kobe is boy


  

函數示例小程序:用戶登陸註冊

def login(user,pwd):
    """
    用戶用戶登陸驗證
    :param: user 用戶名
    :param: pwd  密碼
    :return: Ture 登陸成功 False 登陸失敗
    """
    f = open('db','r')
    for line in f:
        if line.split('|')[0] == user and line.split('|')[1] == pwd:
            return True
    return False
def register(user, pwd):
    """
    用戶用戶註冊
    :param user: 用戶名
    :param pwd: 密碼
    :return: 默認None
    """
    f = open('db', 'a')
    temp = "\n" + user + "|" + pwd
    f.write(temp)
    f.close()
def main():
    select = input("請選擇:【1】登陸 【2】註冊 :")
    if select == "1":
        print("正在登陸...")
        user = input("請輸入用戶名: ")
        pwd = input("請輸入密碼: ")
        ret = login(user, pwd)
        if ret is True:
            print("登陸成功!")
        else:
            print("登陸失敗!")
    if select == "2":
        print("正在註冊...")
        user = input("請輸入用戶名: ")
        pwd = input("請輸入密碼 ")
        ret = register(user, pwd)
        print("註冊成功!")
main()

   

三元運算&三目運算

# 三元運算 通過一條命令代替if else語句

if 1==1:
    name = "kobe"
else:
    name = "jordan"
name = "kobe" if 1 == 1 else "jordan"

 
# lambda表達式

def f1(a1):
    return a1 + 100
f2 = lambda a1, a2: a1 + a2
ret = f1(10)
ret2 = f2(100,10)
print(ret,ret2)
輸出
110 110

  

文件操作

1)打開文件

# f = open('db', 'r')  # 只讀
# f = open('db', 'w')  # 只寫,先清空
# f = open('db', 'x')  # python 3.0 新加(如果文件存在報錯,不存在則創建並寫內容)
# f = open('db', 'a')  # 追加
# f = open('db', 'r', encoding="utf-8")  # 指定字符編碼,防止亂碼
# f = open('db', 'rb')  # 以二進制打開

 

r+ a+ w+的區別

# r+ 能調整寫文件指針位置,其他的總是寫到末尾
# a+ 能讀,但是寫文件只能在末尾添加
# w+ 會先清空文件再寫
f = open('db', 'r+', encoding="utf-8")  # 如果模式沒有加 b 中文默認按照一個字符讀取數據
data = f.read(1)
f.seek(3)   # 調整文件指針到執行位置(以字節方式查找)
print(f.tell())
f.write("777")  # 會覆蓋已經存在的元素

 
2)操作文件

f.read()  # 無參數默認讀全部;有參數(b按字節;無b按字符)
f.tell()  # 查看指針位置
f.seek()  # 按字節調整指針位置
f.write()  # 寫文件
f.close()  # 關閉
f.fileno()  # 文件的描述符
f.flush()  # 強刷文件到硬盤
f.readable()  # 是否可讀
f.readline()  # 僅讀取一行
f.truncate()  # 截斷指針後面的所有數據

  
for循環文件對象

for line in f:
    print(line)

 
關閉文件

f.close()
with open('db') as f:
    pass

  
同時打開兩個文件

with open('db01') as f1, open('db02') as f2:
    pass

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章