【Python】Python高級編程

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