day16學習整理-Python函數進階

2019/08/15 學習整理

函數進階

模塊的四種形式

  • 自定義模塊:若是你本身寫一個py文件,在文件內寫入一堆函數,則它被稱爲自定義慕課,即便用python編寫的.py文件
  • 點三方模塊:已被編譯爲共享庫DLL的C或C++擴展
  • 內置模塊:使用C編寫並連接到python解釋器的內置模塊
  • 包:把一系列模塊組織到一塊兒的文件夾(注:文件夾下有一個__init__.py文件,該文件夾稱之爲包)

爲何要用模塊?

  1. 用第三方或者內置的模塊是一種拿來主義,能夠極大地提高開發效率。
  2. 自定義模塊,將咱們本身程序中用到的公共功能,寫入一個python文件,而後程序的各部分組件能夠經過導入的方式來引用自定義模塊的功能。

如何使用模塊

通常咱們使用import和from...import...導入模塊。python

import的使用:

# run.py
import spam  # from the spam.py
import spam

import首次導入模塊發生了3件事:shell

  1. 以模塊爲準創造一個模塊的名稱空間
  2. 執行模塊對應的文件,將執行過程當中產生的名字都丟到模塊的名稱空間
  3. 在當前執行文件中拿到一個模塊名

模塊的重複導入會直接飲用以前創造好的結果,不會重複執行模塊的文件,即重複導入會發生:spam=spam=模塊名稱空間的內存地址編程

from 模塊名 import 具體的功能:

# run.py

from spam import money

money = 10

print(money)  # 10

from...import...首次導入模塊發生了3件事:json

  1. 以模塊爲準創造一個模塊的名稱空間
  2. 執行模塊對應的文件,將執行過程當中產生的名字都丟到模塊的名稱空間
  3. 在當前執行文件的名稱空間中拿到一個名字,該名字直接指向模塊中的某一個名字,意味着能夠不用加任何前綴而直接使用
  • 優勢:不用加前綴,代碼更加精簡
  • 缺點:容易與當前執行文件中名稱空間中的名字衝突

import和from...import...的異同(掌握)

相同點:api

  1. 二者都會執行模塊對應的文件,二者都會產生模塊的名稱空間
  2. 二者調用功能時,須要跑到定義時尋找做用域關係,與調用位置無關

不一樣點bash

  1. import須要加前綴;from...import...不須要加前綴

循環導入問題

什麼是循環導入

# m1.py
print('from m1.py')
from m2 import x

y = 'm1'
# m2.py
print('from m2.py')
from m1 import y

x = 'm2'
  • 若是運行run.py,則會報錯ImportError: cannot import name 'y'
  • 若是運行m1.py,則會報錯ImportError: cannot import name 'x'
  • 若是運行m2.py,則會報錯ImportError: cannot import name 'y'

報錯緣由:

  1. 運行m2 -> 運行到from m1 import x
  2. 建立名稱空間 m1
  3. m1 運行 -> 運行到 from m2 import y
  4. 建立名稱空間 m2
  5. m2 被運行 -> 運行到from m1 import x 可是此時發現m2已被建立 尋找x x已存在 但爲空 因此報錯

解決方案(掌握)

咱們可使用函數定義階段只識別語法的特性解決循環導入的問題,咱們也能夠從本質上解決循環導入的問題,可是最好的解決方法是不要出現循環導入。dom

方案一

# m1.py
print('from m1.py')


def func1():
    from m2 import x
    print(x)


y = 'm1'
# m2.py
print('from m2.py')

def func1():
    from m1 import y
    print(y)


x = 'm2'

方案二

# m1.py
print('from m1.py')


y = 'm1'
from m2 import x
# m2.py
print('from m2.py')

x = 'm2'
from m1 import y

模塊的搜索路徑

模塊搜索路徑的順序(掌握)

