Python高級編程
python中一切皆對象
—python中一切皆對象
內容
# 變量,函數,類,文件都是對象
[對象的三個特徵]
1.身份
2.類型
3.值
[對象的性質]
1.賦值給一個變量
2.可添加到內置類型中
3.可作爲參數傳遞
4.可作爲函數的返回值
對象的三個特徵
'''
以變量作爲例子
'''
a = 1
print(id(a)) # 身份
print(type(a)) # 類型
print(a) # 值
[輸出]:
>>140706136249376
>><class 'int'>
>>1
對象的性質
'''
以類作爲例子
'''
class Myclass:
def say(self):
print('hello')
# 1.類實例賦值給變量
myclass=Myclass()
a = list()
b = set()
c = dict()
d = set()
# 2.類實例放入內置數據類型
a.append(myclass) # 將類實例放入列表
b = (myclass,) # 將列實例放入元組
c.update({'class':myclass}) # 將類實例放入字典
d.add(myclass) # 將類實例放入集合
# 3.調用類實例中的方法
a[0].say() # 調用Myclass類中say()方法
b[0].say() # 調用Myclass類中say()方法
c['class'].say() # 調用Myclass類中say()方法
d.pop().say() # 調用Myclass類中say()方法
# 4.類實例作爲參數傳遞和作爲函數返回值
def myfunc(class_instance):
return class_instance # 將類實例作爲函數返回值
myfunc(myclass).say() # 調用Myclass類中say()方法
[輸出]:
>>hello
>>hello
>>hello
>>hello
>>hello
—type,object和class的關係
圖解
說明
type 實例化生成所有類包括自身
object 被所有類和對象繼承,但自身繼承爲空
type ->type
type ->int
type ->float
type ->complex
type ->bool
type ->dict
type ->set
type ->str
type ->list
type ->tuple
type ->bytes,bytearray
以上這些內置類型都可以看作是type實例化得到的對象
這些生成的對象又可以作爲類實例化出對象,最後值不能再實例化
—python中的常見內置類型
None(全局只生成一個)
數值(int,float,complex,bool)
序列類型(str,list,tuple,range,bytes,bytearray,memoryview)
散列類型(dict,set)
迭代類型
上下文管理
其他
魔法方法
—字符串相關
方法名
__str__ __repr__
實例
class Myclass:
def __init__(self,user_print,developer_print):
self.user_print = user_print
self.developer_print = developer_print
def __str__(self):
return self.user_print
def __repr__(self):
return self.developer_print
myclass = Myclass("面向用戶的打印模式","面向開發的打印模式")
print(str(myclass))
print(repr(myclass))
[輸出]:
>>面向用戶的打印模式
>>面向開發的打印模式
多線程
創建線程
1.使用Thread方法創建線程
import threading # 引入threading多線程模塊
def task(c1):
print("傳入的參數:",c1)
print(threading.current_thread()) # 獲取當前的線程名和線程ID
t = threading.Thread(target=task,args=(100,),name='子線程')
# target 參數傳入函數名
# args 參數傳入函數需要的參數
# name 參數傳入自定義的線程名
t.start() # 啓動線程
t.join() # 線程阻塞
print("主線程")
[輸出]:
>>傳入的參數: 100
>><Thread(子線程, started 13508)>
>>主線程
2.類的方式創建線程
import threading
class Mythread(threading.Thread):
def __init__(self,name,c1):
super().__init__() # 重寫Thread類中的init方法
self.name = name # name參數傳入自定義的線程名
self.c1 = c1 # c1爲傳入的自定義參數
def run(self):
print("傳入的參數:",self.c1)
print(threading.current_thread()) # 獲取當前的線程名和線程ID
t = Mythread(name='子線程',c1=100) # 傳入線程名和自定義參數
t.start() # 啓動線程
t.join() # 線程阻塞
print("主線程")
[輸出]:
>>傳入的參數: 100
>><Mythread(子線程, started 10736)>
>>主線程
多線程常用方法和屬性
Thread 類
實例化線程
對象=threading.Thread(name=自定義線程名,target=函數名,args=(參數,))
設置線程名
對象.setName(‘線程名’)
獲取線程名
對象.getName()
線程守護(主線程結束它的子線程就結束)
對象.setDaemon(True)
線程阻塞(主線程等子線程結束後才接着往下走)
對象.join()
判斷線程是否存活
對象.is_alive()
通過對象獲取線程ID
對象.ident
開啓線程
對象.start()
獲取所有線程詳細信息列表
threading.enumerate()
在線程執行過程中獲取所在線程名
threading.current_thread().name
在線程執行過程中中獲取所在線程ID
threading.current_thread().ident
在函數執行過程中獲取線程存活數量
threading.active_count()
1.守護線程
import threading
import time
def task():
time.sleep(5)
print("子線程")
t = threading.Thread(target=task) # 傳入要執行的函數名
t.setDaemon(True) # True :將線程設爲守護線程 False :不將線程設爲守護線程
t.start() # 啓動線程
print("主線程")
[t.setDaemon(True)時輸出]:
主線程
[t.setDaemon(False)時輸出]:
主線程
子線程
- 將線程設置爲
守護線程
模式,主線程結束
,子線程也會立即結束
- 若線程
不是守護線程模式
,主線程結束後
,還要所有子線程結束
之後,整個程序纔會結束
2.線程阻塞
import threading
import time
def task():
time.sleep(5)
print("子線程")
t = threading.Thread(target=task) # 傳入要執行的函數名
t.start() # 啓動線程
t.join() # 線程阻塞
print("主線程")
[有t.join()語句時輸出]:
子線程
主線程
[沒有t.join()語句時輸出]:
主線程
子線程
- 將線程設置爲
線程阻塞
模式,主線程要等子線程結束後纔會結束
,即子線程一定在主線程之前結束 - 若線程
不是線程阻塞模式
,主線程結束後
,還要等所有子線程結束
之後,整個程序纔會結束
線程同步
1.全局解釋器鎖GIL
import threading
sum = 0
def income():
global sum
for i in range(1000000):
sum += 1
def consume():
global sum
for i in range(1000000):
sum -= 1
# 定義線程
t_income = threading.Thread(target=income)
t_consume = threading.Thread(target=consume)
# 啓動線程
t_income.start()
t_consume.start()
# 線程阻塞
t_income.join()
t_consume.join()
# 打印變量計算結果
print("sum:",sum)
[輸出]:
sum: 566204
-
GIL鎖即python自帶的
全局解釋鎖
,每次只能一個線程獲得cpu的使用權
,爲了線程安全,也就是爲了解決多線程之間的數據完整性和狀態同步而加的鎖,因爲我們知道線程之間的數據
是共享的
。 -
由於python的全局GIL鎖機制,只要一個線程執行的
字節碼
或執行時間
到指定值,則會自動釋放GIL鎖
,此時多個線程可能同時對同一個變量同時操作,從而導致數據結果錯誤 -
運行結果本
應該輸出sum: 0
,實際輸出sum: 566204
,是因爲多個線程同時對同一個變量進行修改時,一個線程得到的計算值後,可能被另一個線程的計算的值給賦值
2.互斥鎖 Lock
import threading
lock = threading.Lock()
sum = 0
def income():
lock.acquire() # 加鎖
global sum
for i in range(1000000):
sum += 1
lock.release() # 釋放鎖
def consume():
lock.acquire() # 加鎖
global sum
for i in range(1000000):
sum -= 1
lock.release() # 釋放鎖
# 定義線程
t_income = threading.Thread(target=income)
t_consume = threading.Thread(target=consume)
# 啓動線程
t_income.start()
t_consume.start()
# 線程阻塞
t_income.join()
t_consume.join()
# 打印變量計算結果
print("sum:",sum)
[輸出]:
sum: 0
- 使用
lock.acquire()
,lock.release()
手動加鎖保護變量
後,使每次只有一個線程獲得cpu的使用權,即在同一時間,只有一個線程對變量進行修改
,所以數據並沒有發生錯誤
3.遞歸鎖 RLock
4.狀態鎖 Condition
#-*-coding:utf-8-*-
# condition實現的線程同步
import random
import threading
import time
con = threading.Condition()
apple = 0
class Producer(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self, name=name)
def run(self):
global apple
time.sleep(random.randrange(5))
with con:
print('Producer:',end='')
for i in range(1,11):
apple += 1
time.sleep(0.5)
print(f'\rProducer:生產中 剩餘蘋果:{apple}個',end='')
con.notify_all()
class Consumer(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self, name=name)
def run(self):
global apple
is_consumed = False
time.sleep(random.randrange(5))
with con:
if apple == 0 and is_consumed == False:
print('Consumer:等待蘋果生產中...')
con.wait()
for i in range(1,11):
apple -= 1
time.sleep(0.5)
print(f'\rConsumer:消費中 剩餘蘋果:{apple}個',end='')
p = Producer('Produce')
c = Consumer('Consume')
p.start()
c.start()
#-*-coding:utf-8-*-
# queue實現的線程同步
import threading
import time
from queue import Queue
q = Queue()
class Producer(threading.Thread):
def __init__(self,name):
super().__init__(name=name)
def run(self):
for i in range(10):
q.put(i)
print(f'{self.name} put {i}')
time.sleep(0.2)
class Consumer(threading.Thread):
def __init__(self,name):
super().__init__(name=name)
def run(self):
for i in range(10):
print(f'{self.name} get {q.get()}')
time.sleep(0.2)
p = Producer('Producer:')
c = Consumer('Consumer:')
p.start()
c.start()
線程通信
線程池
總結
同一時間,同一個CPU中的多線程運行 --> 併發
同一時間,多個CPU中的多線程運行 --> 並行
'''常用數據類型特殊情況下的值'''
string1 = '' # 0
string2 = ' ' # 1
list1 = [] # 0
list2 = [[]] # 1
tuple1 = () # 0
tuple2 = (()) # 0
set1 = set() # 0
dict1 = {} # 0
null = None # 0
if string1:
print('string1')
if string2:
print('string2')
if list1:
print('list1')
if list2:
print('list2')
if tuple1:
print('tuple1')
if tuple2:
print('tuple2')
if set1:
print('set1')
if dict1:
print('dict1')
if null:
print('None')
[輸出]:
string2
list2