每天3分鐘操作系統修鍊秘籍(14):IO操作和DMA、RDMA

I/O操作和DMA、RDMA

用戶進程想要執行IO操作時(例如想要讀磁盤數據、向磁盤寫數據、讀鍵盤的輸入等等),由於用戶進程工作在用戶模式下,它沒有執行這些操作的權限,只能通過發起對應的系統調用請求操作系統幫忙完成這些操作。這裏因為系統調用產生中斷將陷入到內核,進行一次上下文切換操作。

內核進程幫忙執行IO操作時,由於IO操作相比於CPU來說是極慢的操作,CPU不應該等待在這個過程中,而是切換到其它進程上去執行其它任務。這裏再次涉及到一次上下文切換:從內核態回到用戶態的其它進程。

DMA要求硬件的支持,需要在硬件中集成一個小型的“CPU”,比如現在的机械硬盤、固態硬盤、網卡等硬件都帶有DMA功能,這樣操作系統要執行IO操作時,直接將相關指令發送給這些DMA硬件,DMA處理器負責IO操作,而操作系統這時可以放棄CPU,讓CPU去執行其它進程。例如對於讀磁盤文件時,操作系統將相關指令以及數據應寫在哪個內存地址發送給DMA硬件后,由DMA硬件去讀寫數據到指定內存地址,當IO操作完成后,DMA硬件通過總線發送一個硬件中斷給CPU,於是陷入到內核態(這裏涉及了一次上下文切換),內核就知道了IO已經完成,於是將Kernel Buffer數據拷貝到用戶進程的IO Buffer,並準備調度用戶進程(再次上下文切換)。

假如不使用DMA硬件的話,那麼IO操作過程中,操作系統將多次參与,負責將硬件數據讀入或讀出內存,操作系統參与意味着要陷入到內核態,並且獲取CPU控制權,這也意味着要進行大量的上下文切換以及佔用大量CPU資源。

而使用DMA后,只有4次必要的上下文切換,且IO操作的過程中完全不需要消耗CPU資源。

除了DMA,還有更高級的RDMA(Remote Direct Memory Access)機制,它需要操作系統和硬件的支持,還需要編寫RDMA方式的代碼。

前面介紹緩衝空間時提到過,一般情況下,每個用戶進程要讀、寫數據,都會經過兩個必要的緩衝層:內核空間的Kernel Buffer、用戶空間的IO Buffer。例如讀文件數據時,先將數據拷貝到內核的緩衝空間(page cache),然後陷入內核,內核將該緩衝空間數據拷貝到用戶空間的緩衝空間(IO Buffer),當調度到用戶進程時,用戶進程從自己的緩衝空間讀取數據。

DMA機制並沒有繞過這兩個緩衝層,但使用RDMA機制,程序可以直接繞過Kernel Buffer,內核發現是RDMA操作后,直接告訴RDMA硬件將讀取的數據(寫操作也一樣)寫入到用戶空間的IO Buffer,而不需要先拷貝到Kernel Buffer,再拷貝到IO Buffer。雖然RDMA機制相比DMA不會減少上下文切換次數,但是它減少了內存數據拷貝的過程,相當於是使用了O_DIRECT標記的直接IO技術。

DMA和RDMA兩種技術對比如圖:RDMA一般實現在網卡上,但出於方便理解,下圖直接使用磁盤來描述

像這種繞過內核功能的技術,通常稱為內核旁路(Kernel Bypass),RDMA技術內核旁路的是一種,還有像TOE也是內核旁路的一種。

雖然RDMA比較優秀,但是它需要硬件、操作系統和代碼的同時支持,對編程而言是一個比較大的衝擊,所以目前使用的非常少。

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

【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

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

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

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

多線程之美1一volatile

目錄
一、java內存模型
1.1、抽象結構圖
1.2、概念介紹
二、volatile詳解
2.1、概念
2.2、保證內存可見性
2.3、不保證原子性
2.4、有序性

一、java內存模型

1.1、抽象結構圖

1.2、概念介紹

  • java 內存模型

    即Java memory model(簡稱JMM), java線程之間的通信由JMM控制,決定一個線程對共享變量的寫入何時對另一個線程可見。
  • 多線程通信通常分為2類:共享內存和消息傳遞

     JMM採用的就是共享內存來實現線程間的通信,且通信是隱式的,對程序開發人員是透明的,所以在了解其原理了,才會對線程之間通信,同步,內存可見性問題有進一步認識,避免開發中出錯。
  • 線程之間如何通信?

    在java中多個線程之間要想通信,如上圖所示,每個線程在需要操作某個共享變量時,會將該主內存中這個共享變量拷貝一份副本存在在自己的本地內存(也叫工作內存,這裏只是JMM的一個抽象概念,即將其籠統看做一片內存區域,用於每個線程存放變量,實際涉及到緩存,寄存器和其他硬件),線程操作這個副本,比如 int i = 1;一個線程想要進行 i++操作,會先將變量 i =1 的值先拷貝到自己本地內存操作,完成 i++,結果 i=2,此時主內存中的值還是1,在線程將結果刷新到主內存后,主內存值就更新為2,數據達到一致了。
    
    如果線程A,線程B同時將 主內存中 i =1拷貝副本到自己本地內存,線程A想要 將i+1,而線程B想要將 int j=i,將賦值給j,那麼如何保證線程之間的協作,此時就會涉及到線程之間的同步以及內存可見性問題了。(後文分析synchronized/lock)
     那線程之間實現通信需要經過2個步驟,藉助主內存為中間媒介:
       線程A (發送消息)-->(接收消息) 線程B  
       1、線程A將本地內存共享變量值刷新到主內存中,更新值;
       2、線程B從主內存中讀取已更新過的共享變量;
  • 共享內存中涉及到哪些變量稱為共享變量?

    這裏的共享內存指的是jvm中堆內存中,所有堆內存在線程之間共享,因為棧中存儲的是方法及其內部的局部變量,不在此涉及。
    共享變量:對於多線程之間能夠共同操作的變量,包含實例域,靜態域,數組元素。即有成員變量,靜態變量等等,
       不涉及到局部變量(所以局部變量不涉及到內存可見性問題)
  • 多線程在java內存模型中涉及到三個問題

    • 可見性
    • 原子性
    • 有序性(涉及指令重排序)

二、volatile詳解

2.1、概念

-1、volatile 是 java中的關鍵字,可修飾字段,可以保證共享變量的在內存的可見性,有序性,不保證原子性。
-2、作用:在了解java內存模型后,才能更加了解volatile在JMM中的作用,volatile在JMM中為了保證內存的可見性,即是線程之間操作共享變量的可見性。
  • volatile寫和讀的內存語義
volatile 寫的內存語義:
    當寫一個volatile修飾的共享變量時,JMM會把該線程的本地內存的共享變量副本值刷新到主內存中;
volatile 讀的內存語義:
    當讀一個volatile修飾的共享變量時,JMM會將該線程的本地內存的共享變量副本置為無效,要求線程重新去主內存中獲取最新的值。
  • java內存模型控制與volatile衝突嗎?什麼區別?
不衝突!java內存模型控制線程工作內存與主內存之間共享變量會同步,即線程從主內存中讀一份副本到工作內存,又刷新到主內存,那怎麼還需要 volatile來保證可見性,不是JMM自己能控制嗎,一般情況下JMM可以控制 2份內存數據一致性,但是在多線程併發環境下,雖然最終線程工作內存中的共享變量會同步到主內存,但這需要時間和觸發條件,線程之間同時操作共享變量協作時,就需要保證每次都能獲取到主內存的最新數據,保證看到的工作變量是最後一次修改后的值,這個JMM沒法控制保證,這就需要volatile或者後文要講的 synchronized和鎖的同步機制來實現了。

