Глобальные и локальные переменные в R
Я новичок в R, и я довольно запутался в использовании локальных и глобальных переменных в R.
Я прочитал несколько сообщений в Интернете, которые говорят, что если я использую =
или <-
, я назначу переменную в текущей среде, а с помощью <<-
я могу получить доступ к глобальной переменной, когда внутри функции.
Однако, как я помню, в С++ локальные переменные возникают всякий раз, когда вы объявляете переменную внутри скобок {}
, поэтому мне интересно, так ли это для R? Или это просто для функций из R, что мы имеем понятие локальных переменных.
Я сделал небольшой эксперимент, который, по-видимому, предполагает, что только скобок недостаточно, я получаю что-то неправильно?
{
x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
Ответы
Ответ 1
Переменные, объявленные внутри функции, являются локальными для этой функции. Например:
foo <- function() {
bar <- 1
}
foo()
bar
дает следующую ошибку: Error: object 'bar' not found
.
Если вы хотите сделать bar
глобальную переменную, вы должны сделать:
foo <- function() {
bar <<- 1
}
foo()
bar
В этом случае bar
доступен извне функции.
Однако, в отличие от C, С++ или многих других языков, скобки не определяют область переменных. Например, в следующем фрагменте кода:
if (x > 10) {
y <- 0
}
else {
y <- 1
}
y
остается доступным после оператора if-else
.
Как вы говорите, вы также можете создавать вложенные среды. Вы можете взглянуть на эти две ссылки, чтобы понять, как их использовать:
Здесь у вас есть небольшой пример:
test.env <- new.env()
assign('var', 100, envir=test.env)
# or simply
test.env$var <- 100
get('var') # var cannot be found since it is not defined in this environment
get('var', envir=test.env) # now it can be found
Ответ 2
<-
выполняет назначение в текущей среде.
Когда вы находитесь внутри функции R, создается новая среда для вас. По умолчанию он включает все из среды, в которой он был создан, чтобы вы могли использовать эти переменные, но все новое, что вы создаете, не будет записано в глобальную среду.
В большинстве случаев <<-
присваивает переменные уже в глобальной среде или создает переменную в глобальной среде, даже если вы находитесь внутри функции. Однако это не так просто. Он выполняет проверку родительской среды для переменной с именем, представляющим интерес. Если он не находит его в родительской среде, он переходит к родительскому принципу родительской среды (во время создания функции) и выглядит там. Он продолжает восходить к глобальной среде, и если он не будет найден в глобальной среде, он назначит переменную в глобальной среде.
Это может показать, что происходит.
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
bar <- "in baz - before <<-"
bar <<- "in baz - after <<-"
print(bar)
}
print(bar)
baz()
print(bar)
}
> bar
[1] "global"
> foo()
[1] "in foo"
[1] "in baz - before <<-"
[1] "in baz - after <<-"
> bar
[1] "global"
В первый раз, когда мы печатаем брусок, мы еще не назвали foo
, но он все равно должен быть глобальным - это имеет смысл. Во второй раз мы печатаем его внутри foo
перед вызовом baz
, поэтому значение "в foo" имеет смысл. Ниже мы видим, что фактически делает <<-
. Следующее значение, напечатанное "baz - before < -", даже если инструкция печати появляется после <<-
. Это связано с тем, что <<-
не выглядит в текущей среде (если вы не находитесь в глобальной среде, в этом случае <<-
действует как <-
). Таким образом, внутри baz
значение bar остается как "в baz - до < < -". Как только мы вызываем baz
, копия строки внутри foo
изменяется на "в baz", но, как мы видим, глобальный bar
не изменяется. Это связано с тем, что копия bar
, которая определена внутри foo
, находится в родительской среде, когда мы создали baz
, так что это первая копия bar
, которую видит <<-
и, следовательно, копия, которую она присваивает, Таким образом, <<-
не просто назначает глобальную среду.
<<-
сложно, и я бы не рекомендовал его использовать, если вы можете его избежать. Если вы действительно хотите назначить глобальную среду, вы можете использовать функцию назначения и явно указать, что вы хотите назначить глобально.
Теперь я изменяю <<-
на оператор присваивания, и мы можем видеть, какой эффект имеет:
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
assign("bar", "in baz", envir = .GlobalEnv)
}
print(bar)
baz()
print(bar)
}
bar
#[1] "global"
foo()
#[1] "in foo"
#[1] "in foo"
bar
#[1] "in baz"
Итак, оба раза мы печатаем строку внутри foo
, значение равно "в foo" даже после вызова baz
. Это связано с тем, что assign
никогда не рассматривал копию bar
внутри foo, потому что мы точно сказали, где искать. Однако на этот раз значение bar в глобальной среде было изменено, потому что мы явно назначили там.
Теперь вы также спросили о создании локальных переменных, и вы можете сделать это довольно легко, не создавая функцию... Нам просто нужно использовать функцию local
.
bar <- "global"
# local will create a new environment for us to play in
local({
bar <- "local"
print(bar)
})
#[1] "local"
bar
#[1] "global"