Environment 環境空間
空環境空間(empty environment): 最頂層
全域環境空間(global environment)
- 也稱為 user workspace
new.env(): 建立一個新的 R 環境空間:
my.new.env <- new.env()
my.new.env[["name"]] <- "G.T.Wang"
my.new.env$foo <- c(1, 3, 5)
assign(): 指定變數值的 assign 函數也可以使用 envir 參數來指定變數的環境空間:
assign(
"bar",
c(TRUE, FALSE, NA),
my.new.env
)
View(my.new.env)
Examples
f <- function() "top level function"
##-- all three give the same:
environment()
environment(f)
.GlobalEnv
ls(envir = environment(stats::approxfun(1:2, 1:2, method = "const")))
is.environment(.GlobalEnv) # TRUE
e1 <- new.env(parent = baseenv()) # this one has enclosure package:base.
e2 <- new.env(parent = e1)
assign("a", 3, envir = e1)
ls(e1)
ls(e2)
exists("a", envir = e2) # this succeeds by inheritance
exists("a", envir = e2, inherits = FALSE)
exists("+", envir = e2) # this succeeds by inheritance
eh <- new.env(hash = TRUE, size = NA)
with(env.profile(eh), stopifnot(size == length(counts)))
在 R 中
- 所有的變數都是儲存在特定的環境空間(environments)中
- 而環境空間本身其實也是一種變數,可以當成一般變數使用, 例如
- 指定新的值、或是當成參數傳遞至函數中
- 性質跟列表(list)比較相近,甚至可以直接將列表變數轉換為環境空間變數,反之亦可。
- 而環境空間本身其實也是一種變數,可以當成一般變數使用, 例如
- 所有的變數都是儲存在特定的環境空間(environments)中
通常我們在使用 R 的時候,不太需要去理會環境空間的問題
- 當我們在 R 的命令列建立一個變數時,R 會自動將該變數儲存在全域環境空間(global environment,這個空間也稱為 user workspace)中,
- 另外當我們呼叫一個函數時,R 也會自動建立一個隸屬於該函數的環境空間來儲存與該函數相關的變數,
理解變數以及環境空間的運作,可以幫助程式設計師更清楚 R 變數命名空間規則,以及程式除錯時的呼叫堆疊問題(call stack)。
new.env(): 建立一個新的 R 環境空間:
my.new.env <- new.env()
- 環境空間的操作方式跟列表變數相同
- 使用雙中括號或是錢字號的方式來在此環境空間中建立新的變數:
my.new.env[["name"]] <- "G.T.Wang"
my.new.env$foo <- c(1, 3, 5)
assign(): 用來指定變數值的 assign 函數也可以使用 envir 參數來指定變數的環境空間:
assign(
"bar",
c(TRUE, FALSE, NA),
my.new.env
)
取出特定環境空間中的變數,跟列表的操作類似:
my.new.env[["name"]]
# [1] "G.T.Wang"
my.new.env$foo
# [1] 1 3 5
get(): 也可以使用 get 函數:
get("bar", my.new.env)
ls 與 ls.str 函數也有提供使用者指定環境空間的功能:
ls(envir = my.new.env)
# [1] "bar" "foo" "name"
ls.str(envir = my.new.env)
# bar : logi [1:3] TRUE FALSE NA
# foo : num [1:3] 1 3 5
# name : chr "G.T.Wang"
exists(): 檢查特定的變數是否存在,可以使用 exists 函數:
exists("foo", my.new.env)
# [1] TRUE
環境空間與列表之間若要互相轉換,可以使用
as.list 與
as.environment 函數來處理:
my.list <- as.list(my.new.env)
my.list
# $name
# [1] "G.T.Wang"
# $foo
# [1] 1 3 5
# $bar
# [1] TRUE FALSE NA
as.environment(my.list)
# <environment: 0x7fe9f2dd6a38>
list2env 也可以將列表轉為環境空間:
list2env(my.list)
# <environment: 0x7fe9f2dd6a38>
- 在 R 中所有的環境空間都有繼承的關係,也就是說除了
- 最頂層的空環境空間(empty environment)之外,
- 任何一個環境空間都會有一個母環境空間(parent environment),
- 在預設的狀況下,exists 與 get 函數除了檢查目前的環境空間之外,也會一併檢查所有的母環境空間,
- 如果要讓它只檢查目前的環境空間,可以加入 inherits = FALSE 參數:
child.env <- new.env(parent = my.new.env)
exists("name", child.env)
# [1] TRUE
exists("name", child.env, inherits = FALSE)
# [1] FALSE
globalenv(): 我們在 R 命令列中所建立的任何變數預設都會被儲存於 global 這個環境空間中,若要取得 global 環境空間可以使用 globalenv 這個函數:
globalenv()
# <environment: R_GlobalEnv>
# 或是直接取用 .GlobalEnv 這個變數也可以:
.GlobalEnv
# <environment: R_GlobalEnv>
baseenv()
- 另外一個比較特別的環境空間是 base
- R 中最基本的一個環境空間
- 使用 baseenv() 來取得之:
- 儲存了很多 R 的基礎函數與運算子
- 使用 baseenv() 來取得之:
- R 中最基本的一個環境空間
- 另外一個比較特別的環境空間是 base
baseenv()
# <environment: base>
head(ls(envir = baseenv()), 20)
# [1] "-" "-.Date" "-.POSIXt" ":"
# [5] "::" ":::" "!" "!.hexmode"
# [9] "!.octmode" "!=" "(" "["
# [13] "[.AsIs" "[.data.frame" "[.Date" "[.difftime"
# [17] "[.Dlist" "[.factor" "[.hexmode" "[.listof"
parent.env()
- 這個函數可以用來取得指定環境空間的母環境空間:
parent.env(globalenv())
# <environment: 0x7fa52d118720>
# attr(,"name")
# [1] "tools:RGUI"
在 R 中會遇到環境空間的狀況主要有兩種
- 呼叫函數時
- 每個函數會有自己專屬的環境空間(也稱為 closure),
- 載入各種 R 套件時
- 套件內的函數都會放在套件自己的環境空間中
- 呼叫函數時
- 透過搜尋路徑的方式來讓使用者取得套件內的各種函數,這些狀況會在之後的教學中詳細說明。