學寫PEP,參与Python語言的設計

如果你為Python寫了一篇PEP,這篇PEP成功的被Python指導委員會接受了,那麼以後你在吹牛皮的時候你就可以說我主導了Python語言某個特性的設計工作.

                              					-- 跬蟒

我就問你主導Python語言特性設計牛不牛皮,今天我就寫一篇文章告訴大家如何去為Python設計一篇PEP,並且整個PEP從一個想法到Python語言去實現它的這一套流程:

假設你已經是一個Python高手了,在使用Python給過程中你覺得Python語言在某方面還不夠完善,你有一個不錯的想法可以去改善Python這方面的不足,你打算把你的想法加入到Python語言裏面,所以你打算寫一篇PEP,為Python的發展獻言建策,那首先需要做什麼呢?

  1. 首先你要確保你的想法是個新的想法是個比較大的想法,是一個由必要去建立一個PEP的想法,也許你發現了Python的一些小問題,但是這些小問題如果提交一個小補丁就可以解決了,那就沒必要提PEP
  2. 當你確定自己的想法很牛B之後,你也不是馬上就要提PEP,你首先要做的事情是引發社區的討論,看看其他人怎麼看,然後自己去實現一下這個想法看是否是可行的,並且發帖到 python-list@python.org mailing list或者到 python-ideas@python.org mailing list 進行進一步的確定,看看大家對你的想法是否認同,如果你能讓大多數人都認同,那你就有戲,在你發帖之前最好準備一份高質量的PEP草稿,這樣的話才會更容易的被接受
  3. 總之就是先討論,得到大家的認可,避免後期不必要的撕逼,然受自己也要做好準備,最好有個簡單的實現,然後還有個高質量的PEP草稿

寫PEP你不得不知道的幾個Python社區角色

PEP champion : PEP擁護者 也就是PEP的發起人,也就是跟大家說我有個非常XXX的想法的人

PEP author: PEP作者 就是寫PEP的人,PEP從一個想法到一篇PEP草稿,再到一篇擁有官方PEP編號的PEP文檔,到後面PEP審核通過,PEP複審出現改動,PEP被接受這個過程中維護PEP文檔的人就是PEP的作者,大部分PEP作者就是PEP擁護者本人

PEP reviewer: 這個角色不是單指某一個人,一個PEP從想法到實現需要經過很多此review, 每一次參与review的人都可以被稱作 PEP reviewer

PEP editor: PEP編輯者 就是對PEP進行初步審核的人,審核通過的PEP進入到github上面的PEP倉庫的master分支,進行下一輪的評審

Python Core Developers: Python核心開發人員 就是開發Cpython解釋器的那群人,都是大佬,都是大佬

Python’s Steering Council: Python指導委員會 大佬中的大佬,從Python核心開發人員中選擇出來的指導Python語言開發工作的一群人,對於PEP是否接受有着最終發言權

PEP的工作流程是這樣的:

  1. PEP champion 先有一個高質量的idear(經過討論分析和理性驗證)
  2. 你去github上面去fork PEP倉庫
  3. 在倉庫中創建一個 pep-9999.rst的文件去把你的PEP草稿粘貼進去
  4. 確定你的PEP的類型,PEP的狀態設為草稿,PEP頭部按照模板寫一波
  5. 把你的pep-9999.rst push到PEP倉庫
  6. 然後PEP editors 會去審核你的提交
  7. 如果審核通過,這個本來是草稿的PEP會拿到一個正規的PEP編號,如果沒有審核通過那PEP editors 會打回去讓 PEP author 去修改
  8. 如果PEP審核通過拿到了PEP編號 PEP editor 會把這個新提交的PEP合併到PEP倉庫的 master 分支
  9. 如果你的PEP的類型是Standards Track類,那你提交的PEP還會被發送給Python-dev list 成員進行再次review, 確保你的新PEP沒有坑
  10. 有些聽起很不錯的PEP在實現的時候其實是非常蛋疼的,沒做的時候想的挺好,真正去實現的時候才知道是否靠譜,最好的情況時你在提交PEP的時候你手裡就已經有一個這個PEP的原型實現了,所以如果你的PEP類型是Standards Track類型那你就不僅需要準備設計文檔,你還需要準備一個參考實現,以此來避免一些不切實際的想法

當然凡事都有例外,有些Python的核心開發者是不會走這個流程的因為他們本身的權限比較大,他們有直接push內容到PEP倉庫的權限,所以有時候他們會直接給自己的PEP分配一個PEP編號push進入PEP倉庫的master分支,當然這並不意味着這個PEP就被接受了,他只是繞過了PEP editor的審批而已,PEP被接受和PEP通過審批是完全兩碼事兒,只有通過Python指導委員會的同意,PEP計劃實現,才能叫做PEP被接受.

如果我寫的PEP無法審核通過被拒怎麼辦?