模塊其實就是一個文件,若是要執行文件,首先就須要找到模塊的路徑(某個文件夾)。若是模塊的文件路徑和執行文件不在同一個文件目錄下,咱們就須要指定模塊的路徑。編程語言

模塊的搜索路徑指的就是在導入模塊時須要檢索的文件夾。函數

導入模塊時查找模塊的順序是:

  1. 先從內存中已經導入的模塊中尋找
  2. 內置的模塊
  3. 環境變量sys.path中找

Python文件的兩種用途

python文件總共有兩種用途,一種是執行文件;另外一種是被當作模塊導入。

編寫好的一個python文件能夠有兩種用途:

  1. 腳本,一個文件就是整個程序,用來被執行
  2. 模塊,文件中存放着一堆功能,用來被導入使用
# aaa.py

x = 1


def f1():
    print('from f1')


def f2():
    print('from f2')


f1()
f2()
# run.py

import aaa

若是直接運行run.py會直接運行aaa.py中的f1()f2(),可是若是咱們在aaa.py中加上if __name__ == '__main__':這句話,則能夠防止運行run.py時執行f1()f2()。由於當aaa.py被直接執行,即當作執行文件的時候__name__ == '__main__'; 在aaa.py被當作模塊直接運行的時候__name__ == 'aaa'。由此可讓aaa.py在不一樣的場景下有着不一樣的用法。

# aaa.py

x = 1


def f1():
    print('from f1')


def f2():
    print('from f2')


if __name__ == '__main__':
    f1()
    f2()

Python包

什麼是包?

包是模塊的一種形式,包的本質就是一個含有.py的文件的文件夾。

爲何要有包?

模塊的第一個版本只有10個功能,可是將來在擴展版本的時候,模塊名和用法應該最好不要去修改,可是這只是對使用者友好,而因爲版本擴展,文件愈來愈大,模塊設計者對模塊的管理、維護會愈來愈複雜,所以咱們可使用包來擴展模塊的功能。

如何用包?

導入模塊發生的三件事:

  1. 建立一個包的名稱空間
  2. 執行py文件,將執行過程當中產生的名字存放於名稱空間中。
  3. 在當前執行文件中拿到一個名字aaa,aaa是指向包的名稱空間的

導入包發生的三件事:

  1. 建立一個包的名稱空間
  2. 因爲包是一個文件夾,沒法執行包,所以執行包下的.py文件,將執行過程當中產生的名字存放於包名稱空間中(即包名稱空間中存放的名字都是來自於.py)
  3. 在當前執行文件中拿到一個名字aaa,aaa是指向包的名稱空間的

導入包就是在導入包下的.py,而且可使用如下兩種方式導入:

  1. import ...
  2. from ... import...

Python具體模塊

json 和 pickle模塊

json:

Json序列化並非python獨有的,json序列化在java等語言中也會涉及到,所以使用json序列化可以達到跨平臺傳輸數據的目的。

json數據類型和python數據類型對應關係表

Json類型 Python類型
{} dict
[] list
"string" str
520.13 int或float
true/false True/False
null None

json模塊序列化和反序列化的一個過程以下圖所示

71json和pickle模塊-json.jpg

import json
struct_data = {'name': 'json', 'age': 23, 'sex': 'male'}
print(struct_data, type(struct_data))
{'name': 'json', 'age': 23, 'sex': 'male'} <class 'dict'>
data = json.dumps(struct_data)
print(data, type(data))
{"name": "json", "age": 23, "sex": "male"} <class 'str'>
# 注意:不管數據是怎樣建立的,只要知足json格式(若是是字典,則字典內元素都是雙引號),就能夠json.loads出來,不必定非要dumps的數據才能loads
data = json.loads(data)
print(data, type(data))
{'name': 'json', 'age': 23, 'sex': 'male'} <class 'dict'>
# 序列化
with open('Json序列化對象.json', 'w') as fw:
    json.dump(struct_data, fw)
# 反序列化
with open('Json序列化對象.json') as fr:
    data = json.load(fr)