2.2、保證內存可見性

  • 1、多個線程出現內存不可見問題示例

    /**
     * @author zdd
     * Description: 測試線程之間,內存不可見問題
     */
    public class TestVisibilityMain {
        private static boolean isRunning = true;
    
      // 可嘗試添加volatile執行,其餘不變,查看線程A是否被停止
      //private static volatile boolean isRunning = true;
    
        public static void main(String[] args) throws InterruptedException {
    //1,開啟線程A,讀取共享變量值 isRunning,默認為true 
            new Thread(()->{
              // --> 此處用的lamda表達式,{}內相當於Thread的run方法內部需執行任務 
                System.out.println(Thread.currentThread().getName() + "進入run方法");
                while (isRunning == true) {
                }
                System.out.println(Thread.currentThread().getName()+"被停止!");
            },"A").start();
            //2,主線程休眠1s, 確保線程A先被調度執行
            TimeUnit.SECONDS.sleep(1);
        //3,主線程修改共享變量值 為flase,驗證線程A是否能夠獲取到最新值,跳出while循環  --> 驗證可見性
            isRunning =false;
            System.out.println(Thread.currentThread().getName() +"修改isRunning為: " + isRunning);
        }
    }

​ 執行結果如下圖:

  • 2、一個容易忽視的問題
 上面代碼 while裏面是一個空循環,沒有操作,如果我在裏面加一句打印語句,線程A會被停止,這是怎麼回事呢?
 原:while (isRunning == true) {}
 改1:
 while (isRunning == true) {
     System.out.println("進入循環");
 }
原來 println方法裏面加了 synchronized關鍵字,在加了鎖既保證原子性,也保證了可見性,會實現線程的工作內存與主內存共享變量的同步。
源代碼如下:
 public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
  改2:
  while (isRunning == true) {
       //改為這樣,也可以停止線程A
                synchronized (TestVisibilityMain.class){}
   }

2.3、不保證原子性

  • 1、示例代碼
/**
 * @author zdd
 * Description: 測試volatile的不具有原子性
 */
public class TestVolatileAtomic {

    private static volatile   int  number;
    //開啟線程數
    private static final  int THREAD_COUNT =10;
    //執行 +1 操作
    public static void  increment() {
       //讓每個線程進行加1次數大一些,能夠更容易出現volatile對複合操作(i++)沒有原子性的錯誤
        for (int i = 0; i < 10000; i++) {
          number++;
        }
        System.out.println(Thread.currentThread().getName() +"的number值: "+number);
    }

    public static int getNumber() {
        return number;
    }

    public static void main(String[] args) throws InterruptedException {
        TestVolatileAtomic volatileAtomic  = new TestVolatileAtomic();
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            threads[i]=
            new Thread(()->{
               // 做循環自增操作
                volatileAtomic.increment();
                System.out.println(Thread.currentThread().getName() +"的number值: "+volatileAtomic.getNumber());
            },"thread-"+i);
        }

        for (int i = 0; i <10; i++) {
          //開啟線程
            threads[i].start();
        }
        //主線程休眠4s,確保上麵線程都執行完畢
        TimeUnit.SECONDS.sleep(4);
        System.out.println("執行完畢,number最終值為:"+volatileAtomic.getNumber());
    }
}

執行結果:number的最後值不一定是 10*10000= 100000的結果
  • 2、解決上訴問題
 
  //1,increment()方法上加上 synchronized關鍵字同步
    public static synchronized void  increment() {
       //讓每個線程進行加1次數大一些,能夠更容易出現volatile對複合操作(i++)沒有原子性的錯誤
        for (int i = 0; i < 10000; i++) {
          number++;
        }
         System.out.println(Thread.currentThread().getName() +"的number值: "+number);
    }
  //2,使用Lock,使用其實現類可重入鎖 ReentrantLock
    static Lock lock = new ReentrantLock();
    //執行 +1 操作
    public static   void  increment() {
        lock.lock();
        try {
            for (int i = 0; i < 10000; i++) {
                number++;
            }
            System.out.println(Thread.currentThread().getName() + "的number值: " + number);
        } finally {
            lock.unlock();
        }
    }

運行結果如圖:

  • 3、原因分析
對單個volatile變量的讀/寫具有原子性,而對像 i++這種複合操作不具有原子性。
上面代碼 i++操作可以分為3個步驟
-1 先讀取變量i的值   i
-2 進行i+1操作   temp= i+1
-3 修改i的值     i= temp
比如:比如在線程A,B同時去操作共享變量i, i的初始值為10,A,B同時去獲取i的值,A對i進行 temp =i+1,此時i的值還沒變, 線程B也對i進行 temp=i+1了,線程A執行i=temp的操作,i的值變為11,此時由於 volatile可見性,會刷新A的 i值到主內存,主內存中i此時也更新為11了,線程B接收到通知自己i無效了,重新讀取i=11,雖然i=11,但是已經進行過 temp= i+1了,此時temp =11,線程B繼續第三步,i=temp =11, 預期結果是i被A,B自增各一次,結果i=12,現在為11,出現數據錯誤。

2.4、有序性

  • 重排序
-1,重排序概念:重排序是編譯器和處理器為了優化程序性能而對指令序列重新排序的一種手段
即:程序員編寫的程序代碼的順序,在實際執行的時候是不一樣的,這其中編譯器和處理器在不影響最終執行結果的基礎上會做一些優化調整,有重新排序的操作,為了提高程序執行的併發性能。
-2,重排序分類: 編譯重排序,處理器重排序
-4,單線程下,重排序沒有問題,但是在多線程環境下,可能會破壞程序的語義.
  • volatile 防止重排序保證有序性

為了實現volatile的內存語義,JMM會限制編譯器和處理器重排序

-1 制定了重排序規則表防止編譯器重排序

volatile重排序規則表(圖摘自書-併發編程的藝術)

-2 插入內存屏障防止處理器重排序

參考資料:
1、Java併發編程的藝術- 方騰飛
2、java多線程編程核心技術- 高洪岩

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

vue學習筆記(五)條件渲染和列表渲染

前言

在眾多的編程語言中,我們的基礎語法總是少不了一些專業語法,比如像定義變量,條件語句,for循環,數組,函數等等,vue.js這個優秀的前端框架中也有同樣的語法,我們換一個名詞,將條件語句改成專業詞彙叫做條件渲染,循環語句改成專業詞彙叫做列表渲染,這樣比較舒服一點。

本章目標

  • 學會條件渲染的使用

  • 學會可復用的key的使用

  • 學會列表渲染的使用

條件渲染

1.v-if的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app01">
    <span v-if="type==='A'">成績為A</span>
</div>
<script src="../js/vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app01',
        data:{
            type:'A'
        },
        methods:{
            
        },
        watch:{
            
        },
        computed:{
            
        }
    })
</script>
</body>
</html>

結果:成績為A

v-if判斷條件是否相等,就像if一樣,如果相等,那麼值就會true,與之對應的還有v-else,v-else-if

2.v-else的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app01">
    <span v-if="type==='A'">成績為A</span>
    <span v-else>成績為B</span>
</div>
<script src="../js/vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app01',    
        data:{
            type:'B'
        },
        methods:{
            
        },
        watch:{
            
        },
        computed:{
            
        }
    })
</script>
</body>
</html>

結果:成績為B

小練習

我們做一個小練習,鞏固一下v-if和v-else的使用,需求如下:點擊一個按鈕時,按鈕上的文字變為显示,再次點擊時按鈕上的文字變為隱藏,當按鈕上的文字显示隱藏時,显示紅色,按鈕上的文字變為显示時显示藍色

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button @click="handleClick">{{text}}</button>
            <div v-if="show" class="box red"></div>
            <div v-else class="blue box"></div>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                    text:'隱藏'
                },
                methods:{
                    handleClick(){
                        this.show=!this.show;
                        this.text=this.show?'隱藏':'显示'
                    }
                }
            })
            
        </script>
    </body>
</html>

結果

 

3.v-else-if的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app01">
    <input type="text" v-model="type"/>
    <div v-if="type==='A'">成績為A</div>
    <div v-else-if="type==='B'">成績為B</div>
    <div v-else-if="type==='C'">成績為C</div>
    <div v-else>不及格</div>