PEP被拒絕是很正常的事情,不要灰心,只要能夠堅信自己的PEP是真正對Python有用的東西,真正好的idear,修改一下繼續上就行了,但是被拒肯定是有原因的,最主要的原因就是下面幾條:

  1. 該特性已經存在了
  2. 技術上不合理
  3. Python不需要去實現這樣的特性,也就是說偽需求
  4. 無法進行後向兼容
  5. 不符合Python的設計哲學(Python設計哲學可以在Python交互解釋器中輸入import this獲取)其實在PEP的審批階段可以拿着自己的PEP idear去諮詢Python指導委員會,因為PEP最終會不會被接受其實是由Python指導委員會所決定的,所以如果真的想要自己的PEP被接受,做好提前的溝通還是非常有必要的
  6. 奧對了還有一個蛋疼的要求,就是你的PEP草稿必須帶着至少一名Python核心開發人員一起寫,或者有一個Python核心開發人員指導你寫,或者有一個經過Python指導委員會批準的非Python核心開發人員一起寫,反正就是需要有一個能夠被Python指導委員會所信任的人參與了你的PEP設計,如果沒能滿足這個條件 PEP editor有權直接駁回你的PEP草稿

PEP的複審和決定機制

一篇PEP是否最終被接受並且決定去實現是需要經過層層複審的,反正要經過很麻煩了一個流程,下面有個Python官方畫的簡單流程圖:

但是實際情況比較複雜,有時候不會按照這個流程圖來,但是這個流程圖給人們提供了一個比較清晰的PEP工作流的概覽

PEP格式和模板

這年頭寫啥文檔沒個模板真不行,PEP也是文檔,所以模板搞起來:

  1. 首先PEP是UTF-8編碼的rst文件,首先你需要去指導rst文件的格式,如果rst的語法格式你已經會了,那你就可以閱讀官方的PEP 12--Sample reStructuredText PEP Template,沒錯PEP12是介紹rst格式PEP模板的PEP(有點繞),為什麼要用rst格式?官方給出的解釋是 容易轉成html進行在線發布和閱讀
  2. 每一篇PEP必須有一個標準的PEP頭部,如下所示,帶* 號是可寫可不寫的,不帶* 號的是必須要寫的,記住寫PEP頭的時候,頭的各個字段的順序,必須按照下圖的內容去寫,先後順序不能亂

寫道這裏就講的差不多了,但是其實PEP的書寫還有很多的內容比如:

  1. 如何判斷PEP是不是一個成功的PEP
  2. PEP提交之後發現內容有bug怎麼解決
  3. PEP所有權以及所有權轉移問題
  4. PEP editor的詳細職責和工作流
  5. 等等問題,我就不寫了,寫不動了…..

想寫PEP的可以先根據上面流程走一波,
然後等到遇到問題的時候再去查資料吧.

如果感覺本篇內容還不錯,微信的朋友請點個在看,其他平台的朋友可以(近距離)掃描下方的二維碼關注我的公眾號 早睡蟒更多優質原創無廣告內容等你來看.

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

WebGPU+光線追蹤Ray Tracing 開發三個月總結

大家好~這三個月以來,我一直在學習和實現“基於WebGPU的混合光線追蹤實時渲染”的技術,使用了Ray Tracing管線(如.rgen、.rmiss等着色器)。
現在與大家分享和介紹我目前的學習成果,希望對大家有所幫助!謝謝!

通過國外的開源項目,可在WebGPU中使用Ray Tracing管線

這三個月我對Ray Tracing的研究有了質的突破,主要歸功於我發現的WebGPU Node開源項目!
該作者首先在dawn-ray-tracing開源項目中對“dawn項目:Chrome對WebGPU的實現”進行了擴展,加入了光追的API;
然後在WebGPU Node開源項目中,底層封裝了Vulkan SDK,上層使用了dawn-ray-tracing項目,提供了WebGPU API,實現了在Nodejs環境中使用WebGPU API和Ray Tracing管線來實現硬件加速的光線追蹤(電腦需要使用nvdia的RTX顯卡)!

相關介紹參見:
Real-Time Ray-Tracing in WebGPU

搭建運行環境

有兩種方法來搭建運行環境:
1、給Chrome瀏覽器打補丁,使其與下載DXR驅動(DirectX Raytracing)關聯,從而在該瀏覽器中運行
詳見該作者最近寫的開源項目:chromium-ray-tracing
(我沒有測試過,不知道是否能使用)

2、編譯dawn-ray-tracing和WebGPU Node項目,從而在Nodejs環境中運行
我使用的是這個方法(不過我使用的WebGPU Node項目是今年3月份時的代碼,最新的代碼我還沒有編譯成功)。

我的操作系統是win7,顯卡是RTX 2060s,vulkan sdk是1.1.126.0版本

