Глобальні та локальні змінні в R


126

Я новачок для R, і я дуже плутаю використання локальних та глобальних змінних у Р.

Я читав деякі повідомлення в Інтернеті , які говорять , що , якщо я використовую =або <-я присвоїть змінній в поточній середовищі, і <<-я можу отримати доступ до глобальної змінної , коли всередині функції.

Однак, як я пам’ятаю, у C ++ локальні змінні виникають щоразу, коли ви оголошуєте змінну всередині дужок {}, тож мені цікаво, чи це однаково для R? Або тільки для функцій в R ми маємо поняття локальних змінних.

Я зробив невеликий експеримент, який, здається, підказує, що лише дужок недостатньо, чи я щось помиляюсь?

{
   x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4

На додаток до цих відповідей є якийсь код: globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env……
ізоморфізми

@isomorphismes , Error: could not find function "%>%". Це ще одна форма доручення?
Аарон Макдейд

1
Відповідна нитка в R-help: Що означає оператор "<< -"? .
Генрік

1
@AaronMcDaid Привіт, вибачте за те, що не відповів раніше! Це від require(magrittr). Це спосіб застосування функцій праворуч ( x | f1 | f2 | f3), а не зліва ( f3( f2( f1( x ) ) )).
ізоморфізми

Відповіді:


153

Змінні, оголошені всередині функції, локальні для цієї функції. Наприклад:

foo <- function() {
    bar <- 1
}
foo()
bar

дає наступне повідомлення про помилку: Error: object 'bar' not found.

Якщо ви хочете зробити barглобальну змінну, вам слід зробити:

foo <- function() {
    bar <<- 1
}
foo()
bar

У цьому випадку barдоступний ззовні функції.

Однак, на відміну від C, C ++ або багатьох інших мов, дужки не визначають область змінних. Наприклад, у такому фрагменті коду:

if (x > 10) {
    y <- 0
}
else {
    y <- 1
}

yзалишається доступним після if-elseзаяви.

Як ви добре кажете, ви також можете створювати вкладені середовища. Ви можете ознайомитися з цими двома посиланнями, щоб зрозуміти, як ними користуватися:

  1. http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
  2. http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html

Ось невеликий приклад:

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

136

<- виконує призначення в поточному середовищі.

Коли ви знаходитесь у функції, 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значення бар залишається як "in baz - перед << -". Як тільки ми називаємо bazкопію бару всередині fooзмінено на "in 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, тому що ми точно сказали, де його шукати. Однак цього разу значення бар у глобальному середовищі було змінено, оскільки ми там явно призначили.

Тепер ви також запитали про створення локальних змінних, і ви можете це зробити досить легко, не створюючи функції ... Нам просто потрібно використовувати localфункцію.

bar <- "global"
# local will create a new environment for us to play in
local({
    bar <- "local"
    print(bar)
})
#[1] "local"
bar
#[1] "global"

2

Трохи більше по тих же лініях

attrs <- {}

attrs.a <- 1

f <- function(d) {
    attrs.a <- d
}

f(20)
print(attrs.a)

надрукує "1"

attrs <- {}

attrs.a <- 1

f <- function(d) {
   attrs.a <<- d
}

f(20)
print(attrs.a)

Буде надруковано "20"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.