</div>
<script src="../js/vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app01',    
        data:{
            type:''
        },
        methods:{
            
        },
        watch:{
            
        },
        computed:{
            
        }
    })
</script>
</body>
</html>

結果:

4.v-show

說起這個v-show,其實和v-if有與曲同工的妙處,但是又有不同的地方,我們來看下示例你就秒懂了

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div v-show="show" class="box red"></div>
            <button @click="handleClick()">{{text}}</button>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                    text:'隱藏',
                },
                methods:{
                    handleClick(){
                        this.show=!this.show;
                        this.text=this.show?'隱藏':'显示'
                    }
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

當按鈕變為显示的時候,背景顏色消失,這裏就不截圖了,有興趣的小夥伴可以自己去嘗試,既然v-if可以幫我們實現元素的显示和隱藏,那我們還需要v-show干什麼呢?不妨看下接下來的實例。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div v-show="show" class="box red"></div>
            <div class="box blue" v-if="show"></div>
            <button @click="handleClick()">{{text}}</button>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                    text:'隱藏',
                },
                methods:{
                    handleClick(){
                        this.show=!this.show;
                        this.text=this.show?'隱藏':'显示'
                    }
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

 當我們點擊按鈕的時候

 

現在結果已經出來了,使用v-show的dom元素,dom元素只是簡單的切換display屬性,而v-if會將dom元素移除,當我們再次點擊時,v-if又會重新渲染元素,可想而知如果頻繁的切換的話,那麼有多麼的耗費性能,因此我總結了如下幾點

  • 頻繁的切換显示/隱藏要使用v-show

  • 只判斷一次時,使用v-if

5.減少dom的生成

我們都知道js操作dom元素是非常消耗性能的,但是我們需要盡量的避免這個問題,vue中為我們提供了一個template標籤,這個標籤叫做模板(至於什麼叫做模板,後期的博客會講到),我們先看一個示例

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div v-if="show">
                <div class="box red"></div>
                <div class="box blue"></div>
            </div>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

 我們想讓圖上的那個div消失,不想為了管理同一組元素而多生成一個節點,這樣是非常消耗性能的,我們將div標籤變成template標籤

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div v-if="show">
                <div class="box red"></div>
                <div class="box blue"></div>
            </div>
            <template v-if="show">
                <div class="box red"></div>
                <div class="box blue"></div>
            </template>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

View Code

 現在我有心中萌生了一個想法,v-if可以使用template,那麼v-show是否可以使用呢?

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .box{
                width: 100px;
                height: 100px;
            }
            .red{
                background: red;
            }
            .blue{
                background: blue;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <template v-if="show">
                <div class="box red"></div>
                <div class="box blue"></div>
            </template>
            <template v-show="show">
                <div class="box red"></div>
                <div class="box blue"></div>
            </template>
            <button @click="handleClick()">{{text}}</button>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    show:true,
                    text:'隱藏',
                },
                methods:{
                    handleClick(){
                        this.show=!this.show;
                        this.text=this.show?'隱藏':'显示'
                    }
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

View Code

 

 答案是v-if可以使用template,而v-show不能使用template

vue中用key管理可復用的元素

Vue 會盡可能高效地渲染元素,通常會復用已有元素而不是從頭開始渲染。這麼做除了使 Vue 變得非常快之外,還有其它一些好處。例如,如果你允許用戶在不同的登錄方式之間切換。

示例一:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app01">
    <template v-if="type==='username'">
        <label>用戶名</label>
        <input type="text" placeholder="請輸入您的賬號" />
    </template>
    <template v-else>
        <label>郵箱</label>
        <input type="text" placeholder="請輸入您的郵箱" />
    </template>
    <p>
        <a href=""@click.prevent="type='username'">用戶名登錄</a>|
        <a href=""@click.prevent="type='email'">郵箱登錄</a>
    </p>
</div>
<script src="../js/vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app01',    
        data:{
            isShow:true,
            type:'username'
        },
        methods:{
            
        },
        watch:{
            
        },
        computed:{
            
        }
    })
</script>
</body>
</html>

結果:

 

 

當我們在用戶名登錄和郵箱切換的時候,我們發現我們輸入的內容始終保持,為什麼呢?總的來說,因為兩個模板使用了相同的元素,input不會被替換掉——僅僅是替換了它的 placeholder屬性,這樣也不總是符合實際需求,所以 Vue 為你提供了一種方式來表達這兩個元素是完全獨立的,不要復用它們,只需添加一個具有唯一值的key屬性即可。

示例二:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="app01">
    <template v-if="type==='username'">
        <label>用戶名:</label>
        <input type="text" placeholder="請輸入您的用戶名"  key='usename'/>
    </template>
    <template v-else>
        <label>郵箱:</label>
        <input type="text" placeholder="請輸入您的郵箱"  key='email'/>
    </template>
    <p>
        <a href=""@click.prevent="type='username'">用戶名登錄</a>|
        <a href=""@click.prevent="type='email'">郵箱登錄</a>
    </p>
</div>
<script src="../js/vue.js"></script>
<script>
    let vm=new Vue({
        el:'#app01',    
        data:{
            isShow:true,
            type:'username'
        },
        methods:{
            
        },
        watch:{
            
        },
        computed:{
            
        }
    })
</script>
</body>
</html>

結果:

 

現在我們點擊切換的時候,輸入框都會重新渲染,當然我們的<label>標籤依舊的高效的復用,因為它沒有添加key。

列表渲染

我們用v-for指令根據一組數組的選項列表進行渲染,v-for指令需要以item in items的形式的特殊語法,items是原數據數組並且item是元素迭代的別名

1.v-for的基本使用

語法:(item,index) in|of items

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>v-for的基本使用</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(item) in arr">{{item}}</li>
            </ul>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    arr:['apple','banana','pear']
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

結果:

當然v-for中也可以帶第二個參數index

2.v-for中帶索引

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>v-for的基本使用</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(item,index) in arr">{{item}}--{{index}}</li>
            </ul>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    arr:['apple','banana','pear']
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

View Code

3.v-for迭代字符串

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>v-for的基本使用</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(item,index) in arr">{{item}}--{{index}}</li>
            </ul>
            <ul>
                <li v-for="item in 'helloworld'">{{item}}</li>
            </ul>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    arr:['apple','banana','pear']
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

View Code

4.v-for迭代對象

語法:(value,key,index) of | in items

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>v-for迭代對象</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(value,key,index) of obj">{{value}}-{{key}}-{{index}}</li>
            </ul>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    obj:{
                        name:'kk',
                        age:18,
                        sex:'male'
                    }
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

結果:

5.v-for迭代整數

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>v-for迭代對象</title>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(value,key,index) of obj">{{value}}-{{key}}-{{index}}</li>
            </ul>
            <ul>
                <li v-for="item in 10">{{item}}</li>
            </ul>
        </div>
        <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            let vm=new Vue({
                el:'#app',
                data:{
                    obj:{
                        name:'kk',
                        age:18,
                        sex:'male'
                    }
                },
                methods:{
                    
                },
                computed:{
                    
                }
            })
        </script>
    </body>
</html>

結果:

注意:但我們迭代整數的時候,item從1開始而不是從0開始

總結

在本章內容中,我們一共學習了三個知識點,分別是條件渲染的使用(v-if,v-else,v-else-if),管理可復用的key,列表渲染(v-for的基本使用等等),本章的內容也多但是在實際應用上非常廣泛,畢竟這些是非常基礎的語法,基礎不牢,地動山搖,學習任何東西都需要自己一步一個腳印走出來。

 

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

【其他文章推薦】

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

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

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

南投搬家前需注意的眉眉角角,別等搬了再說!

如何讀好一本書

這個年代,對中年人販賣焦慮是件普遍的事情,尤其是對程序員。35歲左右都是一個坎,不管是國內的華為、阿里,還是國外的facebook,這種焦慮和恐慌逼得程序員不得不時刻充電。學習的方式有很多,做項目、線下線上課程、看書、看博客、看源碼等等。