/* 最新代碼我還沒有編譯成功哈哈!請先不要進行下面的編譯操作!

編譯的步驟為(需要使用VPN翻牆):

# 編譯dawn-ray-tracing項目

## Clone the repo as "dawn-ray-tracing"
git clone https://github.com/maierfelix/dawn-ray-tracing

cd dawn-ray-tracing

## Bootstrap the gclient configuration
cp scripts/standalone.gclient .gclient

## Fetch external dependencies and toolchains with gclient
gclient sync


set DEPOT_TOOLS_WIN_TOOLCHAIN=0

npm install --global --production windows-build-tools

gn gen out/Shared --ide=vs --target_cpu="x64" --args="is_component_build=true is_debug=false is_clang=false"

ninja -C out/Shared


# 編譯webgpu node項目

npm install webgpu

在webgpu node的根目錄中創建名為“PATH_TO_DAWN”的文件,在其中指定dawn-ray-tracing項目的絕對路徑,如:
D:/Github/dawn-ray-tracing

在webgpu node的根目錄中執行:
npm run all --dawnversion=0.0.1
(
這裏要注意的是,需要先安裝Vulkan SDK和python;

可以通過“npm config set python C:\depot_tools\python.bat”來設置python路徑,或者指定python路徑:
npm run all --dawnversion=0.0.1 --python="C:\Users\Administrator\Downloads\depot_tools\bootstrap-3_8_0_chromium_8_bin\python\bin\python.exe"
)


# 在nodejs中運行ray tracing示例,驗證是否成功

進入webgpu node的根目錄

cd examples & cd ..
node --experimental-modules examples/ray-tracing/index.mjs

*/

應用場景

考慮到WebGPU還沒有正式發布,並且可能在三年內瀏覽器都不會支持Ray Tracing管線,所以我把渲染放到雲端,這樣就可以在雲端自行搭建環境(如使用WebGPU Node開源項目),然後通過網絡傳輸將渲染結果傳輸到客戶端,從而在客戶端瀏覽器不支持的情況下仍能显示光追渲染的畫面。

因此,我的應用場景為:
1、雲渲染
2、雲遊戲

這兩個應用場景有不同的需求:
“雲渲染”屬於離線渲染,我們關心的是:

  • 畫質要好
  • 渲染時間可以長點

因此:

  • 每幀可採樣多次,即n spp(n >= 30)
  • 支持多種渲染效果,如“焦射”(causicts)等
  • 全局光照可使用n次bounce(n >= 2)

“雲遊戲”屬於實時渲染,我們關心的是:

  • 畫質可以差點
  • 渲染時間要短(每幀30ms以內)

因此:

  • 每幀只採樣一次,即1 spp
  • 全局光照只使用一次或兩次bounce
  • 對“焦射”(causicts)等場景用性能好的方案達到接近的渲染效果,通過犧牲畫質來減少渲染時間

介紹我目前的實現方案

主要技術框架是“實時混合光線追蹤”,主要包含下面的pass:
1、gbuffer pass
創建gbuffer
2、ray tracing pass
直接從gbuffer中獲取world position、diffuse等數據,用來計算直接光照,從而減少了每個像素髮射的光線數量;
每個像素髮射1個shadow ray,用來計算直接光照的陰影;
如果只用1個bounce來計算全局光照的話,每個像素髮射1個indirect ray+1個shadow ray,用來計算間接光照。
3、denoise pass
基於BMFR算法來實現降噪,具體可參考本文後面的“實現降噪Denoise”部分。
4、taa pass
使用taa來抗鋸齒

相關代碼可見我的開源項目:
WebGPU-RTX

介紹我學習的整個流程,分享相關資料

了解光線追蹤的相關領域

我通過下面的文章進行了初步的了解:
一篇光線追蹤的入門
光線追蹤與實時渲染的未來
實時光線追蹤技術:業界發展近況與未來挑戰
Introduction to NVIDIA RTX and DirectX Ray Tracing
如何評價微軟的 DXR(DirectX Raytracing)?

實現第一個光追的Demo

通過學習下面的資料:
Ray Tracing in One Weekend
Ray Tracing: The Next Week
Ray Tracing in One Weekend和Ray Tracing: The Next Week的詳解
基於OpenGL的GPU光線追蹤

我參考資料中的代碼,用WebGL 2實現一個Demo:

該場景的紅圈中是一個球,附近有一個球形光源和一個矩形光源

因為沒有進行降噪,所以噪點太多了哈哈!

相關代碼可見我的開源項目:
Wonder-RayTrace

學習和實現Ray Tracing管線

通過學習NVIDIA Vulkan Ray Tracing Tutorial教程,我用 js語言+WebGPU Node開源項目 基於Ray Tracing管線依次實現了陰影、反射等基礎渲染效果。

該教程使用了VK_KHR_ray_tracing擴展,而WebGPU Node開源項目也使用了該擴展(Vulkan SDK),因此該教程的shader代碼幾乎可以直接用到該開源項目中。

教程代碼

用Reason重寫

我用Reason語言重寫了示例代碼,提煉了一個基礎架構。

學習GBuffer+Ray Tracing混合管線

因為我希望優先減少渲染時間,所以我要通過混合管線來進行實時渲染。

我通過A Gentle Introduction To DirectX Raytracing教程來學習和實現。

教程代碼下載

我學習了該教程的第一篇到第11篇,分別實現了創建GBuffer、使用Lambertian材質渲染、多光源的陰影等內容。

實現降噪Denoise

