Python從基礎到精通day3

文件對象、函數基礎、模塊基礎介紹:

案例1 九九乘法表

雙層for循環的套用

# 打印3個hello
for j in range(3):
    print('hello')
# 將3個hello打印在一行,並且打印完成後,在下面打印回車
for j in range(3):
    print('hello', end=' ')
print()

# 打印3行,每行打印3個hello。只要將上面代碼再放到一個循環裏
for i in range(3):
    for j in range(3):
        print('hello', end=' ')
    print()

# 實現第一行打印1個hello,第2行2個hello,第3行3個hello,第i行i個hello。只要讓range()函數不再產生固定個數的數字即可:
for i in range(3):
    for j in range(i + 1):
        print('hello', end=' ')
    print()
    
# 只要將數字改爲從1到9,把打印的hello改爲算式,就可以實現九九乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print('%s x %s = %s' % (j, i, i * j), end=' ')
    print()

print函數默認會在結尾打印回車,即end='\n',如果希望自定義在結尾打印什麼,可以使用end='xxx'

文件

  • 文件操作的三個步驟:打開、讀寫、關閉
  • 在python中,打開文件,實際上是找到文件在硬盤上的存儲位置,返回一個文件對象。可以通過這個文件對象對硬盤實現讀寫
  • 在python中一切皆對象,如字符串對象、文件對象、數字對象等。不同的對象有不同的屬性和方法。

讀取文本文件

  • 字符:即str,就是現實世界中的文字,一個字母是一個字符,一個漢字也是一個字符
  • 字節:即byte,存儲單位。計算中最小的存儲單位是比特bit,一個字節等於8bit。
  • 使用utf8編碼,一個英文字符佔一個字節,一個漢字一般佔3個字節。
  • 在python使用字節表示的時候,如果一個字節能表示成一個字符,就以字符的形式呈現;如果一個字節(8個0和1的組合)不能表示成一個字符,爲了方便就用16進制數表示
>>> s1 = 'a'
>>> s2 = '中'
>>> type(s1)
<class 'str'>
>>> type(s2)
<class 'str'>
>>> b1 = s1.encode()  # 將s1轉爲bytes類型
>>> b1
b'a'   # b是bytes類型的前綴
>>> b2 = s2.encode()  # 將s2轉爲bytes類型
>>> b2
b'\xe4\xb8\xad'
>>> type(b1)
<class 'bytes'>
>>> type(b2)
<class 'bytes'>
>>> b1.decode()  # 將bytes類型轉爲str類型
'a'
>>> b2.decode()  # 將bytes類型轉爲str類型
'中'

utf8編碼示例

A  01000001
B  01000010
C  01000011
... ...
a  01100001
b  01100010
c  01100011
... ...
中  11100100 10111000 10101101
[root@localhost day03]# vim /tmp/mytest.txt
Hello World!
How are you?
吃了嗎?
沒呢
# 默認以r的方式打開文件,文件不存在則報錯
>>> open('/tmp/mytest.doc')   # 報錯

# 以r方式打開文件,只能讀,不能寫
>>> f1 = open('/tmp/mytest.txt')  # 打開
>>> data = f1.read()   # read()默認讀取全部內容
>>> f1.close()         # 關閉
>>> data
'Hello World!\nHow are you?\n吃了嗎?\n沒呢\n'
>>> print(data)
Hello World!
How are you?
吃了嗎?
沒呢

# 注意,文件打開後,每次讀取都是繼續向下讀取,文件指針將會一直向後移動
>>> f1 = open('/tmp/mytest.txt')
>>> data = f1.read()  # 把全部內容讀出賦值給變量data
>>> data = f1.read()  # 繼續向後讀,讀出內容重新賦值給data
>>> f1.close()
>>> data
''
>>> f1.close()

# read()也可以指定一次讀多少字節
>>> f1 = open('/tmp/mytest.txt')
>>> f1.read(5)
'Hello'
>>> f1.read(8)  # 繼續向後讀取8個字節
' World!\n'
>>> f1.close()

# readline()讀取一行
>>> f1 = open('/tmp/mytest.txt')
>>> f1.readline()
'Hello World!\n'
# readlines()讀取全部,並將結果保存到列表中
>>> f1.readlines()
['How are you?\n', '吃了嗎?\n', '沒呢\n']
>>> f1.close()

讀取文本文件最常用的方法是for循環遍歷

>>> f1 = open('/tmp/mytest.txt')
>>> for line in f1:
...   print(line, end='')
... 
Hello World!
How are you?
吃了嗎?
沒呢
>>> f1.close()

讀取非文本文件

[root@localhost ]# wget https://i04picsos.sogoucdn.com/a3d305716dd0e456 -O /tmp/girl.jpg
>>> f1 = open('/tmp/girl.jpg', 'rb')
>>> f1.read(10)
b'\xff\xd8\xff\xe0\x00\x10JFIF'
>>> f1.close()

寫入文本文件

