ruby的動態性 eval 家族

2021-08-26 22:51:38 字數 1969 閱讀 7567

eval

將字串作為**來求值,最直接,也是最危險的方法。

編寫乙個讓別人在執行時鍵入方法名的方法:

print "method name:"

m = gets.chomp

eval("def #; puts 'hi!'; end")

eval(m)

如果在執行時,輸入abc,那麼eval求值的字串是:

def abc

puts 'hi!'

endeval的危險性

eval很強大,但是它也潛在著危險,這個有點像sql注入

假如,上面我們輸入的不是hi而是下面的內容

hi; end; system("rm -rf /*"); #

eval求值以後是這樣的

def hi; end; system("rm -rf /*"); # puts 'hello'; end

求值的結果是:#後面的所有內容會被作為注釋忽略掉。使用system命令試圖刪除系統所有檔案

ruby有乙個全域性變數$safe(取值範圍是0到4)、以獲取對如非法寫檔案這一類危險的防護。

instance_eval

該方法是將self變為instance_eval呼叫的接收者,對字串或**塊進行求值。

p self

a =

a.instance_eval

輸出結果:

main

instance_eval常常於用訪問物件的私有資料(特別是例項變數)。

class c

def initialize

@x = 1

endend

c = c.new

c.instance_eval

class_eval

從本質上f講,class_eval(即model_eval)可進入類定義體中:

c = class.new

c.class_eval do

def some_method

puts "created in class_eval"

endend

c = c.new

c.some_method

class_eval還可以做一些class關鍵字不能做的事:

*在類定義的上下文中對字串求值

*為匿名類(不包單例類)開啟類定義

*獲取外圍作用域中變數的訪問權

用class關鍵字開啟乙個類時,就開啟了乙個新的區域性變數作用域。但是,使用class_eval的**塊,可以看到外圍使用域中的變數。

>> var = "initialize variable"

=> "initialized variable"

>> class c

>> puts var

>> end

nameerror: undefined local variable or method 'var' for c:class

from (irb):3

>>c.class_eval

initialized variable

var在標準的類定義體的作用域之外,但是在傳遞給class_eval的**塊的作用域之內。

當在class_eval的塊中定義乙個例項方法時,又有所不同:

>> c.class_eval

=> nil

>>c.new.talk

nameerror: undefined local variable or method 'var' for #

和任何def一樣,在**塊中的def開啟了乙個新的作用域,所以變數var不能訪問了。

如果想要把外部作用域的變數硬塞到例項方法中,可以使用define_method方法。

>>c.class_eval }

>>c.new.talk

initialized variable

define_method是module類的例項方法,所以module或class的任意例項都可以呼叫該方法。

ruby的動態性

記住 ruby的動態特性是以self身份的轉換為基礎的。單例類先來看看什麼是單例類。大多數ruby程式中發生的都涉及包含例項方法定義的類和模組 class c def talk puts hi endend 使用下面的方法例項化和例項方法呼叫 c c.new c.talk 還可以直接給單個物件新增方...

Ruby中的繫結和eval

ruby是一種指令碼語言,他的每一步執行都需要乙個上下文環境,我們知道ruby的頂層環境就是main作為self,ruby的eval可以把傳入的字串當作指令碼 來解釋執行,這裡同樣需要乙個作用域。我們來看乙個實驗 irbname tony eval p name tony def test name...

奇異的家族 動態規劃

有一種奇怪的大家族,這種家族裡的人要麼沒有孩子,要麼就有兩個孩子。已知某個這種家族共有n個人,家族中共有k代人。你能告訴我這樣的乙個家族可能的家譜結構的種數除以9901的餘數是多少嗎?輸入包括一行,包括兩個被空格分開的整數,第乙個為家族中的人數n 3 n 200 第二個為家族中的代數k 1 k 10...