教程的第9篇通過每個像素對每個光源發射一個shadow ray,最後累加並計算平均值,實現了多光源的陰影。

教程的第11篇對第9篇進行了改進:為了減少每個像素髮射的shadow ray的數量,每個像素只隨機向一個光源發射一個shadow ray。
這樣會導致噪點,如下圖所示:

我們可以通過累計採樣數來不斷逼近無噪點的圖片(如該教程的第6篇一樣),但這樣需要經過長時間后才會收斂,所以只適合“雲渲染”這種離線渲染的應用場景。

累加一定幀數后,結果如下圖所示:

實現taa

降噪算法通常需要先實現“幀間的數據復用”,而TAA抗鋸齒也需要實現“幀間數據復用”的技術;而且降噪算法會使用TAA作為最後一個pass來抗鋸齒。所以我決定先實現taa,將其作為實現降噪算法的鋪墊。

我參考了下面的資料來實現taa:
DX12渲染管線(2) – 時間性抗鋸齒(TAA)、 相關代碼
Unity Temporal AA的改進與提高、 相關代碼
unit Temporal Anti-Aliasing

實現BMFR降噪算法

為了能應用於“雲遊戲”這種實時渲染的應用場景,我們需要快速降噪。因此我實現了BMFR算法來降噪。

降噪前場景:

降噪后場景:

我參考了下面的資料:
BLOCKWISE MULTI-ORDER FEATURE REGRESSION FOR REAL-TIME PATH TRACING RECONSTRUCTION
參考代碼

學習蒙特卡羅積分(monte carlo)的理論

教程的第11篇隨機向一個光源發射一個shadow ray,這其實已經使用了蒙特卡羅積分的理論。

我們可以通過下面的資料深入學習該理論,了解概率密度函數(pdf)、重要性採樣等相關概念,為我們後面實現全局光照打下理論基礎:
【RAY TRACING THE REST OF YOUR LIFE 超詳解】 光線追蹤 3-1 蒙特卡羅 (一) 到 【RAY TRACING THE REST OF YOUR LIFE 超詳解】 光線追蹤 3-7 混合概率密
光線追蹤器Ray Tracer:進階篇

實現全局光照

通過學習教程的第12篇,我實現了one bounce的全局光照。

更多參考資料:
Global Illumination and Path Tracing
Global Illumination and Monte Carlo

這裏我遇到的問題主要是處理indirect specular noise:噪點不穩定,導致降噪后不穩定(高光周圍有明顯波動)。
我首先以為是pdf寫錯了,結果修改了pdf后還是沒有改進;
然後希望通過clamp等方法移除這些高光的fireflies噪點,結果影響到了畫質;
最後採用了“採樣indirect specular/diffuse多次”來穩定噪點。這適用於“雲渲染”的離線渲染,但不適用於“雲遊戲”的實時渲染。

基於GGX模型,實現disney BRDF

通過學習教程的第14篇,我引入了pbr材質,實現了GGX模型,加入了多bounce的全局光照。

我對教程代碼進行了改進:
在.rgen着色器中使用for循環而不是遞歸來實現的多bounce;
實現了disney BRDF,在pbr材質中有diffuse、roughness、metallic、specular這幾個參數。

更多參考資料:
基於物理着色(二)- Microfacet材質和多層材質
基於物理着色(三)- Disney和UE4的實現
基於物理的渲染(PBR)白皮書 | 迪士尼原則的BRDF與BSDF相關總結
WebGPU-Path-Tracer 實現了disney BRDF

目前的渲染效果

我目前的實現需要改進的地方

在Ray Tracing pass中支持紋理

使用bindless texture或者virtual texture來實現

擴展disney BRDF,實現BSDF,支持透明、折射效果

增加后處理

如gamma矯正等

在雲端環境下多線程渲染

雲端天然具有并行的優勢,因此可將渲染任務分配到多個顯卡/服務器中執行。

改進降噪效果

BMFR對高光specular處理得不好。
為了應用在“雲渲染”中,需要提高畫質。因此可考慮:

  • 改進BMFR對specular的處理
    BMFR論文中已有相關的討論
  • 使用專門對多個spp採樣進行降噪的降噪器來替代BMFR
    因為BMFR主要是針對1 spp採樣,所以需要使用針對蒙托卡羅積分路徑追蹤的降噪器來替代

改進indirect specular/diffuse noise

現在我通過增加spp來增加噪點的穩定性,這在“雲遊戲”中行不通,因為只能有1 spp。因此可考慮:

  • 使用blue noise
    可參考: http://psgraphics.blogspot.com/2018/10/flavors-of-sampling-in-ray-tracing.html
    https://hal.archives-ouvertes.fr/hal-02158423/file/blueNoiseTemporal2019_slides.pdf
    https://belcour.github.io/blog/research/2019/06/18/animation-bluenoise.html
    https://zhuanlan.zhihu.com/p/90017623
  • 對GGX模型使用VNDF來代替NDF採樣
  • 對多bounce的indirect specular noise進行優化
    可能的解決方案:
    使用reflection denoise filter;
    adaptive multiple bounce;
  • 使用photon mapping來降低噪點

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