相比其他方法,看書(尤其是經典書籍)的好處在於,知識點比較系統全面,講解比較清楚,質量也有所保證。

這一兩年,也看了一些書,技術和非技術都有,可是回頭想想,記得多少,又有哪些用到了實處,似乎很少。於是,懷疑哪裡出了問題,是年紀大了記性不好?還是讀書的方法出了問題?

因此,為了更好的閱讀,我們就得先掌握科學、高效閱讀的方法,而就是指導我們科學閱讀的利器。

“how to read a book” is a metabook about how to read a book

本文地址:

主動閱讀

how to read a book反覆強調 主動閱讀:為了學習知識、增進理解而閱讀,而不是為了獲得諮詢。獲取信息、諮詢所需要的理解力恰好是讀者擁有的,而為了知識而進行的主動閱讀是需要讀者的努力,當然也只有這樣讀者才能成長。

閱讀是作者與讀者的交流,作者拋出問題,然後給出答案,而讀者需要去判斷作者給出的答案是否合理,這個過程就需要讀者的思考。

那麼,怎麼才算是主動閱讀呢,要做到主動閱讀,至少要回答以下四個問題:

  • 整體來說,這本書在討論什麼問題
  • 圍繞核心問題,作者有哪些主要的想法、論點
  • 作者所述是否合理,是部分合理,還是全部合理。當然,這一點的基礎是讀者能回答出上兩個問題
  • 這本書與讀者有何關係,有何啟發,如何運用

關於跳出舒適圈

主動閱讀強調的是需要努力才能掌握知識的閱讀,其實換一種流行的說法就是跳出舒適圈,需要每次都有所進步。

不過,是否跳出舒適圈並不是簡單的0或者1問題,跳出多遠呢?比如閱讀一本全新領域的書,基本上都看不懂,強迫自己看下去也很痛苦。

恰好前一段時間在簡書上看到一篇很有意思的文章: 。在這篇文章中,首先是給出下面這張圖:

從中可以看到,對於學習這件事情,自內而外分三個區

  • 舒適區,conform zone
  • 學習區,learning zone
  • 恐慌區,panic zone

閱讀的舒適區,大約就是為了獲取諮詢、信息而進行的閱讀。而主動閱讀就得跳出舒適區,需要小心意的是,別跳太遠,一下跳到恐慌區反而會有負作用。

那麼,跳多遠是合適的呢,這篇文章中參考了機器學習的一個實驗,指出15.87%是個理想值。就是說,閱讀的時候,應該有85%的內容是讀者能理解的,這樣學習起來既愉快,而且效率也最高。

當然,這個具體的數值因人而異,至少說,如果略讀一本書,大多數的概念都不了解,那麼可能這本書對現階段的你可能不是最好的選擇。

閱讀的四個層次

閱讀的層級,按對閱讀者的要求從低到高排序,分別是:

  • 基礎閱讀(elementary reading)
  • 檢視閱讀(inspectional reading)
  • 分析閱讀(analytical reading)
  • 主題閱讀(syntopical reading)

基礎閱讀的典型問題是,“這個句子在說什麼?”基礎閱讀的能力,應該是在基礎教育的時候就培養的,而且對於絕大多數人來說應該不存在問題。不幸的是,對於程序員–需要閱讀英文原版書籍、論文的程序員–來說,這有時候確實是個問題。雖然筆者也過了英語六級,但是在閱讀英文資料的時候還是可能因為詞彙、語法而卡殼。

檢視閱讀其實就是略讀、粗讀,在較短的時間內掌握一本書的重點、整體架構。典型問題就是:“這本書在談什麼?”或者:“這本書的架構如何?”或是:“這本書包含哪些部分?”

而分析閱讀是全盤的閱讀、完整的閱讀,或是說優質的閱讀。也就是我們常說的,要把一本書讀厚。分析閱讀需要反覆的咀嚼、消化,自然是非常耗時間的,因此我們進行分析閱讀的書籍應該是經過挑選的經典書籍。

最後的主題閱讀,其實就是帶着問題去閱讀。前面的檢視閱讀和分析閱讀都是指閱讀某一本書,而主題閱讀通常需要閱讀好幾本書,才能從不同角度去思考、解決一個問題。

下面依次簡單介紹檢視閱讀、分析閱讀、主題閱讀的基本方法、規則。

檢視閱讀

檢視閱讀既可以作為獨立的閱讀方式,又可以作為分析閱讀或者主題閱讀的前置步驟。

檢視閱讀的第一個階段是有系統的略讀或粗讀。

  1. 先看書名頁,然後如果有序就先看序
    看完序章之後,其實就對這本書的主題有了概念,可以為這本書進行分類了。
  2. 研究目錄頁,對這本書的基本架構做概括性的理解
  3. 如果書中附有索引,也要檢閱一下。
  4. 如果那是本包着書衣的新書,不妨讀一下出版者的介紹。
  5. 從你對一本書目錄很概略,甚至有點模糊的印象當中,開始挑幾個看來跟主題息息相關的篇章來看。如果這些篇章在開頭或結尾有摘要說明(很多會有),就要仔細地閱讀這些說明。
  6. 最重要的是,不要忽略最後的兩三頁,很少有作者能拒絕這樣的誘惑,而不在結尾幾頁將自己認為既新又重要的觀點重新整理一遍的。
    在how to read a book一書中,每章節的最後,作者都會進行總結、概括。

通過上述步驟,就可以從主體、架構上了解一本書,至少能夠判斷,這本書是否值得花時間更深入的閱讀

檢視閱讀的第二個階段是粗淺的閱讀,也就是說頭到尾先快速的讀完一遍,關注的重點在於理解的部分,不要因為暫時不能理解的部分而停頓,這樣閱讀一遍之後也是會很有收益的。

分析閱讀

分析閱讀的第一階段,或,找出一本書在談些什麼的四個規則:
第一個規則:依照書本的種類與主題作分類。

how to read a book對書籍分類是這樣的:首先按照是否是虛構,分成小說類和論說類。論說類的書籍是為了傳遞知識,也是探討的重點。

對於論說類,又分為實用性作品和理論性作品。理論性的作品是在教你這是什麼,實用性的作品在教你如何去做你想要做的事,或你認為應該做的事。

how to read a book本身就是一本實用性的書籍

第二個規則:用最簡短的句子說出整本書在談些什麼。

第二個規則,就是要能說出整本書的大意,整體上來把握一本書。這一部分,通過閱讀書目和序章基本上就能有答案

第三個規則:按照順序與關係,列出全書的重要部分。將全書的綱要擬出來之後,再將各個部分的綱要也一一列出。

一本好書,就像一棟好房子,每個部分都要很有秩序地排列起來。每個重要部分都要有一定的獨立性。

這有點類似金字塔原理中的MECE(Mutually Exclusive Collectively Exhaustive),架構良好的書籍也會按照符合邏輯的順序展示主題相關的每一個部分。

第四個規則:找出作者在問的問題,或作者想要解決的問題。

一本書的作者在開始寫作時,都是有一個問題或一連串的問題,而這本書的內容就是一個答案,或許多答案。在分析閱讀的第一個階段,讀者都明白作者將解答的是什麼樣的問題。

分析閱讀的第二個階段,或找出一本書到底在詳細說什麼的規則(詮釋一本書的內容):

第五規則:詮釋作者使用的關鍵字,與作者達成共識。

同一個詞彙,在不同的語境下有不同的語義,比如“事務”這個詞語,不同領域裏面的含義千差萬別。在特定的領域裏面,我們常常稱這種專門用語及特殊字彙為術語。為了搞清楚一本書在說些啥,首先得找出這些術語,然後分辨出術語在這本書當中最精確的意義。

如何找出術語呢,如果比較熟悉書籍所在領域,那麼自然就能找出這些專門的詞彙;反過來,只要看到不是平常慣見的詞彙,就會知道那些字一定是專門用語。