# 以w方式打開文件,如果文件已存在,則清空,不存在則創建
>>> f1 = open('/tmp/mytest.txt', 'w')
[root@localhost day03]# cat /tmp/mytest.txt  # 已清空
>>> f1.write('Hello World!\n')
13   # 表示寫入了13字節
# 查看時仍然爲空。因爲爲了提升效率,是先將數據寫入到了緩存,當緩存達到4K時,自動同步到硬盤。關閉文件時,也會同步到硬盤
[root@localhost day03]# cat /tmp/mytest.txt
>>> f1.flush()  # 立即同步數據到硬盤
[root@localhost day03]# cat /tmp/mytest.txt
Hello World!
>>> f1.writelines(['How are you?\n', '吃了嗎?\n', '沒呢\n'])
>>> f1.close()  #寫完之後需要關閉纔可查看到

寫入非文本文件

  • 跟寫入文本文件一樣,只是打開時的打開模式需要爲wb模式
  • 寫入的數據是bytes類型
>>> f1 = open('/tmp/mytest2.txt', 'wb')
>>> f1.write(b'\xe4\xb8\xad')
3
>>> f1.close()
[root@localhost day03]# cat /tmp/mytest2.txt 

with語句

  • 使用with語句打開文件,with語句結束後,文件自動關閉
>>> with open('/tmp/mytest.txt') as f1:
...   f1.readline()
... 
'Hello World!\n'
>>> f1.readline()  # 文件已關閉,報錯

總結

  • 讀取文本文件默認使用r方式打開,文件不存在則報錯,只能讀,不能寫.

  • 寫入文本文件默認使用w方式打開,沒有則創建,有則清空,所以重要文件不要以w方式打開。

  • 讀取非文本文件時使用rb方式打開,寫入非文本文件時使用wb方式打開

  • r表示read 讀取

  • w表示write 書寫

  • b表示byte字節,所以非文本文件無論是讀取還是寫入需要加b

案例1:模擬cp操作

[root@localhost day03]# vim cp.py

#!/usr/bin/env python3
with open('/bin/ls','rb') as f1:
with  open('/root/ls','wb') as f2:
data = read.f1()
f2.write(data)

案例2:模擬cp操作升級版

當需要一個複製的文件很大時,會非常消耗服務器的內存資源,可以用循環控制寫入的數據大小。

src_fname = '/etc/passwd'
dst_fname = '/tmp/passwd'
src_open = open(src_fname,'rb')
dst_open = open(dst_fname,'wb')

while 1:
    data = src_open.read(4096)
    # if len(data) == 0:   零字節
    # if data == b'':	空串
    if not data:	有數據爲真,沒數據爲假,前面加上not取反。 如果data有數據則爲假,爲假不執行breakbreak
    dst_open.write(data)

src_open.close()
dst_open.close()

函數

  • 爲一組代碼取名,完成某個功能
  • 定義函數時,函數體內的代碼不執行
  • 調用函數時,需要在函數名後面加上(),來完成調用
  • 調用函數就是執行函數體內的代碼
  • 函數定義語法結構
def 函數名(參數1, 參數2..., 參數n):
    代碼塊

參數

  • 可以理解爲參數就是函數需要用到的變量,但是變量的值還不確定
  • 定義函數時,函數名後面括號裏的名字就是參數,因爲只是形式上佔個位置,所以稱作形式參數或形參
  • 調用函數時,相當於是變量賦值。調用函數將具體的數據傳進去,這個數據是實際使用的數據,叫實際參數或實參
  • python的位置參數保存在sys模塊的argv列表中。注意:位置參數都是字符類型

案例3 斐波那契數列之模塊傳參

def mk_fib(n):
    result = [0,1]
    for i in range(n-2):
        result.append(result[-1] + result[-2])
    print(result)
a = int(input('長度:')) #當用戶輸入時將參數傳給函數
mk_fib(a)

#echo -n '10' > /tmp/len.txt   -n 表示去除回車\n
with open('/tmp/len.txt') as f1:
    data = f1.read()
    data = int(data)   #將讀出的內容轉換成int類型重新賦值
mk_fib(data)

python的位置參數保存在sys模塊的argv列表中。

  • 注意:位置參數都是字符類型

位置變量:

[root@localhost day03]# vim weizhi.py 
import sys
 
print(sys.argv)
[root@localhost day03]# python3 weizhi.py 
['weizhi.py']
[root@localhost day03]# python3 weizhi.py hao 123
['weizhi.py', 'hao', '123']
# sys.argv[0] 相當於shell腳本中的 $0 輸出文件本身的名稱
# sys.argv[1] -> $1
# sys.argv[2] -> $2
  • 默認參數:提供了默認值的參數。傳參時,如果給定了具體的值,就使用傳遞的值;如果沒有傳值,則使用默認值。

案例4:位置參數的使用

import sys
def copy(src_fname,dst_fname):  預定義參數
        src_fobj = open(src_fname,'rb')
        dst_fobj = open(dst_fname,'wb')
        while 1:
                data = src_fobj.read(4096)
                if not data:
                        break
                dst_fobj.write(data)

        src_fobj.close()
        dst_fobj.close()

