python 調試大法

来源:https://www.cnblogs.com/djdjdj123/archive/2019/12/07/12003426.html
-Advertisement-
Play Games

說在前面 我覺得沒有什麼錯誤是調試器無法解決的,如果沒有,那我再說一遍,如果有,那當我沒說 一、拋出異常 可以通過 raise 語句拋出異常,使程式在我們已經知道的缺陷處停下,併進入到 except 語句 raise句法: raise關鍵字 調用的異常函數名 ValueError (這個函數必須是異 ...


說在前面

我覺得沒有什麼錯誤是調試器無法解決的,如果沒有,那我再說一遍,如果有,那當我沒說

一、拋出異常

可以通過 raise 語句拋出異常,使程式在我們已經知道的缺陷處停下,併進入到 except 語句
 

raise句法:

raise關鍵字

調用的異常函數名 ValueError (這個函數必須是異常類或一個實例)

傳遞給 ValueError 的字元串,包含有用的出錯信息

>>> raise ValueError('This is a error message')
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    raise ValueError('This is a error message')
ValueError: This is a error message

然後使用 try...except 語句來對拋出的異常做處理

通常我們在函數本身中拋出異常,然後在調用該函數的地方使用 try...except 語句處理異常

#定義一個簡單的int類型的加法器
def calculator(num1,num2):
    if isintance(num1,int)and isintance(num2,int):
        raise Exception('Symbol must be a int type number.')
    return num1+num2
 
print('please enter two number:')
num1=input()
num2=input()
#在調用函數的地方使用try語句
try:
    print(calculator(num1,num2))
except Exception as err:
    print('發生了一個錯誤:'+str(err))
#另一種使用情況
try:
            print(key)
            return self[key]
        except KeyError:#如果在上面遇見了keyError
            raise AttributeError(r"'%s' don't have attribute '%s'"%#就拋出這個AttributeError類型的錯誤,順序別弄錯<br>(self.__class__.name,key))

註意上面的 as 語句取得 str ,如果不取也是可以的
  
運行示例:

RESTART: C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/boxPrint.py 
please enter two number:
s
發生了一個錯誤:name 'isintance' is not defined
>>>

二、取的反向跟蹤的字元串

當程式運行出現錯誤時,python會生成一些錯誤信息,這些錯誤信息被稱為“反向跟蹤”,它包含了出錯信息、導致該錯誤的代碼行號,和導致 該錯誤的函數調用 的 序列,這個序列被稱為調用棧。

只要拋出的異常沒有被處理,python就會顯示反向跟蹤

以下麵程式來展示我們對反向跟蹤的解讀

def spam():
    bacon()
def bacon():
    raise Exception('This is the error message')
 
spam()

這就是反向跟蹤:

Traceback (most recent call last):
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 6, in <module>
    spam()
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 2, in spam
    bacon()
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/errorExample.py", line 4, in bacon
    raise Exception('This is the error message')
Exception: This is the error message

我們應該從下往上閱讀方向跟蹤,通過反向跟蹤我們可以知道,這個錯誤發生在第5行,在bacon函數中;這次特定的bacon調用發生在第2行,spam函數中,而spam函數又是在第6行被調用的。這樣,在從多個位置調用函數的程式中,調用棧就能幫助你確定那次調用導致了錯誤。

調用 traceback.format_exc() 得到反向跟蹤的字元串形式

前面說過,如果拋出的異常沒有被處理,python才會顯示反向跟蹤。假如我們既想用except處理錯誤,又想要獲得出錯信息,就可以用這個函數,需要導入 traceback 模塊

例如,我們可以在程式出現錯誤時還能繼續運行,同時把錯誤信息記錄到日誌中。在程式結束後調試程式時,我們就根據日誌里記錄的信息去調試

>>> import traceback
>>> try:
    raise Exception('This is a error message')
except:
    errorFile=open('errorInfo.txt','w')
    errorFile.write(traceback.format_exc())  #使用tracback.format_exc()獲得反向跟蹤的字元串形式
    errorFile.close()
    print('The traceback info was written to errorInfo.txt')
 
     
112    #返回的是寫入的字元個數
The traceback info was written to errorInfo.txt
>>>

errorInfo.txt的內容:

Traceback (most recent call last):
  File "<pyshell#8>", line 2, in <module>
Exception: This is a error message

三、斷言assert語句

舉一個例子。你從學校畢業以後,很久都沒有找到工作,有一天你找了一個兼職:寶石大管家。小孩需要拿著與他們身份匹配的標識才能在別處領到寶石,這個標識在你這裡領取,你工作做得不錯,才做了五分鐘就被老闆任命為了區域經理,你覺你年紀輕輕就已經成為了二龍山雲霄飛車街區的揸Fit人、並且一手建立了二龍山游樂場寶石交易的游戲法則,覺得人生巔峰也不過如此,但是,沉迷於自我陶醉的你根本不知道,你將一個錯誤的標識給了一個小朋友,導致他沒有領到寶石。結果他叫他哥哥來打你了一頓。然後你老闆覺得你辜負了他對你的栽培,然後一氣之下把你開了,工資當然沒有結。最慘的是,你的衣服丟了,當時你為了用肚臍眼上的傷疤嚇唬他就把衣服脫了,結果他竟然也有同樣的傷疤,然後又被他打了一頓,然後,你的衣服就丟了。你知道這是你最寶貴的財富,因為這是當年女神贈你的禮物,你永遠也忘不了畢業那天,在你的寢室樓下,他輕輕的把袋子遞給了你,那天你們說了很多,他說感謝你四年來對他的照顧,但是他媽媽不讓他談戀愛,所以讓你再等等,你和他一直聊到晚上10點,只為了能當面向他說一句晚安,他很欣賞你的執著,離別之際對你許下了一個承諾:她說假如有一天這件衣服變成了綠色,他一定和你結婚。你知道,這下肯定沒有希望了。不僅失去了工作,你失去了愛情。你以為丟了衣服,就再也沒機會和他結婚了,萬萬沒想到,最後你們還是成為了夫妻。那天你回來以後就去了網吧,看見旁邊的人在寫代碼,他周圍散落的零食包裝代表著富有,這一切都被你看在眼裡,你知道你看到了希望,然後你就開始學編程了,由於你過人的天賦,沒出幾十年你就自己創辦了一家公司,和阿裡啪啪,中國移不動等大公司都建立了不同程度的合作關係,且業務往來十分密切,身邊的人都誇你有出息,只是在深夜的時候,你常常想起當年的那個他,你祈求老天再給你一次機會,終於有一天,你qq收到了他的信息,她說要來找你,你在城市最有檔次的地方約她吃飯,他一眼就認出來了你,你很開心,你覺得他一點都沒變,還是原來的樣子,他沒有問你衣服的事情,只是不停的向你道歉說是手誤當時才把你刪了,其實他這些年一直在找你,這次找到你了,就是要和你結婚,你十分激動,但是你強忍著激動的心情,勸他在考慮考慮,他搖了搖頭,從他眼神里流露出來的堅定瞬間擊垮了你,你再也控制不了自己了,你拿出了那次做兼職留下的寶石鑽戒,你一直把它帶在身上,就是等著機會到來,他想都沒想就一口答應了你的求婚。看到他對你如此信賴,你暗暗發誓一定要用全部的智商去愛她,晚上他非要枕著你的胳膊睡覺,你雖然覺的不舒服但還是讓他枕了一夜,你做了一個夢,夢見你們有了自己的孩子,那件衣服也被你找到了
衣服上還寫著“前方高能”幾個字,這是你睡得最舒服的一個晚上,你早早就醒來了,發現他也已經起來了,就在床邊上坐著,但令你不解的是,看到你睜開了眼睛,他的表情忽然很激動,sua的一聲就哭了,等他冷靜下來你才知道。原來,你應經昏迷了8年了,8年前,你去買早餐就再也沒有回來,你出了車禍,昏迷了8年,留下他和他腹中的孩子。他說這些年他從來沒有想過放棄你,他對你的愛幫助他剋服了許多困難。如今你醒了,他終於成功了,他高興的留下了激動的淚水,你也很開心。於是從此以後,你們一家三口過上了幸福的生活。

 

“斷言”在這個工作流程當中,就是用來檢查 你是否把牌發對了 的一個機制。為了避免這樣的情況,我們就添加“斷言”來檢查。

assert語句包含:

assert關鍵字、要判斷的條件、逗號、條件為False時顯示的字元串

>>> podBayDoorStatus='open'  #弔艙門的狀態
>>> assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
#這裡結果沒有錯
>>> podBayDoorStatus='other content'
>>> assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
#這裡結果出錯了
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    assert podBayDoorStatus=='open','podBayDoorStatus需要設置為open'
AssertionError: podBayDoorStatus需要設置為open
>>>

我們在程式中為某個變數賦值後,基於 這個變數是這個值 的假定,我們可能寫下了大量的代碼,即這些代碼依賴這個值,才能正確工作。說以我們添加一個斷言,確保假定的變數值是對的。

對於這種情況,我們使用assert讓程式立即崩潰就,以減少尋找缺陷的時間,我們不應用 try except 拋出異常,因為這是程式員的錯誤,而不是用戶的錯誤,對於那些可以恢復的錯誤(如文件沒有找到,用戶輸入了無效的數據)則應該用拋出異常來處理

  

在交通燈模擬中使用斷言

  

你在編寫一個交通信號燈的模擬程式。代表路口信號燈的數據結構是一個字典:

market_2nd={'ns':'green','ew':'red'}#ns南北向,ew東西向

你希望編寫一個函數 switchLight() ,他接受一個路口字典作為參數,並切換紅路燈

你可能認為 switchLight() 只要將每一種燈按順序切換到下一種顏色: ‘green‘ 值應該切換到 'yellow' , 'yellow' 應該切換到 'red' , 'red' 應該切換到 'green' 實現這個功能的代碼:

def switchLights(stoplight):
    for key in stoplight.keys():
        if stoplight[key]=='green':
            stoplight[key]='yellow'
        elif stoplight[key]=='yellow':
            stoplight[key]='red'
        elif stoplight[key]=='red':
            stoplight[key]='green'

這樣的運行結果:

>>>
 RESTART: C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py
{'ns': 'yellow', 'ew': 'green'}
{'ns': 'red', 'ew': 'yellow'}
{'ns': 'green', 'ew': 'red'}

你應該發現第一次的輸出是錯誤的,因為南北向和東西向總應該有一個是紅色的,如果不是,那麼就會出現汽車相撞,為了避免這樣的缺陷出現,你應該添加斷言

market_2nd={'ns':'green','ew':'red'}#ns南北向,ew東西向
 
def switchLights(stoplight):
    for key in stoplight.keys():
        if stoplight[key]=='green':
            stoplight[key]='yellow'
        elif stoplight[key]=='yellow':
            stoplight[key]='red'
        elif stoplight[key]=='red':
            stoplight[key]='green'
    assert 'red' in stoplight.values(),'交通燈都不是紅色的'+str(stoplight)        #在函數裡面添加斷言
switchLights(market_2nd)
print(market_2nd)
switchLights(market_2nd)
print(market_2nd)
switchLights(market_2nd)
print(market_2nd)

假如你沒有看出來這個代碼有問題,然後也沒有使用斷言,當你從運行結果發現問題時,或許要好多時間才能發現問題出現在 stwitchLight 函數中

禁用斷言

當我們開發測試的時候,我們可以使用斷言來幫助我們更早的發現錯誤,但是程式交付的時候應該是沒有缺陷的,這時就不在需要斷言了,我們可以在運行python時傳入-O選項來禁用斷言

需要從終端視窗運行程式時使用 >>>從終端運行程式<<<

在這裡插入圖片描述

四、日誌

記日誌是一種很好的方式,讓我們可以理解程式中發生的事,以及事情發生的順序。python中的 logging 模塊讓你能很容易的創建自定義的消息記錄。這些日誌消息列出了你指定的 任何變數 當時的值。缺失日誌消息表明有一部分代碼被跳過了,從未執行

4.1使用日誌模塊

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')

我們使用 logging.debug('string') 來列印日誌信息,這個 debug() 函數會調用 basicConfig ,所以我們第二行是指定列印信息的格式

python記錄一個時間的日誌時,他會創建一個 logRecord 對象,保存關於該事件的信息。

logging.debug() 調用不僅列印出了我們傳遞給他的信息,而且包含時間戳和一個單詞DEBUG

我們以下麵的程式為例,展示使用日誌來調試程式的大致過程

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
 
def factorial(n):
    logging.debug('Start of factorial(%s%%)' %(n))  #這裡的兩個%是什麼意思?或許是匹配basicConfig()里format里的後兩個參數?
    total=1
    for i in range(n+1):
        total*=i
        logging.debug('i is '+str(i)+', total is '+str(total))
    logging.debug('End of factorial(%s%%)'%(n))
    return total
 
print(factorial(5))
logging.debug('End of program')

運行結果:

RESTART: C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/facatorialLog.py
 2019-03-06 17:39:10,889 - DEBUG - Start of program
 2019-03-06 17:39:10,938 - DEBUG - Start of factorial(5%)
 2019-03-06 17:39:10,973 - DEBUG - i is 0, total is 0
 2019-03-06 17:39:11,001 - DEBUG - i is 1, total is 0
 2019-03-06 17:39:11,030 - DEBUG - i is 2, total is 0
 2019-03-06 17:39:11,058 - DEBUG - i is 3, total is 0
 2019-03-06 17:39:11,083 - DEBUG - i is 4, total is 0
 2019-03-06 17:39:11,108 - DEBUG - i is 5, total is 0
 2019-03-06 17:39:11,132 - DEBUG - End of factorial(5%)
0
 2019-03-06 17:39:11,187 - DEBUG - End of program

從裡面我們可以看到i是從0開始的,這就導致了total變數總是0,當然結果也是0,知道了這些,我們就可以對程式進行改動

import logging
logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
 
def factorial(n):
    logging.debug('Start of factorial(%s%%)' %(n))
    #或許是匹配basicConfig()里format里的後兩個參數?
    total=1
    for i in range(1,n+1):    #改動在這裡
       
---snip--

PS:遇到問題沒人解答?需要Python學習資料?可以加點擊下方鏈接自行獲取
note.youdao.com/noteshare?id=2dce86d0c2588ae7c0a88bee34324d76

4.2日誌級別

這個級別是全局的

“日誌級別”提供了一種方式,按重要性把日誌消息分為了下麵5類。這些級別隻是一種建議,在工作中,還是有我們自己來為日誌消息指定類型。就像上面,我們也可以不用 logging.debug() 而選用其他四種

python中的日誌級別
|級別(上面的是最小的) |日誌函數 |描述|
|--|--|--|
DEBUG| logging.debug() |最低級別。用於小細節。通常你只有在診斷問題時才需要
INFO| logging.info() |用於記錄程式中一般事件的信息,或者是用來確認工作正常
WARNING| logging.warning() |用於表示可能的問題,這些問題不會阻止程式的工作,但將來可能會
ERROR| logging.error() |用於記錄錯誤,它導致程式做某事失敗
CRITICAL |logging.critical() |最高級別。用於表示致命的錯誤,它導致或將要導致程式完全停止工作
  
他們顯示的格式並區別

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
>>> logging.debug('Some debugging details')
 2019-03-06 18:13:44,829 - DEBUG - Some debugging details
>>> logging.info('The logging is working')
 2019-03-06 18:13:59,984 - INFO - The logging is working
>>> logging.critical('The program is unable to recover!')
 2019-03-06 18:14:34,237 - CRITICAL - The program is unable to recover!
>>>

“日誌級別”的好處

“日誌級別”的好處在於,你可以改變想看到的 日誌消息 的優先順序。這通過 basicConfig() 函數的level關鍵字參數來指定, level='logging.DEBUG' 時會顯示所有的日誌級別消息, level='logging.ERROR' 時只會顯示級別大於等於ERROR的日誌消息

當我們開發了更多程式後,我們可能只會對錯誤感興趣,這種情況,就可以通過上面的level參數來設定我們想看到的級別

4.3禁用日誌

logging.disable() 函數接受一個日誌級別,它會禁止該級別和更低級別的所有日誌消息,註意這個參數的書寫正確

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')
>>> logging.critical('The program is unable to recover!')
 2019-03-06 18:14:34,237 - CRITICAL - The program is unable to recover!
>>> logging.disable(logging.CRITICAL)
>>> logging.critical('The program is unable to recover!')#由於上面的禁用這個就不顯示了
>>>

  
我們應該吧 logging.disable() 寫在程式中接近 import logging 代碼行的位置

4.4將日誌記錄到文件

logging.basicConfig() 函數接受 filename 關鍵字參數,日誌消息將被保存到 myProgramLog.txt 文件中,而不會在輸出在屏幕上

>>> import logging
>>>logging.basicConfig(filename='myProgramlog.txt',level=logging.DEBUG,format=' %(asctime)s - %(levelname)s - %(message)s')

4.5 basicConfig 的參數及 logging 模塊定義的格式字元串欄位

參數名稱 描述
filename 指定日誌輸出目標文件的文件名,指定該設置項後日誌信心就不會被輸出到控制台了
filemode 指定日誌文件的打開模式,預設為'a'。需要註意的是,該選項要在filename指定時才有效
format 指定日誌格式字元串,即指定日誌輸出時所包含的欄位信息以及它們的順序。logging模塊定義的格式欄位下麵會列出。
datefmt 指定日期/時間格式。需要註意的是,該選項要在format中包含時間欄位%(asctime)s時才有效
level 指定日誌器的日誌級別
stream 指定日誌輸出目標stream,如sys.stdout、sys.stderr以及網路stream。需要說明的是,stream和filename不能同時提供,否則會引發 ValueError異常
style Python 3.2中新添加的配置項。指定format格式字元串的風格,可取值為'%'、'{'和'$',預設為'%'
handlers Python 3.3中新添加的配置項。該選項如果被指定,它應該是一個創建了多個Handler的可迭代對象,這些handler將會被添加到root logger。需要說明的是:filename、stream和handlers這三個配置項只能有一個存在,不能同時出現2個或3個,否則會引發ValueError異常。

五、IDLE的調試器  

"調試器"是IDLE的一項功能,他可以讓你每次執行一行代碼,並讓你清除的查看當前時刻所有變數的值,對於你弄明白程式的問題很有幫助,通過在交互視窗中點擊 Debug>Debugger 來打開 調試控制視窗

5.1視窗上的信息

調試的時候不要把把斷點打到類似while語句上,因為while這樣的語句只執行一次,執行多次的是裡面包裹的代碼,所以單步跳出或者繼續的時候就相當於繼續執行到這個while語句,結束了要想一次讓單步跳出或者繼續達到一次執行一輪 while裡面代碼的效果,就把斷點打到while裡面

打開調試視窗後,只要你運行程式調試器就會在第一條指令執行前暫停執行,並顯示下麵的信息:

將要執行的代碼行;所有局部變數其其值得列表;所有全局變數及其值的列表

你會發現這裡面有多你沒有定義的變數,如 __ builtins__ 、 __ doc__ 、 __ file__ ,等等。它們是python在運行程式時,自動設置的變數。這些變數代表的含義我現在也不知道。我們可以只關註那些我們定義的變數。

程式將保持暫停,知道我們按下調試視窗的5個按鈕中的一個:GO、Step、Over、Out、Quit

Go

點擊Go按鈕將導致程式正常執行至終止,或到達一個“斷點”(斷點稍後會說)。換句話說,如果你完成了調試,希望程式正常繼續,就點擊Go按鈕

Step

Step按鈕將導致程式執行下一行代碼,然後再次暫停。如果下一行代碼是一個函數調用,調試器就會“步入”那個函數,調到該函數的第一行。

Over

Over按鈕將執行下一行代碼,與Step按鈕類似。但是如果下一行代碼是一個函數調用,Over按鈕將“跨越”該函數的代碼,調試器將在該函數返回後暫停。例如,下一行代碼是 print() 調用,而顯然我們不關註 print() 這個函數的代碼是怎樣的工作的,只希望傳遞給它的字元串列印出來,這時我們就可以使用Over按鈕

Out

Out按鈕將導致調試器全速執行代碼行,直到它從當前函數返回。如果你用Step按鈕進入了一個函數,現在想要讓這個函數全速執行,直到這個函數結束,那麼就可以使用Out按鈕,讓他從當前函數調用中“走出來”

Quit

Quit按鈕將馬上終止該程式,不會執行下麵的代碼,記住是終止程式,不是終止調試

5.2關閉調試器

和打開的操作一樣,從互動式視窗點擊 Debug>Debugger 就會關閉

5.3斷點

“斷點”可以設置在特定的代碼行上,當使用調試器開始調試程式時,按下GO按鈕並不會結束程式了,而是會到達斷點里暫停。

我們可以在編輯器里在要設定斷點的行右擊滑鼠,選擇 Set Breakpoint ,就在當前行設置了斷點,並且會以亮黃色顯示,這次我們打開調試器後,再運行程式後按GO按鈕就會在這一行停止,當我們要清除斷點時,需要在當前行右擊滑鼠,選擇 clear Breakpoint

當我們想要知道for迴圈中某一輪中的變數值,我們就可以在那一行設置斷點,而不是頻繁的點擊Over按鈕

import random
mark=0
for i in range(1,1000):
    s=random.randint(0,2)
    if s==1:
        mark+=1
#我們查看迴圈到i=500時的mark值就可以在下麵設置斷點   
    if i==500:
       print('halfway done')    #設置這裡為斷點,而不要在上一行里設置,因為他是個判斷,每一輪都會運行
print(mark)

斷言、異常、日誌和調試器,都是在程式中發現錯誤和預防缺陷的有用工具。用python的斷言,是檢查自己有沒有犯錯的好方式。如果必要的條件被我們搞錯了,他將會早早的給出警告。斷言所針對的錯誤,是程式不應該嘗試恢復的,而是應該讓程式立馬失敗

異常可以由 try...except 語句捕捉和處理。 logging 模塊是一種很好的方式,可以在運行時查看代碼的內部,他比使用 pring() 語句要好很多,因為他有不同的日誌級別,並能寫入日誌文件。

調試器讓你每次單步執行一行代碼。或者可以用正常的速度運行程式,並讓調試器停在你設置的斷點的代碼行上。利用調試器,你可以看到程式在運行期間,任何時候所有變數的值。
轉自:https://www.cnblogs.com/Gaoqiking/p/10490368.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 什麼是狀態模式? 指的是對象內部狀態發生改變對象行為也會發生變化。 狀態模式主要解決的是當控制一個對象狀態的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判斷邏輯簡化。 UML類圖 封裝變化 該模式中狀態是變化的,變化部分被做成了抽象類或介面,這讓做的目的就 ...
  • 基本思路 在每一次的排序中選出最小(或最大)的數,將其放在數組最前端,然後在後面的數中重覆此步驟,最終達到排序的目的. 演算法描述 將存於數組首位數與後面的數依次比較,將其中的較小的數放到數組放到數組首位 將除存於第二位的數視作首位,重覆第一步的操作 以此類推 代碼實現 這裡以從小到大排序為例 演算法分 ...
  • 冒泡排序(Bubble Sort) 一種電腦科學領域的較簡單的排序演算法。它重覆地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從從Z到A)錯誤就把他們交換過來。走訪元素的工作是重覆地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。 這個演算法的名字由來是因為越 ...
  • 進程,互斥鎖,生產者消費者,線程 一、僵屍進程與孤兒進程 代碼演示 二、子進程回收的兩種方式 代碼演示 三、進程守護 演示 四、進程間數據是隔離的 演示 五、進程互斥鎖 演示 六、隊列 演示 七、IPC(進程間通信) 演示 八、生產者與消費者 演示 子線程守護 十、線程互斥鎖 演示 ...
  • 編程只是 if ; 為了少寫重覆的代碼,有了迴圈 for/while; 但碰到很長的重覆代碼,可能用一個迴圈難以實現,所以出現了面向對象的思想: 類:就是你的迴圈主體 實例:就是對你的迴圈的一次調用 概念: 1. 在Python中,首字母大寫的,名稱指的是類。這個類定義中的括弧是空的 2. 類包括 ...
  • 本人第一次寫博客,之前都是用自己的日記本。 但是苦於不能時時帶著電腦,實在是不方便。。。。所以決定用手機。正好就是朋友也都在用博客,所以,,真香。。。 廢話不多說,點到為止。。 原理:比較兩個相鄰的元素,將值大的元素交換至右端。 冒泡排序的優點:每進行一趟排序,就會少比較一次,因為每進行一趟排序都會 ...
  • 大家好,歡迎來到樂位元組小樂的Java技術分享園地。這次給大家分享的是Tomcat 一. 什麼是 Tomcat Tomcat 是一個符合 JavaEE WEB 標準的最小的 WEB 容器,所有的 JSP 程式一定要有 WEB 容器的支持才能運行,而且在給定的 WEB 容器裡面都會支持事務處理操作。 T ...
  • 利用JavaFX設計一個井字棋游戲,其中包括了能夠與玩家對戰的AI。AI的實現相比五子棋來說要簡單得多,可以保證AI在後手情況下絕對不會輸,具體實現如下: /* * To change this license header, choose License Headers in Project Pr ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...