Python
是“龜叔”在1989年打發無聊聖誕節的創作
我無聊時候在幹嘛? 發呆
文章目錄
1.前言
-
缺點
- 運行速度慢
解釋性,翻譯成CPU能理解的機器碼
- 代碼不能加密
發佈程序就是發佈原碼,編譯型就是機器碼發佈
,
- 運行速度慢
-
版本
2.x和3.x不兼容
-
命令行執行
python hello.py
-
輸出
print("hello","world")
中間的逗號表示輸出一個空格
-
輸入
input()
返回的是字符串類型
前言就到這裏啦! 最最基本的東西,py
本身入門也是很簡單的,有編程基礎的很快就可以入門
2.基礎
- 註釋
#
可不是什麼雙斜槓哦 ,雙斜槓在其他地方另有含義
- 縮進
- 堅持四個空格
- 縮進使
複製-粘貼
變得麻煩
- 數據類型
- 整數
任意大小,永遠是精確的
- 浮點數
存在四捨五入
- 字符串
- 轉義字符前面加上反斜槓取消轉義
- 單引號,雙引號普通字符,存在轉義
- 三引號原樣輸出,不存在轉義
- 表示
- 在內存中是 Unicode
- 把字符送到網絡或磁盤上需要編碼成byte
encode
name=b"Primer"
注意前綴b - 從網絡或磁盤上讀取字符需要解碼
decode
- 格式化輸出
(C語言的都理解)
- 方法一
%
- %d
- %f
- %s
- %x
- 但是用法有點特別
print("hello,%s"%("primer"))
注意百分號和括號裏面的內容
- 方法二
format()
print("hello,{0},今晚去哪? 去{1}".format("小李","派對"))
- 方法一
- 布爾值
- 只有
True False
- 結合
and or not
- 只有
- 空值
None
- 整數
- 編碼
- 可變長編碼
UTF-8
又一個Unicode字符,根據字符所用字節個數,編碼成二進制大小 - 獲取字符的十進制數
ord(char)
只接受單個字符 - 根據十進制數獲取字符
chr(int)
- 編碼轉換
string.encode(編碼格式)
- 注意編碼範圍,比如中文不能使用ascii轉換,中文的範圍大,由輸出單個字符的十進制數大小可知
- 可變長編碼
- list
- 定義是使用
中括號
- 與C語言的數組無差別,有一點特殊的就是可以反向負數遍歷
-1表示最後一個,以此類推
- 定義是使用
- tuple
- 不可修改
- 定義是使用
小括號
- 只有一個元素時候需要
末尾加逗號
- 條件判斷
- if True:
- else :
- elif True :
- 循環
- for item in items:
- range(number) 生成0-number-1的整數序列
- while True :
- break ,continue
- for item in items:
- 字典
dict
- Java中的map
d={'name':'primer'}
- key不可變
- set
- 值不重複
s = set([1,2,3])
需要提供一個list
3.函數
-
def
定義函數def hello(x):
-
空函數
def nop(): pass
- pass就是個佔位符是代碼正常運行,再無它意,但缺少就是語法錯誤
-
多返回值
return 23,456
- 假象的多返回值,其實就是返回一個不可變的tuple,go語言的纔是真的多值返回
-
默認參數
- 一定要指定不變對象
def addstr(name=None):
- 一定要指定不變對象
-
可變參數
def fun(*num)
星號的使用 其實就是參數被封裝爲tuple傳到裏面去
-
關鍵參數
注意咯,一個參數就是一個字典類型
def funb(**b): print(b)
funb(city="japan",name="primer")
4.高級特性
- 切片
- 操作對象
list tuple
a[0:3]
0省略a[-2:-1]
倒數"主函數"[:2]
- 操作對象
- 迭代
for i in items
只要items是可迭代的對象 [如何判斷對象是否可迭代?isinstance(obj,iterable)
]- 下標迭代
for i, value in enumerate(['A', 'B', 'C']):
- 列表生成式
- 生成一個列表list ? 什麼樣的列表,你儘管想!
- 生成器
generator
- 一邊循環一邊計算,不一次性生成全部數據
(x * x for x in range(10))
- 獲取下一個元素
next(g)
調用next時候就是在計算下一個元素的值並獲取
5.函數式編程
-
特色
- 允許把函數本身作爲參數傳給函數,允許返回函數
-
高階函數
- 函數名也是變量,可以把函數名賦值給變量,那麼該變量就相當於是此函數的別名
- map/reduce
- map接受一個自定義函數和序列
- filter
過濾
- 過濾函數,滿足條件就留下元素,否則刪除
- 惰性函數,需要的時候纔會執行過濾
怎麼理解惰性? 比如已件事情,能留給明天做的絕不今天做(可我不想),能有多懶就多懶,能拖多久就拖多久
- sorted
sorted([],key)
- 函數名也是變量,可以把函數名賦值給變量,那麼該變量就相當於是此函數的別名
-
返回函數
- 把函數作爲返回結果
這種返回其實是惰性的,你若是需要結果,則把返回的值作爲函數形式再執行一次即可[就是變量後面在家一對小括號表示執行該函數]
- 閉包
- 把函數作爲返回結果
-
匿名函數
lambda x: 函數體
-
裝飾器
-
函數名就是變量,可以再次複製,然後調用就是
f() 加小括號形式
-
屬性
__name__
獲取函數屬性,比如函數名__main__
就是函數入口if __name__ == '__main__': print(__name__) #輸出__main_
-
所以什麼是裝飾器?
Java中的裝飾模式一樣,就是:運行期間動態添加功能
- 本質是返回函數的高階函數
一開始有點懵,慢慢理解
- decorator裝飾器就是接受一個參數是函數的函數?
有點繞了? 比如:以前函數的參數是int,那麼作爲裝飾器時候,函數的參數就是 函數 ok?
- 本質是返回函數的高階函數
-
-
偏函數
functools.partial
創建偏函數- 啥事偏函數?還沒理解?
- 把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數
6.模塊
__init__.py
文件- 每一個包目錄下面都會有一個,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄,而不是一個包
- 調用另一個包中
__init__.py
中的函數- 先導入包
import primer
- 調用函數需要加包名
primer.sayName("tom")
- 先導入包
- 調用另一個包中其他
py文件
的函數- 導入該
py文件
from primer import Hello
- 調用函數需要加
py文件名
Hell.Who("tom")
- 導入該
- 作用域 Java中的public等
- 下劃線
_
開頭的變量時 private私有的
- 下劃線
- 安裝第三方包
- 方式一
- 工具pip
我在安裝PyCharm時候勾選安裝並且添加到path環境變量中了
- 安裝
pip install name
- 工具pip
- 方式二
- Anaconda工具
- 導包
import name
- 方式一
7.面向對象
-
類
抽象的模板
class Student(object): pass #objetc表示繼承自哪一個父類,object就是終極父類,與Java中的Object是一樣的
-
在類裏面訪問控制符就起很大作用了,
就是下劃線開頭的變量或者方法名
-
__init__方法
兩個下劃線哦,我認爲跟構造函數類似
class Student():
def __init__(self,name,id):
self.name = name
self.id = id
def sayName(self):
print(self.name)
if __name__ == '__main__':
print("程序入口")
s = Student("老李",24)
s.sayName()
# self代表本身,第一個參數永遠是self,其餘跟普通函數一致
-
特殊變量
__name__
- 雙下劃線開始,雙下劃線結束
- 可以直接訪問
-
訪問權限
- 雙下劃線開頭
__init__ private
不可以訪問 - 單下劃線開頭
_name protected
可以訪問,但不建議訪問 - 其餘合法字符
id
公開訪問
- 雙下劃線開頭
-
繼承
支持多繼承
class Man(): def __init__(self,name,age): self.name=name self.age=age def person(self): print("我是人") class Student(Man): def __init__(self,name,age,clazz): self.clazz =clazz self.name=name self.age=age def whoIam(self): print(self.name) print(self.age) print(self.clazz) if __name__ == '__main__': print("程序入口") s = Student("老李",24,"假網工") s.whoIam() s.person()
-
獲取對象信息
- 判斷對象類型
type(obj)
返回類型isinstance(obj,str)
指定變量是否是給出的類型
- 獲取對象的所有屬性和方法
dir(str)
- 判斷對象類型
8.面向對象高級編程
-
__slots__
- 目的? 動態給類添加屬性或者方法.
在Java動態語言中是很容易的,就是類似調用setName("kg");
- 在python中呢?
__slots__ = ('qq','telNumber')
就相當於是類中存在兩個變量qq
telNumber
[我思考也實踐了一個問題就是:我若是qq
加雙下劃線會不會是private不可訪問的? 顯然結果不是.我想的是,既然__slots__
明確說目的是爲了動態添加值,再私有化就沒有意義了.]
- 目的? 動態給類添加屬性或者方法.
-
@property
- 保護數據不易被修改
- 這個註解就是個裝飾器
不記得裝飾器是啥了? 聯想動態添加功能啊,裝飾模式
-
多繼承
class Student(Person,Man): pass
Minln
就是像Java那種繼承一個類,實現多個接口類似,這是一種設計
-
定製類
__str__
不就是類似toString
方法嘛 [兩者的區別是__str__()
返回用戶看到的字符串,而__repr__()
返回程序開發者看到的字符串,也就是說,__repr__()
是爲調試服務的。]__iter__
返回迭代對象
-
枚舉類
Moth=Enum('one','tow')
class Moth(Enum)
-
元類
-
type()
-
判斷類型
type(name)
-
創建類
Hello = type('Hello', (object,), dict(hello=fn)) # 創建Hello class
1.class的名稱; 2.繼承的父類集合,注意Python支持多重繼承,如果只有一個父類,別忘了tuple的單元素寫法; 3.class的方法名稱與函數綁定,這裏我們把函數fn綁定到方法名hello上
看着優先香Java的反射[我瞎想的]
-
-
metaclass
[聽說是很難的魔法棒,可以實現ROM框架,聽聽就刺激,先跳過,老子也是菜鳥,暫看不懂]
-
9.錯誤處理
-
錯誤處理
try .. except .. finally..
-
調試
print()
自己俗稱的中間變量輸出- 斷言
assert true, error message
logging
內置日誌,輸出到文件日誌一般都會有日誌級別
pdb
單步執行- 好好利用
IDE
的功能
-
單元測試
-
導入測試模塊
unittest
-
編寫測試類,繼承導入的模塊
class TestAdd(unittest.TestCase): pass
-
然後理由
self
不斷測試自身 -
運行測試類
if __name__ == '__main__': unittest.main()
-
setUp()
和tearDown()
方法。這兩個方法會分別在每調用一個測試方法的前後分別被執行。
-
-
文檔測試
- 執行寫在註釋中的代碼? 什麼? 震驚菜鳥,我也是第一次聽說,怪我太菜 /掉頭流淚狂奔
- 使用
doctest
來測試
10. IO編程
-
文件讀取
-
open(path,mode)
打開文件 -
read()
一次讀完內容 -
close()
-
readlines()
每次讀取一行 -
自動關閉文件
with open('/path/to/file', 'r') as f: print(f.read())
-
open(path,'rb')
讀取二進制文件 -
open(path,mode,encoding='gbk')
字符編碼
-
-
寫文件
open(path,'w')
write(str)
- 也可以使用上述的
with
自動關閉
-
String IO / Bytes IO
-
在內存中讀寫
f=StringIO() #寫 f.write(str) #讀 f.getvalue()
-
區別就是
StringIO操作字符串
Bytes IO操作字節
-
-
序列化
pickle
模塊pickle.dumps(obj)
序列化任意對象爲字節流pickle.load(obj)
反序列化josn
序列化,調用的方法名一致,結果不一樣
11.進程和線程
- 多進程
- 在
os
模塊中fork()調用,子進程返回0,父進程返回子進程ID
fork()
只能在Linux上面使用,故Windows不行,mac也是基於Linux/Unix- 所以在Windows上怎麼使用多線程?
p = Process(target=fun,args=('primer',))
- 這句話有些坑啊
target
接受的是函數名而不是函數調用args
接受的是tuple
- 當tuple只有一個元素的時候,末尾需要加逗0號
,
p.start() p.join()
線程開始和等待
Pool
線程池 創建大量子線程時候使用p = Pool(4) p.apply_async(target,args)
Pool
默認大小是CPU核數,當出現線程數大於CPU核數的時候,就會出現競爭的現象- 子進程
subprocess
- 在
- 多線程
_thread
是低級模塊,threading
是高級模塊- Python解釋器由於設計時有GIL全局鎖,導致了多線程無法利用多核。多線程的併發在Python中就是一個美麗的夢
- 本地線程
- 使用自己的局部變量,避免過多使用全局變量,對全局變量加鎖使代碼臃腫
- 分佈式進程
- Process可以分佈到多臺機器上,而Thread最多隻能分佈到同一臺機器的多個CPU上。
12.常用內建模塊
datetime
時間處理datetime.now()
當前時間datetime.now().timestamp()
轉換成時間戳datetime.fromtimestamp(time)
把時間戳轉換
collections
集合namedtuple
自定義tuple
deque
隊列defaultdict
dict
key不存在的時候拋出異常,而這個不會ordereddict
有序的key,dict
是無需的chainmap
串聯dict
counter
計數器 返回還是一個tupel
base64
使用64個字符表示二進制base64.b64encode(str)
編碼base64.b64decode(str)
解碼- 注意
str
是字節流,需要使用b
作爲前綴- 不能直接轉換中文
struct
- 處理字節數據類型
hashlib
- 把任意數據轉換成固定長度的字符串,十六進制表示
- 常見的
MD5
sha1
hmac
- 驗證數據的有效性
token
對比
- 驗證數據的有效性
iteratools
- 遍歷工具
contextlib
1.urllib
xml
htmlparser
13.網絡編程
tcp
- 可靠
socket
使用- 一句話總結,比之前自己使用c++寫的做了很多封裝,只暴露幾個方法
udp
- 不可靠
- 無連接
- 直接調用
sendto
14.數據庫
-
sqlinte
這不是Android中使用的,巧了 -
mysql
- 驅動
pip install mysql-connector
- 驅動
-
SQL alchemy
二維表