Terry七月Ruby讀書筆記(比較詳細(xì))第3/4頁
復(fù)雜數(shù)據(jù)類型
1. 數(shù)組
(1) 建立數(shù)組
¨ array_1=[]
¨ array_2=Array.new
¨ array_3=['3 ','4 ','5 ']
(2) 訪問元素
arr=[3,4,5,6,7,8,9]
Ruby以整數(shù)作為下標(biāo),訪問數(shù)組元素通過數(shù)組下標(biāo),數(shù)組下標(biāo)稱作數(shù)組索引比較好一些。
數(shù)組的索引從0開始(arr[0]),一直到數(shù)組的長度減去1,如:arr[arr.length-1]或arr[arr.size-1]);
負(fù)數(shù)表示從數(shù)組末尾開始的索引,如:arr[-1]。
用一對數(shù)字索引數(shù)組,第一個數(shù)字表示起始位置,第二數(shù)字表示從起始位置開始的元素?cái)?shù)目。如:arr[2..4],arr[-3,2]。
arr.first,arr.last分別代表第一個和最后一個元素。
(3) 增刪元素
Ruby的數(shù)組大小是動態(tài)的,你能夠隨時增加、刪除數(shù)組元素。
print arr.join(", "),"\n" 意思是:將數(shù)組 arr轉(zhuǎn)換成字符串輸出,用", "隔開每個
元素,并且換行。
arr=[3,4,5]
print arr #輸出:345
print arr.join(", ") #輸出:3,4,5
(4) 數(shù)組運(yùn)算
arr1=["abc",1,2,"de"]
arr2=[2,3,4,7,6,5]
運(yùn)算 |
運(yùn)算表達(dá)式 |
輸出結(jié)果 |
加 |
print arr1+arr2 |
abc12de234765 |
減 |
print arr2-arr1 |
34765 |
乘 |
print arr1*2 |
abc12deabc12de |
并 |
print arr1|arr2 |
abc12de34765 |
交 |
print arr1&arr2 |
2 |
排序 |
print arr2.sort |
234567 |
倒置 |
print arr1.reverse |
de21abc |
2. 字符串
(1) 生成一個字符串
字符串是 String 類的對象,一般使用字符串值來創(chuàng)建。
%q用來生成單引號字符串;
%Q用來生成雙引號字符串。
%q或者%Q后面跟著的是分隔符,可以是配對的!!;//;<>;();[];{};等等。
字符串文檔,從<<和文檔結(jié)束符的下一行開始,直至一個放置在行首的文檔結(jié)束符結(jié)束。文檔結(jié)束符自己指定,結(jié)束符本身不屬于字符串。
注意:文檔結(jié)束符后面不能跟有空格。
一個數(shù)組可以用join方法轉(zhuǎn)換成字符串,join()內(nèi)的參數(shù)也是一個字符串,用來分隔數(shù)組的每個元素,例如:arr.join(",")。
(2) 字符串操作
字符串既然是String類的對象,String類的方法你都可以使用在字符串變量上。
(3) 字符串轉(zhuǎn)義
雙引號括起來的字符串會有轉(zhuǎn)義,例如:“\n”表示換行。
單引號括起來的字符串不會轉(zhuǎn)義,有一個例外:單引號字符串里的單引號,需要轉(zhuǎn)義。
(4) 字符串內(nèi)嵌表達(dá)式
在雙引號字符串中,不僅可以使用轉(zhuǎn)義符,而且可以在#{ }之中放入Ruby表達(dá)式,使用字符串時,這些表達(dá)式的值被計(jì)算并放入字符串。
字符串內(nèi)嵌表達(dá)式,使得你能夠更加靈活地組織代碼,表現(xiàn)出更強(qiáng)、更多的動態(tài)特性。
3. 代碼塊
可以用大括號{ }將代碼組織成塊,也可以用 do…end 將代碼組織成塊。大括號{ }的優(yōu)先級高于 do…end。代碼塊,簡稱塊。
yield [ji:ld] 產(chǎn)生,輸出……
注意:{}或者do…end之間的是塊。
#E8.4-1.rb def one_block yield yield yield end
|
one_block { puts "This is a block." } |
代碼塊 |
把塊作為參數(shù),帶入到def定義中的yield處即可。
調(diào)用一次塊要用關(guān)鍵字yield。每一次yield,塊就被調(diào)用一次。
yield還可以帶參數(shù)調(diào)用塊,yield后面是實(shí)參,塊定義處是形參。
一個塊可以接收yield傳來的參數(shù),還可以將結(jié)果返回給調(diào)用它的方法。
如果我們還沒有決定在塊里寫什么代碼,或者塊里的代碼會隨著不同的情形而變化,那么就看出代碼塊的靈活性了。
先寫出方法的大致框架,調(diào)用方法的時候才告訴方法要作什么。
4. 迭代器
迭代器是一個與代碼塊有關(guān)聯(lián)的方法。
(1..9).each {|i| print i if i<7}
迭代器 each 是數(shù)組類的一個方法;大括號{ }里的代碼是代碼塊。
class Array def one_by_one for i in 0...size yield(self[i] ) end puts end end
|
arr = [1,3,5,7,9] arr.one_by_one {|k| print k , ", "} # 1, 3, 5, 7, 9, arr.one_by_one {|h| print h*h, ", "} # 1, 9, 25, 49, 81,
|
5. 閉包
代碼塊是一段代碼,相當(dāng)于一個匿名方法,被調(diào)用它的方法所調(diào)用。
如果我們不僅僅想調(diào)用代碼塊,還想把代碼塊作為參數(shù)傳遞給其它方法,就要使用閉包。
閉包也是一段代碼,一個代碼塊,而且能夠共享其它方法的局部變量。
閉包既然是一段代碼,也就有自己的狀態(tài),屬性,作用范圍,也就是一個可以通過變量引用的對象,我們稱之為過程對象。
一個過程對象用 proc 創(chuàng)建,用 call 方法來調(diào)用。
¨ 閉包作為參數(shù)傳遞給其它方法
以下兩個程序相同
程序1 |
程序2 |
def method(pr) puts pr.call(7) end
oneProc=proc{|k| k *=3} method(oneProc) |
oneProc=proc{|k| k *=3}
puts oneProc.call(7) |
#過程對象oneProc作為一個參數(shù),傳遞給method; |
|
¨ 閉包共享其它方法局部變量
def method(n) return proc{|i| n +=i } end
oneProc=method(3) puts oneProc.call(9) #12 puts oneProc.call(5) #17 |
方法method返回一個Proc對象,這個對象引用了函數(shù)的參數(shù)n。即使參數(shù)n在閉包被調(diào)用時已經(jīng)不在自己的作用域里,這個閉包還是可以訪問參數(shù)n,并且和方法method共同擁有變量n。開始時方法method的變量n是3;oneProc.call(9)的時候,oneProc 更新了變量n,把n=12 傳回給方法method;oneProc.call(5)的時候,oneProc取出方法 method 的變量 n=12,更新為n=17,傳回給方法method的同時,也把n=17作為自己的返回值輸出。 |
正則表達(dá)式
正則表達(dá)式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串;將匹配的子串做替換;或者從某個串中取出符合某個條件的子串;等等。
Ruby 中,可以使用構(gòu)造器顯式地創(chuàng)建一個正則表達(dá)式,也可以使用字面值形式 /正則模式/ 來創(chuàng)建一個正則表達(dá)式。
=~ |
匹配一個正則表達(dá)式:用來比較是否符合一個正則表達(dá)式,返回模式在字符串中被匹配到的位置,否則返回nil。 |
!~ |
不匹配一個正則表達(dá)式:用來斷言不符合一個正則表達(dá)式,返回true,flase。 |
一些字符或字符組合在正則表達(dá)式中有特殊的意義。
特別字符 |
描述 |
( ) |
標(biāo)記一個子表達(dá)式的開始和結(jié)束位置。子表達(dá)式可以獲取供以后使用。要匹配這些字符,請使用 \( 和 \)。 |
[] |
范圍描述符 (比如,[a - z] 表示在 a 到 z 范圍內(nèi)的一個字母),要匹配 [,請使用\[。 |
{} |
標(biāo)記限定符表達(dá)式。要匹配{,請使用 \{。 |
\ |
將下一個字符標(biāo)記為或特殊字符、或原義字符、或向后引用、或八進(jìn)制轉(zhuǎn)義符。例如, 'n'匹配字符 'n'。'\n'匹配換行符。序列 '\\'匹配 "\",而 '\('則匹配 "("。 |
| |
指明兩項(xiàng)之間的一個選擇。要匹配 |,請使用 \|。 |
. |
匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。 |
非打印字符
非打印字符 |
描述 |
\f |
匹配一個換頁符。等價(jià)于\x0c。 |
\n |
匹配一個換行符。等價(jià)于\x0a。 |
\r |
匹配一個回車符。等價(jià)于\x0d。 |
\s |
匹配任何空白字符,包括空格、制表符、換頁符等等。等價(jià)于[\f\n\r\t\v]。 |
\S |
匹配任何非空白字符。等價(jià)于[^\f\n\r\t\v]。 |
\t |
匹配一個制表符。等價(jià)于\x09。 |
\w |
匹配包括下劃線的任何單詞字符。等價(jià)于'[A-Za-z0-9_]'字母或數(shù)字;相當(dāng)于[0-9A-Za-z] |
\W |
匹配任何非單詞字符。等價(jià)于'[^A-Za-z0-9_]'非字母,數(shù)字 |
\d |
匹配一個數(shù)字字符。等價(jià)于[0-9]。[0-9]數(shù)字;相當(dāng)于[0-9] |
\D |
匹配一個非數(shù)字字符。等價(jià)于[^0-9]。非數(shù)字字符 |
\b |
退格符(0x08)(僅在范圍描述符內(nèi)部時) |
限定符
限定符用來指定正則表達(dá)式的一個給定組件必須要出現(xiàn)多少次才能滿足匹配。
* 和 + 限定符都是貪婪的,因?yàn)樗鼈儠M可能多的匹配文字,只有在它們的后面加上一個 ? 就可以實(shí)現(xiàn)非貪婪或最小匹配。
限定符 |
描述 |
* |
前面元素出現(xiàn)0或多次。* 等價(jià)于{0,}。 例如,zo*能匹配 "z"以及 "zoo"。 要匹配 * 字符,請使用 \*。 |
+ |
前面元素出現(xiàn)1或多次。+ 等價(jià)于{1,}。 例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。 要匹配 + 字符,請使用 \+。 |
? |
前面元素最多出現(xiàn)1次;相當(dāng)于 {0,1}。 例如,”do(es)?” 可以匹配 “do” 或 “does” 中的"do" 。 要匹配 ? 字符,請使用 \?。 |
{n} |
n 是一個非負(fù)整數(shù)。匹配確定的 n 次。 例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food"中的兩個o。 |
{n,} |
n 是一個非負(fù)整數(shù)。至少匹配n 次。'o{1,}' 等價(jià)于 'o+'。'o{0,}' 則等價(jià)于 'o*'。 例如,'o{2,}' 不能匹配 "Bob"中的 'o',但能匹配 "foooood"中的所有 o。 |
{n,m} |
m 和 n 均為非負(fù)整數(shù),其中n <= m。前面元素最少出現(xiàn)n 次,最多出現(xiàn) m次。 'o{0,1}'等價(jià)于 'o?'。請注意在逗號和兩個數(shù)之間不能有空格。 例如,"o{1,3}"將匹配 "fooooood"中的前三個 o。 |
定位符
用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結(jié)束,\b描述單詞的前或后邊界,\B表示非單詞邊界。不能對定位符使用限定符。
定位符 |
描述 |
^ |
匹配輸入字符串的開始位置,除非在方括號表達(dá)式中使用,此時它表示不接受該字符集合。要匹配^字符本身,請使用\^。 |
$ |
匹配輸入字符串的結(jié)尾位置。如果設(shè)置了RegExp對象的Multiline屬性,則$也匹配'\n'或'\r'。要匹配$字符本身,請使用\$。 |
\b |
匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,'er\b'可以匹配"never"中的'er',但不能匹配"verb"中的'er'。 |
\B |
匹配非單詞邊界。'er\B'能匹配"verb"中的'er',但不能匹配"never"中的'er' |
各種操作符的運(yùn)算優(yōu)先級
相同優(yōu)先級的從左到右進(jìn)行運(yùn)算,不同優(yōu)先級的運(yùn)算先高后低。各種操作符的優(yōu)先級從高到低如下:
優(yōu)先級 |
操作符 |
描述 |
高 |
\ |
轉(zhuǎn)義符 |
|
(),[] |
圓括號和方括號 |
|
*,+,?,{n},{n,},{n,m} |
限定符 |
|
^,$, |
位置和順序 |
低 |
| |
“或”操作 |
元編程
元編程:編寫能夠生成程序的程序。
聽起來很有趣!
Ruby語言強(qiáng)大的動態(tài)特征,賦予了我們靈活地進(jìn)行元編程的能力。
Ruby語言的訪問控制是動態(tài)的,是在程序運(yùn)行時刻確立的。
你可以根據(jù)自己的需要,在程序的不同位置,改變某個方法的訪問控制級別,讓你的程序更加富于變化。
page 79
模塊化程序設(shè)計(jì)
1. 模塊
在程序中,相關(guān)的、不相關(guān)的代碼的組合,叫作模塊。一般情況下,我們總是把功能相關(guān)的代碼放在一個模塊里。
把功能相關(guān)的程序代碼放在一個模塊里,體現(xiàn)了模塊的第一個作用:可以被其它程序代碼重復(fù)使用。
Ruby標(biāo)準(zhǔn)包里的 Math 模塊提供了許多方法
模塊名.方法名(參數(shù)) |
Math 模塊還提供了兩個常量,圓周率π 和自然對數(shù)底 e,
模塊名::常量名 |
定義模塊用 module...end 。模塊與類非常相似,但是:
A) 模塊不可以有實(shí)例對象;
B) 模塊不可以有子類。
2. 命名空間
模塊的第二個作用:提供了一個命名空間(namespace),防止命名沖突。
include 模塊名
定義一個模塊方法,在方法名前加上模塊名和一個點(diǎn)號“.”。
調(diào)用一個模塊方法,與定義模塊方法一樣,要在方法名前加上模塊名和一個點(diǎn)號“.”。模塊方法提供了一個途徑,在模塊的外部訪問模塊內(nèi)部方法,無須 include模塊。定義模塊常量不需要如此。
3. 糅和(Mix-in)與多重繼承
柔和/混合插入/Mix-in
Ruby是單繼承,通過Mix-in模塊,實(shí)現(xiàn)多重繼承的優(yōu)點(diǎn)。
模塊的第三個作用:實(shí)現(xiàn)了類似多重繼承的功能。
通過“<父類名”,一個子類可以得到父類的屬性和方法;
通過“include模塊名”,一個子類可以得到某個模塊的常量和方法。
類不能被include。
include方法為一個類的所有對象包含某個模塊;
extend方法為一個類的某個對象包含某個模塊(聯(lián)系單例方法)。
4. require和load
require方法包含另一個文件,另一個文件名需要是一個字符串。
load方法與require方法相對應(yīng),也用來包含另一個文件。
require包含文件,只加載一次,遇到同一文件時自動忽略;不同路徑下的同名文件會多次加載。
load包含文件,加載多次,即使是相同路徑下同一文件。
總結(jié)一下:
require,load |
包含文件 |
include,extend |
包含模塊 |
require |
加載文件一次 |
加載文件時可以不加后綴名 |
一般情況下用于加載庫文件 |
load |
加載文件多次 |
加載文件時必須加后綴名 |
用于加載配置文件 |
利用load多次加載文件的特性,可以用來實(shí)現(xiàn)程序的無縫升級和系統(tǒng)的熱部署。程序功能改變了,你只需要重新load一次,其它代碼與它再次交互的時候,這個程序?qū)嶋H上已經(jīng)不是原來的程序了。
page 88
相關(guān)文章
Ruby的面向?qū)ο蠓绞骄幊虒W(xué)習(xí)雜記
Ruby是具有面向?qū)ο筇匦缘木幊陶Z言,這里整理了一些Ruby的面向?qū)ο蠓绞骄幊虒W(xué)習(xí)雜記,包括類與方法等基本的面向?qū)ο笠氐闹R,需要的朋友可以參考下2016-05-05mac os gem安裝json出現(xiàn)error failed的解決辦法
這篇文章主要介紹了mac os gem安裝json出現(xiàn)error failed的解決辦法,系統(tǒng)是mac os Mavericks,失敗提示Failed to build gem native extension,需要的朋友可以參考下2014-06-06Ruby on rails安裝后去掉DL is deprecated,please use Fiddle警告信息的方法【
這篇文章主要介紹了Ruby on rails安裝后去掉DL is deprecated,please use Fiddle警告信息的方法,通過針對Ruby on rails安裝文件中的警告部分源碼進(jìn)行注釋來達(dá)到消除警告的目的,需要的朋友可以參考下2017-02-02Ruby 中$開頭的全局變量、內(nèi)部變量、隱藏變量介紹
這篇文章主要介紹了Ruby 中$開頭的全局變量、內(nèi)部變量、隱藏變量介紹,需要的朋友可以參考下2014-04-04