Java筆試面試總結—try、catch、finally語句中有return 的各類情況

前言

之前在刷筆試題和面試的時候經常會遇到或者被問到 try-catch-finally 語法塊的執行順序等問題,今天就抽空整理了一下這個知識點,然後記錄下來。

正文

本篇文章主要是通過舉例的方式來闡述各種情況,我這裏根據 try-catch-finally 語法塊分為兩種大情況討論:try-catch 語法塊和 try-catch-finally 語句塊,然後再在每種情況里再去具體討論。

一、try-catch 語句塊

我們可以看看下面程序:

public static void main(String[] args) {

    System.out.println(handleException0());
  }

  /**
   * try,catch都有return
   * @return
   */
  private static String handleException0() {
    try{
      System.out.println("try開始");
      String s = null;
      int length = s.charAt(0);
      System.out.println("try結束");
      return "try塊的返回值";
    }catch (Exception e){
      System.out.println("捕獲到了異常");
      return "catch的返回值";
    }
  }

執行結果

try開始
捕獲到了異常
catch的返回值

分析:程序首先執行 try 塊裏面的代碼,try 塊裏面發現有異常,try 塊後面的代碼不會執行(自然也不會return),然後進入匹配異常的那個 catch 塊,然後進入 catch 塊裏面將代碼執行完畢,當執行到 catch 裏面的return 語句的時候,程序中止,然後將此 return 的最終結果返回回去。

二、try-catch-finally 語句塊

這種語法塊我分為了 4 種情況討論,下面進行一一列舉。

1、第一種情況,try 塊裏面有 return 的情況,並且捕獲到異常

例1:

public static void main(String[] args) {
  String result = handleException1();
  System.out.println(result);
}
private static String handleException1() {
  try{
    System.out.println("try開始");
    String str = null;
    int length = str.length();
    System.out.println("try結束");
  }catch (Exception e){
    System.out.println("捕獲到了異常");
  }finally {
    System.out.println("finally塊執行完畢了");
  }
  return "最終的結果";
}

例1執行的結果如下

try開始
捕獲到了異常
finally塊執行完畢了
最終的結果

例2:

public static void main(String[] args) {
  String result = handleException2();
  System.out.println(result);
}
private static String handleException2() {
  try{
    System.out.println("try開始");
    String str = null;
    int length = str.length();
    System.out.println("try結束");
    return "try塊的返回值";
  }catch (Exception e){
    System.out.println("捕獲到了異常");
  }finally {
    System.out.println("finally塊執行完畢了");
  }
  return "最終的結果";
}

例2的執行結果如下

try開始
捕獲到了異常
finally塊執行完畢了
最終的結果

分析:首先 例1 和 例2 的結果是很顯然的,當遇到異常的時候,直接進入匹配到相對應的 catch 塊,然後繼續執行 finallly 語句塊,最後將 return 結果返回回去。

第二種情況:try塊裏面有return的情況,但是不會捕獲到異常

例3:

思考:下面代碼try語句塊中有return語句,那麼是否執行完try語句塊就直接return退出方法了呢?

public static void main(String[] args) {
  String result = handleException3();
  System.out.println(result);
}
private static String handleException3() {
  try{
  	System.out.println("");
    return "try塊的返回值";
  }catch (Exception e){
    System.out.println("捕獲到了異常");
  }finally {
    System.out.println("finally塊執行完畢了");
  }
  return "最終的結果";
}

例3的執行結果如下

finally塊執行完畢了
try塊的返回值

分析:例3的結果其實我們可以通過打斷點的方式去看看程序的具體執行流程,通過打斷點我們可以發現,代碼先執行 try塊 里的代碼,當執行到 return 語句的時候,handleException3方法並沒有立刻結束,而是繼續執行finally塊里的代碼,finally塊里的代碼執行完后,緊接着回到 try 塊的 return 語句,再把最終結果返回回去, handleException 方法執行完畢。

第三種情況:try塊和finally裏面都有return的情況

例4:

public static void main(String[] args) {
    System.out.println(handleException4());
  }

  /**
   * 情況3:try和finally中均有return
   * @return
   */
  private static String handleException4() {
    try{
      System.out.println("");
      return "try塊的返回值";
    }catch (Exception e){
      System.out.println("捕獲到了異常");
    }finally {
      System.out.println("finally塊執行完畢了");
      return "finally的返回值";
    }
  //  return "最終的結果";//不能再有返回值
  }

例4的執行結果

finally塊執行完畢了
finally的返回值

分析:需要注意的是,當 try 塊和 finally 裏面都有 return 的時候,在 try/catch/finally 語法塊之外不允許再有return 關鍵字。我們還是通過在程序中打斷點的方式來看看代碼的具體執行流程。代碼首先執行 try 塊 里的代碼,當執行到 return 語句的時候,handleException4 方法並沒有立刻結束,而是繼續執行 finally 塊里的代碼,當發現 finally 塊里有 return 的時候,直接將 finally 里的返回值(也就是最終結果)返回回去, handleException4 方法執行完畢。