print(data)
{'name': 'json', 'age': 23, 'sex': 'male'}

pickle:

Pickle序列化和全部其餘編程語言特有的序列化問題同樣,它只能用於Python,而且可能不一樣版本的Python彼此都不兼容,所以,只能用Pickle保存那些不重要的數據,即不能成功地反序列化也不要緊。可是pickle的好處是能夠存儲Python中的全部的數據類型,包括對象,而json不能夠。

pickle模塊序列化和反序列化的過程以下圖所示

71json和pickle模塊-pickle.jpg

import pickle
struct_data = {'name': 'json', 'age': 23, 'sex': 'male'}
print(struct_data, type(struct_data))
{'name': 'json', 'age': 23, 'sex': 'male'} <class 'dict'>
data = pickle.dumps(struct_data)
print(data, type(data))
b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00jsonq\x02X\x03\x00\x00\x00ageq\x03K\x17X\x03\x00\x00\x00sexq\x04X\x04\x00\x00\x00maleq\x05u.' <class 'bytes'>
data = pickle.loads(data)
print(data, type(data))
{'name': 'json', 'age': 23, 'sex': 'male'} <class 'dict'>
# 序列化(注意:pickle模塊須要使用二進制存儲,即'wb'模式存儲)
with open('Pickle序列化對象.pkl', 'wb') as fw:
    pickle.dump(struct_data, fw)
# 反序列化
with open('Pickle序列化對象.pkl', 'rb') as fr:
    pickle = pickle.load(fr)
print(data)
{'name': 'json', 'age': 23, 'sex': 'male'}

os 和 sys模塊

os模塊(掌握)

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下爲"\t\n",Linux下爲"\n"
os.pathsep 輸出用於分割文件路徑的字符串 win下爲;,Linux下爲:
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所指向的文件或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小

sys模塊(掌握)

sys模塊負責程序與Python解釋器進行交互,多用於處理環境變量。

方法 詳解
sys.argv 命令行參數List,第一個元素是程序自己路徑
sys.modules.keys() 返回全部已經導入的模塊列表
sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細信息
sys.exit(n) 退出程序,正常退出時exit(0)
sys.hexversion 獲取Python解釋程序的版本值,16進制格式如:0x020403F0
sys.version 獲取Python解釋程序的版本信息
sys.maxint 最大的Int值
sys.maxunicode 最大的Unicode值
sys.modules 返回系統導入的模塊字段,key是模塊名,value是模塊
sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform 返回操做系統平臺名稱
sys.stdout 標準輸出
sys.stdin 標準輸入
sys.stderr 錯誤輸出
sys.exc_clear() 用來清除當前線程所出現的當前的或最近的錯誤信息
sys.exec_prefix 返回平臺獨立的python文件安裝的位置
sys.byteorder 本地字節規則的指示器,big-endian平臺的值是'big',little-endian平臺的值是'little'
sys.copyright 記錄python版權相關的東西
sys.api_version 解釋器的C的API版本

random模塊

random模塊通常用於生成隨機數。

import random
# 大於0且小於1之間的小數
print(random.random())
0.25435092120631386
# 大於等於1且小於等於3之間的整數
print(random.randint(1, 3))
2
# 大於等於1且小於3之間的整數
print(random.randrange(1, 3))
1
# 大於1小於3的小數,如1.927109612082716
print(random.uniform(1, 3))
2.718804989532962
# 列表內的任意一個元素,即1或者‘23’或者[4,5]
print(random.choice([1, '23', [4, 5]]))
1
# random.sample([], n),列表元素任意n個元素的組合,示例n=2
print(random.sample([1, '23', [4, 5]], 2))
[[4, 5], '23']
lis = [1, 3, 5, 7, 9]
# 打亂l的順序,至關於"洗牌"
random.shuffle(lis)
print(lis)
[1, 3, 9, 7, 5]
相關文章
相關標籤/搜索