如何衡量是否有作者就某個術語的精確意義達成了共識呢?讀者可以用自己的話語來解釋這個術語。

第六個規則:從最重要的句子中抓出作者的重要主旨。

主旨,也是一種聲明。那是作者在表達他對某件事的判斷。主旨所聲明的是知識或觀點。這也是為什麼我們說表達這種聲明的句子是敘述句(declarative),而提出問題的句子是疑問句(interrogative)

如何判斷自己是否吸收了一本書的主旨呢?有以下方法

  • 能否用自己的語言重新表達?
  • 舉出一個自己所經歷過的主旨所形容的經驗,或與主旨有某種相關的經驗?
  • 就作者所闡述的特殊情況,說明其中通用於一般的道理?

第七個規則:找出作者的論述,重新架構這些論述的前因後果,以明白作者的主張。

第八規則:確定作者已經解決了哪些問題,還有哪些是未解決的。在未解決的問題中,確定哪些是作者認為自己無法解決的問題。

分析閱讀的第三階段:像是溝通知識一樣地評論一本書的規則

第九規則:除非你已經完成大綱架構,也能詮釋整本書了,否則不要輕易批評。(在你說出:“我讀懂了!”之前,不要說你同意、不同意或暫緩評論。)

第十規則:不要爭強好勝,非辯到底不可。

第十一規則:在說出評論之前,你要能證明自己區別得出真正的知識與個人觀點的不同。

主題閱讀

主題閱讀是閱讀的最高層級,即帶着某個特定問題去大量閱讀相關書籍中的相關章節。檢視閱讀和分析閱讀都是以書為中心,而主題閱讀是以特定問題為核心

在主題閱讀中有兩個階段。一個是準備階段,另一個是主題閱讀本身。

主題閱讀的準備階段是為了觀察、選擇研究範圍,一定程度上會用到檢視閱讀的規則

  • 針對你要研究的主題,設計一份試驗性的書目。你可以參考圖書館目錄、專家的建議與書中的書目索引。
  • 瀏覽這份書目上所有的書,確定哪些與你的主題相關,並就你的主題建立起清楚的概念。

主題閱讀的第二個階段:閱讀所有第一階段收集到的書籍

  • 瀏覽所有在第一階段被認定與你主題相關的書,找出最相關的章節。
  • 根據主題創造出一套中立的詞彙,帶引作者與你達成共識——無論作者是否實際用到這些詞彙,所有的作者,或至少絕大部分的作者都可以用這套詞彙來詮釋。
  • 建立一个中立的主旨,列出一連串的問題——無論作者是否明白談過這些問題,所有的作者,或者至少大多數的作者都要能解讀為針對這些問題提供了他們的回答。
  • 界定主要及次要的議題。然後將作者針對各個問題的不同意見整理陳列在各個議題之旁。你要記住,各個作者之間或之中,不見得一定存在着某個議題。有時候,你需要針對一些不是作者主要關心範圍的事情,把他的觀點解讀,才能建構出這種議題。
  • 分析這些討論。這得把問題和議題按順序排列,以求突顯主題。比較有共通性的議題,要放在比較沒有共通性的議題之前。各個議題之間的關係也要清楚地界定出來。

注意:理想上,要一直保持對話式的疏離與客觀。要做到這一點,每當你要解讀某個作家對一個議題的觀點時,必須從他自己的文章中引一段話來並列。

如何實踐閱讀

在how to read a book的最後一章 “閱讀與心智的成長”, 有兩個觀點,個人是深表認同的

  • 如果你所讀的書都在你的能力範圍之內,你就沒法提升自己的閱讀能力。你必須能操縱超越你能力的書,或所說的,閱讀超越你頭腦的書
  • 如果讀者閱讀了一本實用的書,並接受作者的觀點,認同他的建議是適當又有效的,那麼讀者一定要照着這樣的建議行事

第一點其實就是要從舒適區跳到學習區,主動閱讀。關於這一點,已經在本文第一章進行了討論。

第二點,就是學以致用。

我們常說,聽過很多道理,卻依然過不好這一生,也許道理已經懂了,但是沒有落到實處,自然不會有任何改變。對於閱讀更是如此,閱讀相比教學而言,更需要學習者的主動,而且閱讀本身比較慢,也很少存在很強烈的時間壓力和考核目標,如果讀者不主動去刻意使用,那麼大概率過一段時間就忘了。

實用性書籍閱讀

前面對書籍分為了虛構類、實用類、理論類。對於程序員的技術閱讀而言,大多時候都是實用類。閱讀的目標都是為了提高自己的能力,將知識應用到工作中。

在閱讀任何一種實用書時,一定要問自己兩個主要的問題。
第一:作者的目的是什麼?
第二:他建議用什麼方法達到這個目的?

比如筆者之前閱讀了《clean code》這本書,作者的目的就是讓我們認識到代碼整潔的重要性以及如何寫出整潔的代碼。而如何寫出整潔代碼呢,作者先從小到大,指出應該如何命名、寫好函數、寫好注意、寫好一個類;然後再給出一個完整的逐步改善的列子。

在how to read a book中,給出了主動閱讀一本書,至少要回答的四個問題,這裏回顧一下

  1. 整體來說,這本書在討論什麼問題
  2. 圍繞核心問題,作者有哪些主要的想法、論點
  3. 作者所述是否合理,是部分合理,還是全部合理
  4. 這本書與讀者有何關係,有何啟發,如何運用

這四點對於閱讀適用類書籍來說非常合適

第一點,實用性書籍討論的問題,其實就是作者作者寫這本書的目的,即希望讀者去做到的事情。

第二點,實用性書籍中的主要想法和論點,即使就是作者闡釋為什麼要這麼做、如何達到這個目的。

第三點,作者所述是否正確、合理,對於實用性的書籍,更多的是你是否認同作者的目的、以及達成目的的方法。

第四點,對於實用性書籍,如果你認同了作者的說法,那麼就得採取行動才行。

上面四點,最難的就是落實,學以致用,知行合一。

刻意練習

很多時候,我們看完一本書,或者看完一個在線課程,我們就認為掌握了知識。其實不然,掌握知識需要知識的內隱化,讓這部分知識成為習慣、潛意識。這個過程並沒有捷徑可走,需要不斷的練習,只不過一些知識、技能是每天都能用到的,而有一些則較少用到,對於後者,則需要專門安排時間來刻意練習

比如,當我們看完了how to read a book這本書,想要掌握分析閱讀的技能。那麼需要按照規則一步步執行,這個過程中可能就要求也不同的速度、注意力反覆閱讀一本書,也許會讓人覺得麻煩 — 為什麼不看一遍就搞定?對於一個熟練掌握分析閱讀能力的人來說,也許確實可以在一遍閱讀中同時遵守這些規則,但前提是已經熟練掌握了每一個規則。

就像學游泳一樣,對於新手,會花大量的時間來練習移臂、擺腿、換氣,一遍又一遍的重複這些枯燥的動作。但對於老手來說,似乎從來不會刻意注意這些動作,如果注意這些動作,反而還游不好。但是,為了要忘掉這些單一的動作,一開始就必須先分別學會每一個單一的動作,只有這樣,你才能將所有的動作連結起來。

如何刻意練習 實用性書籍閱讀這件事情呢?RIA拆書法是個可行的辦法:

RIA拆書法

RIA拆書法來自一書,不過本人沒有讀過這本書,對於RIA拆書法,感覺這篇文章 介紹得很清楚。

如圖所示,RIA分為四個階段

  • R: 找到有價值、感興趣的片段
  • I:用自己的語言重述知識
  • A1:描述自己的相關經驗
  • A2:思考自己怎麼應用,指定計劃

其中,I、A1、A2這三步要求讀者用不同顏色的便簽做記錄,貼在原書頁處。

其實,這幾點都是how to read a book中的規則的具體體現,比如I和A1,其實就是分析閱讀的第六個規則中衡量自己是否掌握了主旨的方法,而A2則是閱讀實用性書籍需要回答的第四個問題。