第四種情況:try塊,catch塊,finally塊都有return

例5:

public static void main(String[] args) {
    System.out.println(handleException5());
  }

  /**
   * 情況4:try,catch,finally都有return
   * @return
   */
  private static String handleException5() {
    try{
      System.out.println("try開始");
      int[] array = {1, 2, 3};
      int i = array[10];
      System.out.println("try結束");
      return "try塊的返回值";
    }catch (Exception e){
      e.printStackTrace();//這行代碼其實就是打印輸出異常的具體信息
      System.out.println("捕獲到了異常");
      return "catch的返回值";
    }finally {
      System.out.println("finally塊執行完畢了");
      return "finally的返回值";
    }
//    return "最終的結果";
  }

例5的執行結果

try開始
捕獲到了異常
finally塊執行完畢了
finally的返回值
java.lang.ArrayIndexOutOfBoundsException: 10
at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.handleException5(TryCatchFinally.java:25)
at com.example.javabasic.javabasic.ExceptionAndError.TryCatchFinally.main(TryCatchFinally.java:14)

分析:程序首先執行try塊裏面的代碼,try塊裏面發現有異常,try塊後面的代碼不會執行(自然也不會return),然後進入匹配異常的那個catch塊,然後進入catch塊裏面將代碼執行完畢,當執行到catch裏面的return語句的時候,程序不會馬上終止,而是繼續執行finally塊的代碼,最後執行finally裏面的return,然後將此return的最終結果返回回去。

總結

其實,我們通過以上例子我們可以發現,不管return關鍵字在哪,finally一定會執行完畢。理論上來說try、catch、finally塊中都允許書寫return關鍵字,但是執行優先級較低的塊中的return關鍵字定義的返回值將覆蓋執行優先級較高的塊中return關鍵字定義的返回值。也就是說finally塊中定義的返回值將會覆蓋catch塊、try塊中定義的返回值;catch塊中定義的返回值將會覆蓋try塊中定義的返回值。
再換句話說如果在finally塊中通過return關鍵字定義了返回值,那麼之前所有通過return關鍵字定義的返回值都將失效——因為finally塊中的代碼一定是會執行的。

公眾號:良許Linux

有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

C++ Primer Plus(四)

完整閱讀C++ Primer Plus 

  系統重新學習C++語言部分,記錄重要但易被忽略的,關鍵但易被遺忘的。

 

友元、異常和其他

  1、拋出異常類時,雖然catch的是一個引用,但是也會產生一次拷貝,因為當拋出異常的函數在棧解退的過程中會會調用異常類的析構函數,異常類將不復存在。

  2、如果有一個異常類層次結構,應該這樣排列catch塊:將捕獲位於層次結構最下面的異常類的catch語句放在最前面,將捕獲基類異常的catch語句放在最後面。拋出異常的順序要與catch塊相反。

  3、在catch語句中使用基類對象時,將捕獲所有的派生類對象,但派生類特性將被剝去,因此將使用虛方法的基類版本。

  4、 將dynamic_cast用於引用時,由於沒有與空指針對應的引用值,因此無法使用特殊的引用值來表示失敗,當請求不正確時,將引發bad_cast的異常。

  5、reinterpret_cast運算符並不支持所有的類型轉換,例如,可以將指針類型轉換為足以存儲指針的整數,但不能將指針轉換為更小的整型或浮點型。另一個限制是,不能將函數指針和數據指針互相轉換。

 

string類和標準模板庫

  6、使用new分配內存時,可以使用auto_ptrunique_ptrshared_ptr、但只有unique_ptr有使用new[]和delete[]的版本。

  7、在unique_ptr為右值時,可以將其賦值給shared_ptr,模板shared_ptr包含一個顯式構造函數,可以用於將右值unique_ptr轉換為shared_ptr。

  8、對於所有內置的算術運算符、關係運算符和邏輯運算符,STL都提供了等價的函數符(仿函數)。

  9、valarray模板類重載了許多運算符,可以直接參与大多數數值運算;slice類可用作數組索引,它接受三個值初始值:起始索引、索引數、跨距。

1 valarry<double> arr(10);
2 arr[slice(1,4,3)] = 10;

  slice(1,4,3)創建的對象表示選擇4個索引,這可以將arr的第1、4、7、10個元素都設置為10。

  10、迭代器類型

Input iterator(輸入迭代器)  讀,不能寫;只支持自增運算
Output iterator(輸出迭代器) 寫,不能讀;只支持自增運算
Forward iterator(前向迭代器) 讀和寫;只支持自增運算
Bidirectional iterator(雙向迭代器) 讀和寫;支持自增和自減運算
Random access iterator(隨機訪問迭代器) 讀和寫;支持完整的迭代器算術運算

 