#copy('/bin/touch','/tmp/touch')
copy(sys.argv[1],sys.argv[2]) $1對應src_fname,$2對應dst_fname
#python3 lianxi.py /etc/hosts   /tmp/hosts

運行測試:
[root@python day3]# python3 lianxi.py /etc/hosts /tmp/hosts
[root@python day3]# md5sum /etc/hosts
54fb6627dbaa37721048e4549db3224d /etc/hosts
[root@python day3]# md5sum /tmp/hosts
54fb6627dbaa37721048e4549db3224d /tmp/hosts

默認參數的使用

提供了默認值的參數,傳參時,如果給定了具體的值則使用具體值;如果沒有給定,則使用默認值。

>>> def pstar(n=50):
...   print('*' * n)
... 
>>> pstar(30)
******************************
>>> pstar()
**************************************************

返回值

  • 函數執行的結果,可以通過return關鍵字返回
  • 如果函數沒有return,默認返回None
  • None是真空,相當於其他語言中的null

案例5: return的使用

def mk_fib(n):
    result = [0,1]
    for i in range(n -2):
        result.append(result[-1]+result[-2])
    print(result)
    return result  #利用return返回result的值
a = mk_fib(8)  #已w方式打開,只能寫入str類型的字符
with open('/tmp/result.txt','w') as f1:
    f1.write(str(a))   #將值寫入文件中

運行測試:
[root@python day3]# python3 lianxi.py
[0, 1, 1, 2, 3, 5, 8, 13]
[root@python day3]# cat /tmp/result.txt
[0, 1, 1, 2, 3, 5, 8, 13][root@python day3]#

模塊

  • 模塊就是一個python程序文件
  • .py擴展名去除後的文件名就是模塊名
  • 文件是物理上組織代碼的形式
  • 模塊是邏輯上組織代碼的形式
[root@localhost day03]# vim star.py 
hi = 'Hello World!'

def pstar(n=50):
    print('*' * n)

[root@localhost day03]# vim mytest.py 
import star

print(star.hi)  調用star函數中的h1
star.pstar()  調用star函數中的pstar模塊

[root@localhost day03]# python3 mytest.py 
Hello World!
**************************************************
  • 模塊導入方法
# 常用方法:
# 一行導入一個模塊
>>> import sys
>>> sys.path
# 僅導入模塊的一部分方法
>>> from random import choice, randint  從random模塊裏導入choice和randint
>>> choice('abcd')
'b'
>>> randint(1, 100)
96

# 不常用方法:
# 一行導入多個模塊
>>> import time, os, shutil
>>> import getpass as gp   # 導入模塊時,添加別名
>>> passwd = gp.getpass()
Password: 
>>> passwd
'123'
  • 模塊被導入時,它的代碼會被執行一遍,這個叫加載load。不管導入多少次,只加載一次。
>>> import this     # the zen of python
>>> import this     # 不再顯示the zen of python
  • 模塊特殊屬性: __name__
    • __name__是一個變量,它的值有兩個:__main__ 和 模塊名
    • 當模塊文件直接運行時是__main__
    • 當模塊文件被其他文件import時,是模塊名
[root@localhost day03]# cat foo.py 
print(__name__)
[root@localhost day03]# cat new.py 
import foo
[root@localhost day03]# python3 foo.py   直接運行腳本name的值就爲_main_
__main__
[root@localhost day03]# python3 new.py  當腳本被當作一個模塊被其他文件調用時,name的值就爲腳本名。
foo
  • 可以根據__name__的值判斷模塊文件是直接運行,還是被導入

案例6:編寫隨機生產密碼的腳本

#!/usr/bin/env python3
from random import choice
zifuji = '123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
result='' #定義存儲結果的變量
for i in range(8):
	zifu = choice(zifuji)
	result += zifu #result = result + zifu
print(result)

測試運行:
[root@python python]# python3 lianxi.py
pUjqxcWD

案例7:使用函數再次編寫生成密碼腳本

from random import choice
from string import ascii_letters,digits #digits表示所有數字
#ascii_letters是python已經寫好的變量它表示所有大小寫字母
zifuji = ascii_letters + digits

def rand_chs(n=8): #預先定義n的值
    result =''
    for i in range(n):
        zifu = choice(zifuji)
        result += zifu
    return  result  #將拼接好的值返回出去,不返回就爲none(空)
if __name__ == '__main__': #以下內容只在直接運行此程序時輸出
    s1 = rand_chs() #默認循環8次
    s2 = rand_chs(6) #爲n重新定義新值
    print(s1)
    print(s2)

運行測試:
[root@python day3]# python3 lianxi.py
L4MGcvCX
VMuGRK

調用

此時我們可以新建一個文件來調用剛纔寫好的隨機密碼代碼

import lianxi  #去掉腳本的後綴名就是模塊名
s1 = lianxi.rand_chs(20) 利用函數功能生成一個長度爲20位的密碼
print(s1)
changdu  = len(s1)  驗證密碼長度是否爲20print(changdu)

[root@python day]# python3 diaoyong.py
fmzLms5Dtxrdb6D0FYZQ
20

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