RIA的好處在於通過這幾個標籤強迫讀者停下來進行思考、記錄,將思考的結果和原問題保持在同一個地方,方便回顧;不同顏色的便簽也是很好的視覺刺激,方便記憶。

最後,RIA拆書法還要求:看完一本書後,把所有的A2便簽拿出來貼在牆上,提醒自己日後應用,落實行動。

所以RIA的正式貫徹了學習 — 思考 — 實踐這個流程,值得借鑒 參考。

自我實踐:讀好下一本書

上面的內容,其實都是我所學到的“如何閱讀一本(實用性)書籍”的知識,具體怎麼落實呢?打算用《金字塔原理》這本書來實踐,這本書聽聞已久,也簡單知道其內容,但還沒有仔細閱讀過。

怎麼閱讀呢,會按照以下步驟(checklist)

  • 思考清楚閱讀一本書的目的是什麼,以此決定是檢視閱讀、分析閱讀還是主題閱讀,甚至決定要不要閱讀這本書(閱讀書籍不一定是解決問題的最有效方法,或者當前自己的知識貯備還無法閱讀這麼一本書)。以下步驟假設均決定分析閱讀
  • 如果確定要分析閱讀,那麼應按照smart原則來設立讀這本書的目標。核心在於輸出是怎麼樣的,具體的閱讀計劃(每天讀多少,什麼時候讀完)
  • 利用檢視閱讀,找出這本書的主旨(作者要探討的問題)、主體架構、問題的簡要答案。檢視閱讀也會幫助去調整閱讀計劃。檢視閱讀注重以下幾部分
    • 書目、序章
    • 目錄,每章總結
    • 結語
  • 分析閱讀這本書,做好筆記。分析閱讀注意事項:
    • 使用8020法則,嘗試按照重要性挑戰閱讀速度、時間分配,不重要的章節速讀
    • 核心的部分採用RIA方法(複述、聯想、如何應用)
  • 分析閱讀完成之後,回答閱讀一本實用性書籍應該回答的四個問題。此時可參考輔助閱讀,看看其他讀者的總結和思考。
  • 加強記憶、內化,分為三步:
    • 筆記:在閱讀的過程中就應完成;
    • 博客、腦圖二選一,對筆記進行凝練,深入思考;
    • 分享、實踐二選一,理論知識一般適用於分享,而實用性知識盡量去實踐。
  • 如何實踐落實,總結RIA方法中所有A2,整理成一個checklist(电子版或者紙版),定期逐項check是否有做到

爭取年內搞定!

references

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

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

美生物學家夫婦深入拉美記錄野生動物

摘錄自2020年1月25日公視報導

氣候變遷讓全世界許多珍貴的物種面臨可能消失的危機,有一對美國的生物學家夫婦在哥斯大黎加執行拍攝動物的計畫,希望能將這些影像分享給世人。

八年前,來自美國賓州的生物學家洛沙索以及太太琳熙,搬到哥斯大黎加西北部的瓜拿卡斯特省,去年底,他們成立瓜拿卡斯特監控計畫,在當地超過40個森林裡架設隱藏式攝影機,收錄超過100個不同的野生動物物種、約1萬個錄影的片段。這些鏡頭防水防震,還有動態捕捉以及夜間攝影功能。他們希望將這些拍攝到的珍貴畫面,分享給在地的孩子。

根據世界自然基金會的報告,哥斯大黎加面積不到全世界的1%,但其生物多樣性卻佔全球的5%,而這其中有超過25%,是國家指定為特別保護的森林及保育區。

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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

中國全面禁野生動物交易

摘錄自2020年1月27日自由時報中國報導

中國國家市場監督管理總局、農業農村部和國家林業和草原局26日發布聯合公告,針對中國各地飼養野生動物場所、農(集)貿易市場、超市、餐飲店、電商平台等場所,即日起暫時「嚴禁野生動物對外擴散與轉運販賣及任何形式的交易活動」,直到「二○一九新型冠狀病毒」(2019-nCoV)肺炎(簡稱武漢肺炎)的全國疫情解除。地方當局也將加強檢查,加以停業整頓、查封,將犯嫌移送公安機關。

中國科學院武漢病毒研究所與若干頂尖大學的十九位知名研究人員,早已呼籲中國政府取締被視為疫情爆發中心的武漢華南海鮮批發市場之類的野生動物市場,但鑽法律漏洞的野生動物非法交易仍盛行,增加疫情爆發的可能性。《華盛頓郵報》指出,中國未能從十七年前爆發的嚴重急性呼吸道症候群(SARS)學到教訓,即野生動物交易市場是動物傳人疾病的一大溫床。

 

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

【其他文章推薦】

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

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

對於計算機相關專業我們在迷茫什麼

計算機相關專業初識–對於計算機相關專業我們在迷茫什麼

前言

由於種種原因,迫使我寫下這篇博客,我相信,初入計算機相關專業的萌新肯定很迷茫,我該學什麼,我該如何去學,我該如何學好等等問題纏繞心頭。有很多學弟學妹問我該如何去學計算機相關專業,作為過來人,我決定將我的所知所得寫下來,讓初入計算機相關專業的萌新的學習之路走得更順暢一些。

一、什麼是計算機

對於剛學習計算機相關專業的萌新來說,了解一下計算機的工作原理是十分必要的,但是在這裏我們不過多闡述,讓大家簡單了解一下就好。

讓我們先來看一下對於計算機名詞的解釋:

計算機(computer)俗稱電腦,是現代一種用於高速計算的电子計算機器,可以進行數值計算,又可以進行邏輯計算,還具有存儲記憶功能。是能夠按照程序運行,自動、高速處理海量數據的現代化智能电子設備。

划重點:

  • 我們注意到,計算機就是一種用於進行數值計算的現代化智能电子設備。需要理解的是為什麼是進行數值計算,在這裏,你會疑惑,為什麼是數值計算呢,我輸入的明明不是数字呀?這個問題很容易解釋清楚,因為計算機只是一種电子設備,它不具有人類獨立思考和不斷學習的能力,它的所有功能都是事先設定好的,所以當計算機面對輸入字符的時候,會將它統一按照ASCII(計算機編碼系統)規則轉換為數值“0”和“1”(二進制數值),所以,在計算機里,數據存儲都是用“0”和“1”(即二進制數值)來實現。

  • 還有一點值得注意,按照程序運行,那麼問題來了,程序是什麼?程序就是一組計算機能識別和執行的指令, 它以某些程序設計語言編寫,運行於某種目標結構體繫上 。舉個例子,程序就像是用英語(程序設計語言,例如c,c++)寫的文章,要讓一個懂的英語的人(編譯器,如C的編譯器gcc,這裏要注意編譯器和IDE的區別,通常IDE包含編譯器)同時也會閱讀這篇文章的人(結構體系)來閱讀、理解、標記這篇文章。

有學妹問過我,為什麼簡單的代碼,能實現豐富的效果。其實這取決於編譯器的強大能力。下面來簡單介紹一下,編輯器,編譯器,IDE(集成開發環境)的區別。

  • 編輯器:編輯器就是用來編輯的軟件,比如windows自帶的記事本就是一個編輯器, 記事本沒有語法高亮,不显示行號,當一段可執行代碼寫完后無法通過內置環境執行,必須手動輸入命令執行編譯等等一些弊端,所以很少有程序員會用記事本去寫代碼 , 寫代碼比較好用的編輯器軟件有vscode,vim,sublime,notepad++,emacs,atom等等 ,雖然編輯器原始功能不足,但是開發人員為了使編輯器更加友好,所以有很多內置插件可供使用,完全可以手動打造一個IDE。
  • 編譯器:簡單來說,編譯器就是將“一種語言(一般為高級語言,如c,c++,java,python等,計算機不可直接識別和執行)”翻譯為“另一種語言(一般為低級語言,低級語言即機器語言,機器語言是用二進制代碼錶示的計算機能直接識別和執行的一種機器指令的集合)”的程序。舉個例子,用Dev-C++寫好一段可執行"hello,world!"C語言代碼之後,我們要讓它在屏幕打印出來我們想要它輸出的"hello,world!",就需要通過gcc編譯器執行編譯后才能显示。其他語言同理。
  • IDE:集成開發環境,用於程序開發環境的應用程序,一般包含代碼編輯器編譯器調試器圖像用戶界面等工具。集成了代碼編寫程序分析程序編譯程序調試等功能。如 jetbrains 的用於Java開發的 IntelliJ IDEA 、用於JavaScript開發的WebStorm、用於Python開發Pycharm,微軟的 Visual Studio系列 ,IBM的Eclipse。

