代碼褲子:https://github.com/lotapp/BaseCode/tree/mastehtml
在線編程:https://mybinder.org/v2/gh/lotapp/BaseCode/masterpython
最新預覽:http://www.cnblogs.com/dotnetcrazy/p/9253087.htmlgit
老師休假度蜜月去了,這學期也到了尾聲,小明同窗以爲本身學的挺好的,在四處逛遊的過程當中看見了小潘的電腦,而後驚到了!程序員
# 導入matplotlib的pyplot模塊
import matplotlib.pyplot as plt
x_list=list(range(1,11))
y_list=[y*2+1 for y in x_list]
print(x_list)
print(y_list)
# 畫圖
plt.plot(x_list,y_list)
# 設置X,Y的座標區間(能夠不設置,用默認顯示方式)
plt.axis([0,10,0,25])
# 顯示圖片
plt.show()
小潘昨晚螃蟹吃多了,今天拉肚子拉的不要不要的,如今去藥店買紫蘇和乾薑來解蟹毒呢github
怎麼辦呢,感受本身再也不萌萌噠了,好心情瞬間被比下去了,小明心裏不斷思索中....web
做爲一個吃胖了的小明,過了一分鐘就調節好了,而後好好看小潘的Codeshell
咦,第一句是啥?無論,繼續看x_list=list(range(1,11))
y_list=[y*2+1 for y in x_list]
編程
這不是以前老師講的列表生成式嗎?而後就是畫圖了,好像也不是很難,開頭究竟是個啥,有了這個就能夠幾句話實現牛逼哄哄的技能了,不行得買瓶飲料問問課表明偉哥~json
一進偉哥宿舍就發現,偉哥在給舍友們補課?這是要講課的節奏嗎?趕忙湊過來學習~緩存
模塊就是一組功能的集合體,咱們的程序能夠導入模塊來複用模塊裏的功能
在Python中,一個py文件就稱之爲一個 模塊(Module)
咱們先來說講 模塊怎麼導入,上學期咱們學了點C,發現每一個文件開頭都有一個#include <stdio.h>
這個就相似咱們說的模塊導入了,我們Python的模塊導入和Java有點像用 import
來導入
先看個例子 ~ 咱們定義了一個test.py文件,裏面定義了這麼一個函數:
# %load test.py
def show():
print("---show---")
咱們想在新的py文件中使用這個函數
import test
把這個文件直接導入進來了
import test
test.show()
執行結果:
---show---
有時候咱們只須要用到模塊中的某個函數,只須要引入該函數便可
from test import show
把這個文件的show方法導入進來,調用的時候直接show()
便可
from test import show
show()
執行結果:
---show---
使用模塊有什麼好處?
提升了代碼的維護性,當一個模塊編寫完畢,就能夠被其餘地方引用。
使用模塊還能夠 避免函數名和變量名衝突。相同名字的函數和變量徹底能夠分別存在不一樣的模塊中
咱們本身在編寫模塊時,沒必要考慮名字會與其餘模塊衝突(不要和內置函數名字衝突)
看着小明一愣一愣的,加上那瓶菊花茶的面子,課表明來了一個demo:
test1.py
test_str = "111"
def show():
print(__name__, "show")
test2.py
test_str = "222"
def show():
print(__name__, "show")
能夠以,
分隔(這種導入方式,官方推薦多行導入)
import test1, test2
print(test1.test_str)
print(test2.test_str)
test1.show()
test2.show()
結果:
111 222 test1 show test2 show
還能夠用這種方式,該模塊裏面的函數名、變量名以逗號分隔(不用多行)
經過這種方式引入的時候,是當兩個模塊中含有相同名稱函數的時候,後面一次引入會覆蓋前一次引入,因此用as
來避免一下
from test1 import show as show1, test_str as test_str1
from test2 import show as show2, test_str as test_str2
print(test_str1)
print(test_str2)
show1()
show2()
結果:
111 222 test1 show test2 show
若是想引入模塊中全部東西能夠用 from 模塊名 import *
,這樣全部被容許(過會講)的變量和函數都被導入進來了(少用)
from 模塊名 import
好處:使用起來方便了,壞處:容易與當前執行文件中的名字衝突
小明恍然大悟,盯着__name__
看了很久,而後結合前面的知識,乘着旁邊位置電腦沒人,寫了一半的demo卡殼了:
get_infos.py
def get_infos():
print("信息以下:xxxx")
def main():
get_infos()
if __name__ == '__main__':
main()
偉哥過來瞟了一眼繼續講到:
以前老師講面向對象的時候有提到標準格式寫法:
def main():
get_infos()
if __name__ == '__main__':
main()
python文件能夠有兩種用途:
那怎麼區分呢?就要用到__name__
了
咱們來看個案例就懂了:
get_user_infos.py
def get_infos():
print(__name__)
print("信息以下:xxxx")
def main():
get_infos()
if __name__ == '__main__':
main()
再定義一個函數來調用它
import get_user_infos as user_infos
user_infos.get_infos()
直接執行的時候__name__
等於__main__
,別人調用的時候顯示該文件名
這樣的好處就是==> 避免被別人導入的時候執行某些Code
小明樂壞了,平時和小潘之前作項目老被吐槽,學了這個得好好嘲諷一下小潘了
之後不再怕直接py文件各類問題了,我們能夠先簡單自測一下O(∩_∩)O哈!
在一個模塊中,咱們可能會定義不少函數和變量,但有的函數和變量咱們但願給別人使用,有的函數和變量咱們但願僅僅在模塊內部使用。在Python中,是經過_
前綴來實現的
小明同窗基礎功底紮實,看見標題小明就樂了,前面看了這麼多案例瞬間秒懂,大叫道~」等一下~~~我來寫demo,要是不行請大家吃晚飯~「
寫下了以下代碼:
test3.py
def test1():
print("test1")
def _test2():
print("test2")
def __test3():
print("test3")
調用代碼:
import test3
test3.test1()
test3._test2()
test3.__test3()
結果:
test1 test2 test3
你們大眼瞪小眼的看着小明,嘴角邊露出了陰謀的味道~
這下小明傻眼了,難道老師以前類的私有系列講錯了?
小平瞥了小明一眼說道,你本身的打開方式不對還怪老師咯?看我給你改改~
調用代碼:
from test3 import *
test1()
_test2()
__test3()
小明運行後就傻眼了,心想到,課表明這個宿舍臥虎藏龍啊,下次少來點,否則這點老底就被他們吃空了
NameError: name '_test2' is not defined
註釋掉_test2()
運行結果: NameError: name '__test3' is not defined
小明有點尷尬,而後轉了個話題,說道:」那import不是無敵了?咱們的私有不給力啊?「
偉哥語重心長的說道:
相似_xxx
和__xxx
這樣的函數或變量就是非公開的(private),不該該被直接引用
之因此咱們說,「不該該」被直接引用,而不是「不能」被直接引用,是由於Python並無一種方法能夠徹底限制訪問private函數或變量
好比小明的那種方式就能夠直接使用了,可是從編程習慣上不該該引用private函數或變量。
咱們平時使用的時候:
外部不須要引用的函數所有定義成private,只有外部須要引用的函數才定義爲public,而後導入的時候儘可能使用from ... import
來個案例便可:
test4.py
__all__ = ["Dog", "test1", "name"]
class Animal(object):
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
def test1():
print("test1")
def test2():
print("test2")
def test3():
print("test3")
name = "小明"
age = "22"
效果:只有__all__
列表裏面的才能被訪問
小明,看到使用的電腦出現了這麼多的pyc文件,覺得中毒了,慌了慌了,連忙問道:"偉哥偉哥,這個pyc是啥啊?不會是病毒吧?"
├── 1.def_module.py ├── 2.use_module.py ├── 3.use_name.py ├── 4.use_module.py ├── 5.use_all_.py ├── get_user_infos.py ├── __pycache__ │ ├── get_user_infos.cpython-36.pyc │ ├── test1.cpython-36.pyc │ ├── test2.cpython-36.pyc │ ├── test3.cpython-36.pyc │ ├── test4.cpython-36.pyc │ └── test.cpython-36.pyc ├── test1.py ├── test2.py ├── test3.py ├── test4.py └── test.py
旁邊小李嘲笑道~」這你都不知道「
爲了 提升加載模塊的速度,python解釋器會在pycache目錄中下緩存每一個模塊編譯後的版本
格式爲:模塊名.Python版本號.pyc
這種命名規範保證了編譯後的結果多版本共存
小明問道,那我更新文件它怎麼辦呢?
小李瞥了一眼說道:
Python檢查源文件的修改時間與編譯的版本進行對比,若是過時就自動從新編譯
而且編譯的模塊是平臺獨立的,因此相同的庫能夠在不一樣的架構的系統之間共享
小明恍然大悟,說道:
這不相似於Java和Net嘛,未來咋們編寫的東西均可以跨平臺了啊,O(∩_∩)O~,反正是由python虛擬機來執行的,太方便了
PS:pyc文件是能夠反編譯的,於是它的出現僅僅是用來提高模塊的加載速度的,不是用來加密的
小明乘着你們休息的時候回宿舍拿了個筆記本,繼續聽道:
當你導入一個模塊,Python解析器對模塊位置的搜索順序是:
sys.path
變量中。變量裏包含當前目錄,PYTHONPATH和由安裝過程決定的默認目錄總之你看sys.path
就對了
前幾天時間發佈了Python3.7,咱們設置vscode的運行環境爲Python3.7,而後看看:
我用的是conda的一個路徑,Python3.7相關的一下插件沒那麼完善,我用的是3.6系列,3.7
你能夠用來練習一下新語法糖
['', # 當前目錄 '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7/dist-packages', '/usr/lib/python3/dist-packages']
小明心想,我是省事直接裝了個conda路徑是啥呢?因而本身測試了下:
# conda的默認搜索路徑
import sys
print(sys.path)
運維方面用些許,平時用的不是不少,一帶而過~
細心能夠看到,sys.path是一個列表,那麼你對其添加刪除操做也是和list同樣的
好比這個場景,服務器給不一樣的用戶使用,又不想他們的程序訪問到超過其文件夾外的文件(系統、其餘用戶)
那麼能夠弄一個公共的庫文件夾(手段先不用管),用程序模擬一下
這種方法是在運行時修改,運行結束後失效
其實還能夠設置環境變量pythonpath
,該環境變量的內容會被自動添加到模塊搜索路徑中。設置方式與設置Path環境變量相似。
注意只須要添加你本身的搜索路徑,Python本身自己的搜索路徑不受影響。(列表第二個就是說的這個)
import語句是能夠在程序中的任意位置使用的,且針對同一個模塊很import屢次
爲了防止你重複導入,python的優化手段是:
第一次導入後就將模塊名加載到內存了,後續的import語句僅是對已經加載到內存中的模塊對象增長了一次引用,不會從新執行模塊內的語句
看個例子:
想要從新導入修改的模塊,可使用官方推薦的方法:importlib
下面的reload
方法
from importlib import reload
reload(test)
固然了你也可使用imp
下面的reload
方法(3.4日後,官方就不推薦使用 **imp** 了)
稍微提一下循環導入(相似於C#循環引用),能避免就避免。
子模塊相對獨立,儘可能別相互導入,經過父模塊來調用 (有點像微服務的感受)
這樣不會混亂也不會出現循環導入的問題了
若是項目裏面真的出現了循環導入,那麼能夠這麼解決(參考):
看到標題小明就樂了,這不~終於能夠說話了,不用被他們壓抑的不敢出聲了~
以前說了不少,好比time
,random
,sys
等等,此次再擴充幾個用的比較多的模塊
後面demo裏面還會再說,能夠本身學習一下(官方文檔)(源碼文件)
在Python中,一般有這幾種方式來表示時間:
因爲Python的time模塊實現主要調用C庫,因此各個平臺可能有所不一樣
type(time.time())
==> float
time()
,clock()
(這個Win和Xinux系列有些區別)等看到表格不用懷疑,沒錯,更詳細能夠看官方介紹
| 索引 | 屬性 | 值 | | ---- | -------------------------| ------------------------- | | 0 | tm_year(年) | eg:2018 | | 1 | tm_mon(月) | range [1, 12] | | 2 | tm_mday(日) | range [1, 31] | | 3 | tm_hour(時) | range [0, 23] | | 4 | tm_min(分) | range [0, 59] | | 5 | tm_sec(秒) | range [0, 61] | | 6 | tm_wday(星期幾) | range [0, 6](0表示週日) | | 7 | tm_yday(一年中的第幾天) | range [1, 366] | | 8 | tm_isdst(是不是夏令時) | 0, 1 or -1 |
datetime
模塊
datetime.datetime.now().strftime("%Y-%m-%d %X")
主要是時間相關的封裝,案例在time模塊的下面:
import time
# 時間戳,結果是float類型
print(time.time())
# 格式化的時間字符串:年-月-日 小時:分鐘:秒
print(time.strftime("%Y-%m-%d%X"))
print(time.localtime()) # 本地時區的 struct_time
print(time.gmtime()) # UTC時區(世界標準時間)的struct_time
# time.mktime 將一個 struct_time 轉化爲時間戳
print(time.mktime(time.localtime()))
# t = time.localtime()
# print(time.asctime(t)) # 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'
# print(time.asctime()) # 不寫參數默認就是time.localtime()
import datetime
print(datetime.datetime.now()) # 當前時間 2018-07-03 13:02:20.824494
print(datetime.datetime.now().strftime("%Y-%m-%d%X")) # 當前時間 2018-07-03 13:02:20
# 時間加減
print(datetime.datetime.now() + datetime.timedelta(3)) # 當前時間+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) # 當前時間-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 當前時間+3小時
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 當前時間+30分
random
小明有好好研究,因而搶着講解:
經常使用方法主要是這幾個:
random.random()
:大於0且小於1之間的小數
random.randint(1, 3)
:[1,3] 大於等於1且小於等於3之間的整數
random.randrange(1, 3)
:[1,3) 大於等於1且小於3之間的整數
random.choice([4, 'a', [1, 2]])
:隨機返回三者之一
random.uniform(1, 3)
:大於1小於3的小數,如1.927109612082716
random.sample(old_list, 5)
:從list中隨機獲取5個元素,做爲一個片段返回
random.shuffle(old_list)
:打亂list的順序
下面來看看例子吧(最下面有個簡單驗證碼的demo):
import random
print(random.random()) # 大於0且小於1之間的小數
print(random.randint(1, 3)) # [1,3] 大於等於1且小於等於3之間的整數
print(random.randrange(1, 3)) # [1,3) 大於等於1且小於3之間的整數
print(random.choice([4, 'a', [1, 2]])) # 隨機返回三者之一
print(random.uniform(1, 3)) # 大於1小於3的小數,如1.927109612082716
# 從list中隨機獲取N個元素,做爲一個片段返回
old_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
new_list = random.sample(old_list, 5) # 從list中隨機獲取5個元素,做爲一個片段返回
print(old_list)
print(new_list) # 原有序列並無改變
test_list = [1, 3, 5, 7, 9]
random.shuffle(test_list) # 打亂test_list的順序
print(test_list)
# 簡單驗證碼的例子
import random
def get_code(n):
"""簡單驗證碼"""
code = ""
for i in range(n):
s1 = chr(random.randint(65, 90)) # 字母
s2 = str(random.randint(0, 9)) # 數字
code += random.choice([s1, s2]) # 隨機返回s1 or s2
return code
def main():
print(get_code(4))
if __name__ == '__main__':
main()
一看到hashlib,小明就退縮了,只能繼續聽偉哥講解:
官方文檔:https://docs.python.org/3/library/hashlib.html
簡單hash:hashlib.sha256(pass_str.encode("utf-8")).hexdigest()
和key一塊兒加密:
import hashlib
pass_str = "123456"
m = hashlib.sha256()
m.update(pass_str.encode("utf-8"))
m.update("你設置的key".encode("utf-8"))
pass_str_new = m.hexdigest()
擴展:python 還有一個hmac
模塊,它內部對咱們建立key
和pass
進行處理後再加密:https://docs.python.org/3/library/hmac.html
import hashlib
pass_str = "123456"
# 簡單hash一下
m = hashlib.sha256()
m.update(pass_str.encode("utf-8"))
pass_str_new = m.hexdigest()
print(pass_str_new)
print(len(pass_str_new))
# 簡寫:
hashlib.sha256(pass_str.encode("utf-8")).hexdigest()
# 簡寫這麼方便爲何要像上面例子那麼複雜呢?
# 直接加密的方式能夠經過撞庫破解,但你能夠設置個key來加大難度
# 大部分網站都是用平臺key + 用戶key(能夠是用戶建立時間或者id之類的不變信息)來加密的
m = hashlib.sha256()
m.update(pass_str.encode("utf-8"))
m.update("你設置的key".encode("utf-8"))
pass_str_new = m.hexdigest()
print(pass_str_new)
print(len(pass_str_new))
經常使用模塊裏面還有不少,就不一一介紹了,好比:functools
裏面的偏函數partial
這個咱們下次講閉包相關知識會說的functools.partial(函數名, 默認參數1,默認參數2...)
第三方模塊安裝以前有說過:http://www.javashuo.com/article/p-tvzhtwbx-bq.html
簡單提一下:(pip官網)
pip install 模塊名 # 正常
sudo pip install 模塊名 # 沒權限運行
pip install --user 模塊名 # conda下的pip
若是不想讓包破壞本身的環境,可使用:virtualenv
,你能夠做爲擴展瞭解下(參考)
若是不一樣的人編寫的模塊名相同怎麼辦?
小明搶答曰:」爲了不模塊名衝突,Python又引入了按目錄來組織模塊的方法,稱爲包(Package)「
小張斜了一眼小明補充道:」相互間有聯繫功能的模塊能夠放在一個包裏,這個包就有點像C#的文件夾和類庫的概念了「
小明不服氣的把小潘那段代碼的開頭貼了出來:import matplotlib.pyplot as plt
,而後叫囂道:」怎麼樣,這個確定用到了包「
課表明看着這兩個活寶,而後繼續講解道:
模塊是一組Python代碼的集合,可使用其餘模塊,也能夠被其餘模塊使用
好比一個模塊的名稱是A.B
, 那麼他表示一個包A
中的子模塊B
剛說完,小明就得意的看着小張,而後繼續聽課:
建立本身的模塊時,要注意:
下面咱們來一個簡單的案例:
本身定義一個包,目錄結構以下:(__init__.py
是空文件)
web/ ├── data.py ├── __init__.py └── json.py
調用web包裏面的get_json()
方法:
from web.json import get_json
get_json()
或者:
import web.json as json
json.get_json()
每個包目錄下面都會有一個__init__.py
的文件,這個文件是必須存在的,不然Python就把這個目錄當成普通目錄
__init__.py
能夠是空文件,編譯器默認會把它認成名字是文件夾名的模塊,eg:web
還記得以前講得__all__
吧,若是你想控制包裏面的模塊可否被訪問使用,可使用它
好比web包下的init文件中寫下這一句:__all__ = ["json"]
神奇的事情發生了:
from web import *
json.get_json()
data.get_data()
在調用data.get_data()
的時候出現了以下錯誤:
NameError: name 'data' is not defined
小明想到了本身當時的那頓飯,而後用當時的思路試了下:
# 你這樣調就不行了
import web
web.data.get_data()
發現和上面同樣的錯誤,而後誇張的說道~「哈哈哈,這種方式無敵了,裏面有誰能調data模塊
下的get_data()方法
我就請他喝飲料!」
話剛落完,發現你們刷刷的提交了相同的代碼:
# 一樣的,你硬是要調,python也拿你沒辦法
import web.data as data
data.get_data()
小明頓時崩潰了,自我安慰到:「反正都是要請大家吃晚飯的了,也不差這飲料了...」
把咱們以前的Code作一個包,目錄結構以下:
├── datalib │ ├── base │ │ ├── get_user_infos.py │ │ ├── __init__.py │ │ ├── test1.py │ │ ├── test2.py │ │ ├── test3.py │ │ ├── test4.py │ │ └── test.py │ ├── __init__.py │ ├── main.py │ └── web │ ├── data.py │ ├── __init__.py │ └── json.py └── setup.py
模塊的目錄結構中包含一個setup.py文件,用於定義模塊名稱、包含的模塊等模塊信息
固定格式以下:
setup(name="模塊名稱", version="版本", description="模塊描述", author="模塊做者", py_modules=[包含的模塊內容])
以demo爲例:
from distutils.core import setup
setup(
name="datalib",
version="1.0",
description="數據相關的模塊",
author="小明",
py_modules=[
"datalib.base.get_user_infos", "datalib.base.test", "datalib.web.json"
])
build命令(構建模塊):python setup.py sdist
來張圖更形象:
build文件夾:
dnt@MZY-PC:~/xiaoming/build$ tree . └── lib └── datalib ├── base │ ├── get_user_infos.py │ ├── __init__.py │ └── test.py └── web ├── __init__.py └── json.py
生成發佈壓縮包:python3 setup.py sdist
他會幫你打包成一個tar.gz
的壓縮包
其實你不構建,直接sdist也是能夠的
dnt@MZY-PC:~/xiaoming$ tree . ├── datalib │ ├── base │ │ ├── get_user_infos.py │ │ ├── __init__.py │ │ ├── test1.py │ │ ├── test2.py │ │ ├── test3.py │ │ ├── test4.py │ │ └── test.py │ ├── __init__.py │ ├── main.py │ └── web │ ├── data.py │ ├── __init__.py │ └── json.py ├── dist │ └── datalib-1.0.tar.gz ├── MANIFEST └── setup.py
安裝比較簡單,若是是build文件夾,直接sudo python setup.py install
若是是tar.gz,那麼解壓後再執行sudo python setup.py install
固然了,也能夠目錄安裝:python setup.py install --prefix=路徑
查看包內容:tar -tvf datalib-1.0.tar.gz
解包:tar -zxvf datalib-1.0.tar.gz
這些基礎命令若是還不是很熟悉的話,能夠看看逆天2015年寫的LinuxBase文檔
其實說句內心話,2015開始摸索虛擬機中的Linux,幾年提高確定是有的,可是絕對沒有這幾個月的Linux真機開發來得快
逆天仍是建議程序員儘快適應Linux環境開發,剛開始的確不方便,適應以後就感受Win特別麻煩了...
不少東西一個指令就能夠實現的,重複執行的東西寫個腳本批量執行
固然了你Win下各類跑腳本也是同樣的,可是別忘了~公司服務器基本上都是Linux的,該面對的總該來的,加油~
Old C#相關的知識能夠參考:如何在nuget上傳本身的包
NetCore能夠用打包命令:dotnet-pack
來打包成Nuget包,官方文檔說的很詳細了,就不一一複述了
打包當前目錄中的項目:dotnet pack
打包 app1 項目:dotnet pack ~/projects/app1/project.csproj
打包當前目錄中的項目並將生成的包放置到 nupkgs 文件夾:
dotnet pack --output nupkgs
將當前目錄中的項目打包到 nupkgs 文件夾並跳過生成步驟:
dotnet pack --no-build --output nupkgs
使用 PackageVersion MSBuild 屬性將包版本設置爲 2.1.0:
dotnet pack /p:PackageVersion=2.1.0
打包特定目標框架的項目:
dotnet pack /p:TargetFrameworks=net45
打包項目,並使用特定運行時 (Windows 10) 進行還原操做(.NET Core SDK 2.0 及更高版本):
dotnet pack --runtime win10-x64
小明聽完了這節課,感嘆道~ 「模塊用起來真是爽啊」
而後問道:「爲何老師沒講呢?」
其餘人一塊兒鄙視小明說道:「你本身睡大覺你本身內心沒有點逼數嗎?」
小明大囧,感受飲料和飯錢真是白花了。。。(完)