輸入、輸出和文件

  11、對於標準錯誤輸出,是沒有緩衝區的。

  12、在使用cout時,可以使用成員函數width()設置下一次輸出時的字段寬度,默認右對齊並以空格填充空白字段,當字段寬度不足時,C++不對截斷輸出寬度;使用成員函數fill()用來填充空白字段;使用成員函數precision()來設置浮點數輸出精度;成員函數setf()與unsetf()提供了更豐富的輸出格式設置方法,但使用標準控制符將更加簡單。

  13、對於cin的get()方法和getline()方法來說,如果沒有讀取到任何字符(getline()將換行符視為一個字符),則設置failbit;如果讀取了最大數目的字符,但行中還有其他字符,getline()將設置failbit

  14、cin的peak()方法可以查看輸入流中的下一個字符,gcount()方法可以返回最後一個非格式化抽取方法讀取的字符數,putback()方法可以將字符插入到輸入字符串中。

  15、fstream類中的方法seekg()和seekp()分別將輸入指針和輸出指針移到指定的文件位置,事實上,由於fstream類使用緩衝區來存儲中間數據,因此指針指向的是緩衝區中的位置,而不是實際的文件。

  16、fstream類中的方法tellg()和tellp()方法分別返回輸入流、輸出流當前指針的位置,對於fstream對象,輸入輸出指針將一前一后地移動,因此它們的返回值相同。但對於使用istream對象來管理輸入流,而使用ostream對象來管理同一個文件的輸出流,則輸入指針和輸出指針將彼此獨立的移動。

  17、關於如何生成臨時文件,使用tmpnam()可以生產TMP_NAM個不同的文件名,其中每個文件名包含的字符不超過L_tmpnam個。

  18、C++庫還提供了sstream族(包含ostringstream類和istringstream類),它們使用相同的接口提供程序和string對象之間的IO。

 

探討C++新標準

  19、新標準引入的移動語義,用來修飾六個特殊函數的default關鍵字,用來刪除任意成員函數的delete關鍵字,以及使用類似初始化列表的方式在一個構造函數中使用另一個構造函數(被稱為委託構造),以及使用using 類名::函數名,使基類所有的非特殊成員函數對派生類可以用(繼承構造函數),以及显示聲明重寫(覆蓋)某個虛函數的標識符override,以及禁止派生類覆蓋特定的虛函數標識符final

  20、C++11引入lambda表達的主要目的是能夠將類似於函數的表達式用作接受函數指針或函數符的函數的參數。

  21、C++提供了多個包裝器對象,用於給其他編程接口提供更一致或更合適的接口。C++11提供了包括模板bind(替代bind1st和bind2nd)men_fn(將成員函數作為常規函數傳遞)reference_wrapper(創建行為像引用但可被複制的對象)以及funtion(以統一的方式處理多種類似於函數的形式,使用模板時可減少可執行代碼的規模)

  22、正確使用遞歸實現可變參數模板

  23、C++11增加了對并行編程的支持,以及相當多的新增庫等。

 

附錄

  24、C++允許定義指向類成員(包括數據和函數)的指針,這種語法需要使用到成員解除引用運算符(* 、->*)。

  25、C++11新增了alignof運算符,它接受一個類型作為參數,返回這個類型的對齊方式;noexcept關鍵字用於指出函數不會引發異常,它也可以用作運算符,判斷表達式是否可能引發異常,不引發返回true。

  26、STL提供了豐富的全局函數,包括查詢,排序,複製等一系列算法。

  

  2020年6月2日,星期二,凌晨2點01分,首次完整讀完這本書,共勉。

  學如逆水行舟,不進則退;心似平原放馬,易縱難收。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

澳洲野火燒破千人家園 雪梨收災難性警告

摘錄自2019年11月11日ETtoday 綜合報導

澳洲東部森林野火自8日起延燒多日,造成3人死亡、數十人受傷以及上千人失去家園,仍在燃燒的上百處火場燒掉了至少150棟的住宅。當局指出,恐怕連雪梨及周邊地區也會受影響,12日將迎接「災難性」野火威脅。

外電報導,新南威爾斯州(New South Wales)及昆士蘭州(Queensland)等地接連傳出災情,當局派出將近1300名消防員也沒能撲滅燒了4天的大火,只能宣布災區進入「緊急狀態」,並警告人口最多的雪梨地區,高溫恐飆破攝氏37度,要面臨「災難性」(catasrophic)的野火威脅。

這也是澳洲2009年推出新的「火情危險評級制度」(Fire Danger Rating,分為中等、高、非常高、嚴重、極高及災難性)後,雪梨第一次面臨「災難性」等級,預計12日雪梨會出現攝氏37度高溫、強風、乾燥等,不排除比澳洲東部當初被野火襲擊時更嚴重。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

管理出包? 大堡礁集水區驗出高濃度殺蟲劑

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

水上太陽能火災 消防車要用特別款──千葉・山倉風災事件啟示錄