二、我們該學什麼

很多初入計算機相關專業的萌新,總是很迷茫,不知道自己該學什麼,通常是他們知道如何去學好學校開設的每一門課程,就是不知道自己該向哪些方向學習,這些方向指的是專業技能和就業方向,諸如web開發、Android/IOS開發、數據分析、人工智能、網絡安全、遊戲開發、軟件測試等等。有這種疑惑很正常,迷茫也是正常的,但我們總要讓自己了解自己所需,然後腳踏實地,一步一步去充實自己的能力。而我想做的也很簡單,就是幫助大家解除心裏的疑惑。那麼,我們開始進入正題。

1. 我們該如何選擇適合自己的方向

對於這個問題,其實是很難回答清楚的,因為每個人的興趣都不相同,所以就很難去站在自己的角度去回答疑問者的問題。但是,原理都是想通的,我相信我的經驗會幫助到你們。

  • 通常,學校每學期都會開設一門或多門語言(程序設計語言,下文同),那麼,喜歡一門語言,首先要愛上它的語言風格,諸如Java的嚴謹,Python的自由,總有一款適合你;其次,在學習語言的過程中,一定要了解它能幹什麼,市場環境如何,工作崗位多少等綜合因素,再決定要不要去深入這門語言,並且主攻自己感興趣的那個方向。

  • 對於學校沒有開設,但是自己又想學習的語言而言,該如何去選擇。首先,學校開設的語言基本是市場比較流行的語言,也符合市場需求,所以,完全可以在學校開設的語言中去選擇自己想要了解並學習的語言。此外,我們可以藉助 TIOBE ( TIOBE 編程社區指數是編程語言流行度的指標,該榜單每月更新一次,指數基於全球技術工程師、課程和第三方供應商的數量。包括流行的搜索引擎,如谷歌、必應、雅虎、維基百科、亞馬遜、YouTube 和百度都用於指數計算。 )去了解語言的流行程度,流行程度決定市場需求,以此來參考自己想要了解並學習的語言,在此附上2019年11月語言排名。

2. 主流編程語言主要應用場景

  • Java

    1. 企業級應用開發: 大到全國聯網的系統,小到中小企業的應用解決方案,Java都佔有極為重要的地位 。
    2. web後端開發: JSP+Servlet+JavaBean 是一種比較流行的開發模式。
    3. 移動領域:手機遊戲。
    4. Android App開發: android 開發只用到了JAVA的語法和JAVA SE的一小部分API。
  • C

    C語言是一門基礎語言,是其他一些語言的基礎,例如MATLAB,Object-C,Lua等.同時也是學習來比較難的語言,達到精通的程度沒有3-10年左右很難,C語言沒有比較完善的開發框架,是面向過程的一門語言,講究算法跟邏輯。

    1. 科研
    2. 服務器: 網絡核心設備,如路由器、交換機、防火牆。
    3. 操作系統:類unix系統(Linux/freebsd)
    4. 嵌入式開發: 在一個特定的硬件環境上開發與構建特定的可編程軟件系統的綜合技術。
    5. 自動化控制
  • Python

    1. 圖形處理
    2. 數學處理
    3. 文本處理
    4. 數據庫編程
    5. 網絡編程
    6. 多媒體應用
    7. pymo引擎: 運行於Symbian S60V3,Symbian S60V5,Symbian 3,Android,Windows,Linux,Mac Os,Maemo,MeeGo系統上的AVG遊戲引擎。
    8. 黑客編程
    9. 網絡安全
  • C++

    1. 遊戲開發
    2. 科學計算
    3. 網絡軟件
    4. 操作系統
    5. 設備驅動程序
    6. 移動設備
    7. 嵌入式開發
    8. 科研
    9. 編譯器
  • C#

    1. web後端開發
    2. 桌面軟件開發
    3. 人工智能
    4. 遊戲開發
  • JavaScript
    唯一能用於前後端開發的語言web前端開發
    1. web前端開發
    2. node web後端開發
    3. 操作系統
    4. 後台
    5. 桌面軟件開發
    6. 混合App
    7. 小程序
  • PHP

    1. web後端開發
    2. 桌面軟件開發
    3. 命令行腳本
  • SQL

    1. 操作數據庫
  • Swift

    1. 蘋果生態系統應用開發
  • Ruby

    1. web開發
  • R

    數據科學闖天下,左手Python右手R

    1. 機器學習
    2. 數據分析
    3. 科學計算
  • Go

    1. web後端開發
    2. 高性能服務器應用

3. 主流編程語言學習路徑(將持續更新,僅供參考)

  • JavaScript

4. 主流編程語言入門學習書籍推薦

語言 書籍
C 《嗨翻C語言》
C++ 《C++權威教程》
Java 《Java輕鬆學》
Python 《Python編程從入門到實戰》
JavaScript 《JavaScript入門經典》
PHP 《PHP編程實戰》
SQL 《SQL基礎教程》
Swift 《Swift編程權威指南》
Ruby 《Ruby從入門到精通》
R 《R語言實戰》
Go 《Go語言聖經》

5. 編程學習網站推薦

網站 網址
菜鳥教程
W3School
實驗樓
猿學
慕課網
SegmentFault
博客園
GitHub
掘金
學習數據科學
易百教程
看雲

三、總結

通篇寫完,感覺自己也重新學到了很多,學習就是一個反覆複習的過程,每次學習都能帶給自己不一樣的收穫。希望以上內容可以給初入計算機相關專業的萌新帶來一些幫助,後面我會不斷更新和優化本文,請大家持續關注。

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

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

【自然語言處理】利用LDA對希拉里郵件進行主題分析

首先是讀取數據集,並將csv中ExtractedBodyText為空的給去除掉

import pandas as pd
import re
import os

dir_path=os.path.dirname(os.path.abspath(__file__))
data_path=dir_path+"/Database/HillaryEmails.csv"
df=pd.read_csv(data_path)
df=df[['Id','ExtractedBodyText']].dropna()

對於這些郵件信息,並不是所有的詞都是有意義的,也就是先要去除掉一些噪聲數據:

def clean_email_text(text):
    text = text.replace('\n'," ") #新行,我們是不需要的
    text = re.sub(r"-", " ", text) #把 "-" 的兩個單詞,分開。(比如:july-edu ==> july edu)
    text = re.sub(r"\d+/\d+/\d+", "", text) #日期,對主體模型沒什麼意義
    text = re.sub(r"[0-2]?[0-9]:[0-6][0-9]", "", text) #時間,沒意義
    text = re.sub(r"[\w]+@[\.\w]+", "", text) #郵件地址,沒意義
    text = re.sub(r"/[a-zA-Z]*[:\//\]*[A-Za-z0-9\-_]+\.+[A-Za-z0-9\.\/%&=\?\-_]+/i", "", text) #網址,沒意義
    pure_text = ''
    # 以防還有其他特殊字符(数字)等等,我們直接把他們loop一遍,過濾掉
    for letter in text:
        # 只留下字母和空格
        if letter.isalpha() or letter==' ':
            pure_text += letter
    # 再把那些去除特殊字符后落單的單詞,直接排除。
    # 我們就只剩下有意義的單詞了。
    text = ' '.join(word for word in pure_text.split() if len(word)>1)
    return text

然後取出ExtractedBodyText的那一列,對每一行email進行噪聲過濾,並返回一個對象:

docs = df['ExtractedBodyText']
docs = docs.apply(lambda s: clean_email_text(s))  

然後我們呢把裏面的email提取出來:

doclist=docs.values

接下來,我們使用gensim庫來進行LDA模型的構建,gensim可用指令pip install -U gensim安裝。但是,要注意輸入到模型中的數據的格式。例如:[[一條郵件字符串],[另一條郵件字符串], ...]轉換成[[一,條,郵件,在,這裏],[第,二,條,郵件,在,這裏],[今天,天氣,腫么,樣],...]。對於英文的分詞,只需要對空白處分割即可。同時,有些詞語(不同於噪聲)是沒有意義的,我們要過濾掉那些沒有意義的詞語,這裏簡單的寫一個停止詞列表:

stoplist = ['very', 'ourselves', 'am', 'doesn', 'through', 'me', 'against', 'up', 'just', 'her', 'ours',
            'couldn', 'because', 'is', 'isn', 'it', 'only', 'in', 'such', 'too', 'mustn', 'under', 'their',
            'if', 'to', 'my', 'himself', 'after', 'why', 'while', 'can', 'each', 'itself', 'his', 'all', 'once',
            'herself', 'more', 'our', 'they', 'hasn', 'on', 'ma', 'them', 'its', 'where', 'did', 'll', 'you',
            'didn', 'nor', 'as', 'now', 'before', 'those', 'yours', 'from', 'who', 'was', 'm', 'been', 'will',
            'into', 'same', 'how', 'some', 'of', 'out', 'with', 's', 'being', 't', 'mightn', 'she', 'again', 'be',
            'by', 'shan', 'have', 'yourselves', 'needn', 'and', 'are', 'o', 'these', 'further', 'most', 'yourself',
            'having', 'aren', 'here', 'he', 'were', 'but', 'this', 'myself', 'own', 'we', 'so', 'i', 'does', 'both',
            'when', 'between', 'd', 'had', 'the', 'y', 'has', 'down', 'off', 'than', 'haven', 'whom', 'wouldn',
            'should', 've', 'over', 'themselves', 'few', 'then', 'hadn', 'what', 'until', 'won', 'no', 'about',
            'any', 'that', 'for', 'shouldn', 'don', 'do', 'there', 'doing', 'an', 'or', 'ain', 'hers', 'wasn',
            'weren', 'above', 'a', 'at', 'your', 'theirs', 'below', 'other', 'not', 're', 'him', 'during', 'which']

然後我們將輸入轉換成gensim所需的格式,並過濾掉停用詞:

texts = [[word for word in doc.lower().split() if word not in stoplist] for doc in doclist]

再將這所有的單詞放入到一個詞袋中,把每個單詞用一個数字index指代:

from gensim import corpora, models, similarities
import gensim
dictionary = corpora.Dictionary(texts)

再分別統計每一篇email中每個詞語在這個詞袋中出現的次數,並返回一個列表:

corpus = [dictionary.doc2bow(text) for text in texts]

 這個列表告訴我們,第14(從0開始是第一)個郵件中,一共6個有意義的單詞(經過我們的文本預處理,並去除了停止詞后)其中,51號單詞出現1次,505號單詞出現1次,以此類推。。。

最後,就可以開始構建我們的模型了:

lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20)
print(lda.print_topic(10, topn=5))

 可以看到,第11個主題最常用的單詞,接下來,我們看下所有的主題:

for i in lda.print_topics(num_topics=20, num_words=5):
    print(i)

 我們再看下第一篇email屬於哪一個主題:

print(lda.get_document_topics(corpus[0]))

 屬於第四個主題的概率是0.95

相關代碼和數據:鏈接: https://pan.baidu.com/s/1sl1I5IeQFDHjVwf2a0C89g 提取碼: xqqf 

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

【其他文章推薦】

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

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

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

南投搬家前需注意的眉眉角角,別等搬了再說!

SQlALchemy session詳解

系列文章:

概念

session用於創建程序和數據庫之間的會話,所有對象的載入和保存都需通過session對象 。

通過sessionmaker調用創建一個工廠,並關聯Engine以確保每個session都可以使用該Engine連接資源:

from sqlalchemy.orm import sessionmaker

# 創建session
DbSession = sessionmaker(bind=engine)
session = DbSession()

操作

session的常見操作方法包括:

  1. flush:預提交,提交到數據庫文件,還未寫入數據庫文件中
  2. commit:提交了一個事務,把內存的數據直接寫入數據庫
  3. rollback:回滾
  4. close:關閉

在事務處理時,需注意一下兩點:

  1. 在事務處理過程發生異常時,進行rollback操作,否則會在下次操作時報錯:
Can’t reconnect until invalid transaction is rolled back 
  1. 一般情況下,在一個事務處理完成之後要關閉session,以確保數據操作的準確性。

建議封裝上下文方法:

from contextlib import contextmanager

@contextmanager
def session_maker(session=session):
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

調用:

def update_user():
    with session_maker() as db_session:
        db_session.query(Users).filter_by(name='test2').update({'email': 'test2@qq.com'})

線程安全

session不是線程安全的,並且我們一般session對象都是全局的,那麼在多線程情況下,當多個線程共享一個session時,數據處理就會發生錯誤。

為了保證線程安全,需使用scoped_session方法:

db_session = scoped_session(sessionmaker(bind=engine))

內部原理

session對象包含了三個重要的部分:

  1. 標識映射(Identity Map)
  2. 對象的狀態 / 狀態跟蹤
  3. 事務

標識映射

標識映射是與ORM關聯的集合,通過標識映射保證了數據庫操作的準確性。

具體的實現原理是:維護一個Python字典(IdentityMap),關聯這個Session對象到數據庫ID的映射,當應用程序想要獲取一個session對象時,若該對象不存在,標識映射會加載該對象並緩存,若該對象已存在,則直接獲取。這樣的好處是:

  1. 已經被請求過的session對象緩存下來,不需要連接加載多次,造成額外的開銷;
  2. 避免了數據不一致

狀態跟蹤

一個Session對象從創建到銷毀,依次經歷四種狀態,分別是:

  1. Transient:剛new出來的對象,還不在會話中,也沒有保存到數據庫。
  2. Pending:transient的對象調用add后,就會變成pending狀態,這時會加入sqlalchemy的監管範圍,數據並未更新到數據庫。
  3. Persistent:該狀態表明數據庫里已經記錄了該對象,在兩種情況下對象處於該狀態:一是通過flush()方法刷新pending對象,二是從數據庫query()得到對象。
  4. Detached:在會話中的事務提交之後,所有的對象都將是Detached狀態。

所謂的狀態跟蹤,就是跟蹤以上四個狀態,保證數據的準確性並在合理的時機丟棄對象以保證合理開銷,那麼具體是怎麼實現的呢?

我們可以看到,只有在pending狀態時,對象的內存數據和數據庫中的數據不一致,在Persistent狀態時,內存數據和數據庫數據已經一致,那麼此後任意時刻丟棄該對象數據都是可以的,這時就需要找個合適的時機丟棄對象,過早或過晚都有其缺陷。於是,就讓垃圾回收器來做決定,在內存不夠的時候釋放對象,回收內存。

Session對象採用了弱引用機制,所謂弱引用,就是說,在保存了對象的引用的情況下,對象仍然可能被垃圾回收器回收。在某一時刻通過引用訪問對象時,對象可能存在也可能不存在,如果對象不存在,就重新從數據庫中加載對象。而如果不希望對象被回收,只需要另外保存一個對象的強引用即可 。

session對象包括三個屬性:

  1. new:剛加入會話的對象
  2. dirty:剛被修改的對象
  3. deleted:在會話中被刪除的對象

三個屬性共同的特點就是內存的數據和數據庫數據不一致,也就是對象處於pending狀態,這也就表明了session保存了所有對象處於pending狀態的強引用。

以上。

代碼可參照:

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

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

從演奏家的新年大膽願望 一窺日本都市蜂害問題

文:宋瑞文

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

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

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