文:宋瑞文(加州能源特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

稀有越南老鼠鹿 近30年首度現蹤

摘錄自2019年11月12日中央通訊社綜合報導

一種外觀似鹿、大小相當於兔子或貓的小型哺乳類動物銀背鼷鹿(越南老鼠鹿),在失去蹤跡近30年後,近日首度在越南被發現。專家多年來認為此物種已瀕臨絕種。

根據今天發布在「自然生態學與進化」(Nature Ecology and Evolution)期刊的研究報告,紀錄顯示,越南老鼠鹿(Silver-backed Chevrotain,或Mouse deer)最後一次現蹤是在1990年。由於自1990年起即未有發現越南老鼠鹿的紀錄,專家推測此物種已因人類過度獵捕而瀕臨絕種。

由於人口成長和經濟開發對東南亞的樹林構成巨大生存壓力,生物學家堤爾克指出,保育工作必須搶占先機。根據聯合國「政府間生物多樣性與生態系服務科學政策平台」(IPBES)5月發布的報告,人類活動對地球的衝擊,導致高達100萬個物種瀕臨絕種。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

增近四倍 2015年Q1中國純電動車銷量達1.54萬輛

近日,中國汽車工業協會發佈最新統計資料顯示,今年第一季,中國汽車銷售達615.3萬輛,與去年同期相比增長3.9%,但相較去年同期9.2%的增幅,下滑明顯。此外新能源汽車產銷分別為2.73萬輛和2.66萬輛,與去年同期相比分別增長2.9倍和2.8倍。   其中,純電動車型銷售1.54萬輛,與去年同其相比增長3.7倍;插電式混合動力車型銷售1.12萬輛,與去年同期相比增長2.1倍。與新能源汽車相比,傳統車型銷量增幅卻明顯回落。根據資料,一季度乘用車共銷售530.51萬輛,與去年同其相比增長8.95%,增幅比去年同期回落1.14個百分點。在乘用車四類車型中,轎車銷量與去年同期相比下滑0.4%。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

電動車電池與太陽能成本下降飛快,再生能源主宰的日子不遠了?

  電動車電池的成本下降速度超乎預期,甚至低於國際能源署(IEA)原本預估的 2020 年成本數值,且不少研究也指出,太陽能在 2020 年代將某些地區成為最便宜的能源選項,彭博新聞認為,便宜的電池與太陽能發電兩者相輔相成的結果,將加速再生能源主宰能源市場的趨勢。   國際能源署在 2013 年時,原本預估 2020 年電動車電池價格將會下降至每度電 300 美元,不過,由斯德哥爾摩環境機構最近登上《自然氣候變化(Nature Climate Change)》期刊的研究中指出,全球電動車電池價格已從 2007 年的每千瓦小時 1,000 美元,下降至 2014 年的每千瓦小時 410 美元,平均每年成本下滑 14%,且特斯拉(Tesla)及 Nissan 等電動車製造商領頭羊的價格也年減約 8%,來到 2014 年的每千瓦小時 300美元,提早 6 年達到國際能源署預定目標。   但這所謂的每千瓦小時 300 美元,除了顯示電動車電池成本下降速度超乎預期外,是否還意味著電動車躍起的時代即將來臨呢?全球顧問公司麥肯錫(Mckinsey & Company)在 2011 年曾做了一張圖表,顯示不同的油價與電池價格情況下,純電動車、插電式混合電動車、油電混合車及一般汽車何者較具競爭力,灰色區塊的部分則是 2011 年的價格區間。從下圖圖表中可以看出,當電動車電池價格位於每千瓦小時約 300 美元左右時,就是電動車競爭力逐漸起飛的時刻。    
 

  (Source:)     雖然在過去一年中,油價已下跌至每加侖 2 美元,但若電池價格也跟著不斷下跌,圖表中的灰色矩形就會繼續向左移動。該研究作者認為,若按照特斯拉執行長 Elon Musk 所言,特斯拉正在興建的超級電池工廠真能大舉降低電池組成本 30%,且天然氣價格若反彈回 3 美元區間,將可能使電動車成功在大多數地區取代一般汽車的主宰地位。   此外,根據聯合國環境署(UNEP)於 3 月 31 公布的數據指出,2014 年全球對於再生能源投資額達 2,700 億美元,而新增的再生能源裝置容量,也超過往年的成長數字,來到歷史新高的 103 GW。   即便如此,但 2014 年全球再生能源發電總量僅占 9.1%,較 2013 年的 8.5% 成長 0.6 個百分點,雖然成長速度相當緩慢,且若等到再生能源發電量占全球發電量一半的份額,得等到 2080 年才可望實現。不過,太陽能發電成本下降速度增快,加上不少研究都預估太陽能最快將在 2020 年代就能成為最便宜的能源類型,或許照這樣看來,不用等到 60 年後,就能預見再生能源主宰能源市場的世界了。   便宜的電池與太陽能發電兩者可說是相輔相成,彭博新聞認為,電動車電池價格下跌能將汽車從傳統的汽油切換到電網連結,雖然目前大多數的電網仍然由燃煤發電驅動,但若太陽能發電成本下降速度夠快,搭配如特斯拉等公司欲打造的便宜家用儲能電池組,或許能解決太陽能發電不夠穩定、無法成為基載電力的缺點,以取代燃煤發電在電網中的主導角色。     本文全文授權轉載自《科技新報》─〈〉     (首圖來源:Flickr/CC BY 2.0)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案