99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀R語言面向?qū)ο缶幊?S3和R6
R語言面向?qū)ο缶幊?S3和R6
2017-06-10
收藏

R語言面向?qū)ο缶幊?S3和R6

一、基于S3的面向?qū)ο缶幊?

基于S3的面向?qū)ο缶幊淌且环N基于泛型函數(shù)(generic function)的實(shí)現(xiàn)方式。
1.S3函數(shù)的創(chuàng)建
S3對象組成:generic(generic FUN)+method(generic.class FUN)
泛型函數(shù)(generic)創(chuàng)建示例:
get_n_elements <- function(x,...)
{
UseMethod("get_n_elements")
}
通常用UseMethod()函數(shù)定義一個泛型函數(shù)的名稱,通過傳入?yún)?shù)的class屬性,來確定對應(yīng)的方法調(diào)用。
method(generic.class)函數(shù),創(chuàng)建示例: 
# Create a data.frame method for get_n_elements
get_n_elements.data.frame <- function(x, ...)
{
nrow(x) * ncol(x) # or prod(dim(x))
}
 
# Create a default method for get_n_elements
#在使用UseMethod調(diào)用時(shí),先在methods中尋找對應(yīng)class,如果都沒有找到,則會調(diào)用#default方法。
get_n_elements.default <- function(x,...)
{
length(unlist(x))
}
methods() 用于查找S3泛型函數(shù)中所有可用的methods。

調(diào)用pryr包中的is_s3_method() 可以驗(yàn)證函數(shù)是否S3方法。

2、S3對象的傳入?yún)?shù)有多個class屬性的處理方法
當(dāng)變量x具有多個class屬性,應(yīng)按具體到通用的順序來排列變量對應(yīng)的class。
使用NextMethod()來調(diào)用methods
an_s3_method.some_class <- function(x, ...)
{
# Act on some_class, then
NextMethod("an_s3_method")
}
具體示例如下:
# Assign classes
class(kitty) <- c("cat","mammal","character")
 
what_am_i <- function(x,...)
{
   UseMethod("what_am_i")
}
 
# cat method
what_am_i.cat <- function(x)
{
  message("I'm a cat")
  NextMethod("what_am_i")
}
 
# mammal method
what_am_i.mammal <- function(x, ...)
{
  message("I'm a mammal")
  NextMethod("what_am_i")
}
 
# character method
what_am_i.character <- function(x, ...)
{
  message("I'm a character vector")
}
二、基于R6的面向?qū)ο缶幊?br /> 1、R6對象的創(chuàng)建
首先使用 R6Class() 創(chuàng)建一個class generator(也可叫factory)。
第一個參數(shù)是創(chuàng)建的對象的類的名字。
參數(shù)private為一個list,為對象保存數(shù)據(jù)域(data field),包含每個元素的名字。
參數(shù)pubilc為一個list,為對象保存面向用戶的函數(shù)或功能。
library(R6)<br>thing_factory <- R6Class(
  "Thing",
  private = list(
    a_field = "a value",
    another_field = 123
  ),
  public = list(
    do_something = function(x, y, z) {
      # Do something here
    }
  )
)
創(chuàng)建factory后,再調(diào)用new()來生成一個R6對象。new()無需定義,所有的factory都默認(rèn)具有該方法。
a_thing <- thing_factory$new()
initialize()是一種特殊的公有方法(public method), 在R6對象創(chuàng)建時(shí)自動調(diào)用,用來設(shè)置私域(private field)值。
new()中的參數(shù)被傳給initialize()。
# Add an initialize method
microwave_oven_factory <- R6Class(
"MicrowaveOven",
private = list(
power_rating_watts = 800,
door_is_open = FALSE
),
public = list(
cook = function(time_seconds) {
Sys.sleep(time_seconds)
print("Your food is cooked!")
},
open_door = function() {
private$door_is_open = TRUE
},
close_door = function() {
private$door_is_open = FALSE
},
# Add initialize() method here
initialize = function(power_rating_watts,door_is_open){
if(!missing(power_rating_watts)){
private$power_rating_watts<-power_rating_watts
}
if(!missing(door_is_open)){
private$door_is_open<-door_is_open
}
}
)
)
 
# Make a microwave
a_microwave_oven <- microwave_oven_factory$new(
power_rating_watts = 650,
door_is_open = TRUE
)
2.訪問和設(shè)置私有域
private組件中的數(shù)據(jù)對用戶隱藏,這是封裝的原理。使用private$前綴可以訪問私域(private field)。
存在active組件中的active binding(行為像變量的函數(shù)),可以獲取和設(shè)置私有數(shù)據(jù)域。
Active bindings是R6中一種特殊的函數(shù)調(diào)用方式,把對函數(shù)的訪問表現(xiàn)為對屬性的訪問,屬于公有組件。
thing_factory <- R6Class(
  "Thing",
  private = list(
    ..a_field = "a value"
  ),
  active = list(
    a_field = function(value) {
      if(missing(value)) {
        private$..a_field
      } else {
        assert_is_a_string(value) # or another assertion
        private$..a_field <- value
      }
    }
  )
)
 將active binding作為數(shù)據(jù)變量而不是函數(shù)進(jìn)行調(diào)用。
 a_thing <- thing_factory$new()
a_thing$a_field # not a_thing$a_field()
3、R6的繼承
(1)子類的創(chuàng)建
繼承將一個類(class)的功能復(fù)制到另一個??稍赗6Class()中用inherit參數(shù)來創(chuàng)建子類。

child_class_factory <- R6Class(
"ChildClass",
inherit = parent_class_factory
)
子類可以添加公有方法來擴(kuò)展父類的功能,并在公有方法中使用前綴self$調(diào)用其他公有方法。
子類也可定義與父類相同的方法名稱來重寫該方法,用于擴(kuò)展父類的功能,子類使用前綴super$訪問父類的公有方法。
(2)跨級訪問
R6類默認(rèn)只能使用直接父類的功能。為了跨級訪問,中間類(intermediate classes)首先需要定義一個active binding來顯示父類,形式如下:
active = list(super_ = function() super)
然后可以跨級使用方法parent_method <- super$method()grand_parent_method <- super$super_$method(great_grand_parent_method <- super$super_$super_$method()
(3)共享域
大部分類型的R變量是通過值復(fù)制,意思是當(dāng)復(fù)制一個變量時(shí) ,新的變量具有自己的復(fù)制值,改變其中一個變量不會影響另外一個。
環(huán)境變量(Environments)比較特殊,通過地址傳送來復(fù)制(by reference),因此所有的復(fù)制品都是等同的,改變其中一個就會改變其他變量。R6類可利用環(huán)境的地址傳送(by reference)復(fù)制行為在對象之間共享區(qū)域,定義一個名為shared的私域,方式如下:
創(chuàng)建一個新的環(huán)境,指定該環(huán)境的任意共享域,可通過active bindings訪問。
工作方式與其他active bindings相同,但需使用private$shared$前綴來找回(retrieve)這些區(qū)域
R6Class(
"Thing",
private = list(
shared = {
e <- new.env()
e$a_shared_field <- 123
e
}
),
active = list(
a_shared_field = function(value) {
if(missing(value)) {
private$shared$a_shared_field
} else {
private$shared$a_shared_field <- value
}
}
)
)

(4)R6對象的復(fù)制 

R6對象使用與環(huán)境變量相同的地址傳送復(fù)制方式,如果使用<- 符號復(fù)制R6對象,原對象的變化會影響復(fù)制品。
a_reference_copy <- an_r6_object
R6 對象有一個自動生成的clone() 方法,用于值復(fù)制,使用clone()復(fù)制的對象的變化不影響其他對象。
a_value <- an_r6_object$clone()
當(dāng)R6對象的一個或多個域包含另一個R6對象時(shí),默認(rèn)clone() 通過地址傳送復(fù)制該R6域。
如果值復(fù)制這些R6域,clone() 方法必須使用參數(shù):deep = TRUE。
a_deep_copy <- an_r6_object$clone(deep = TRUE)
(5)R6對象的消除
當(dāng)消除對象時(shí),定義公有finalize()方法運(yùn)行自定義代碼。該方法一般用于關(guān)閉與數(shù)據(jù)庫或文件的連接,或者消除例如改變?nèi)诌x項(xiàng)(option)或者圖形參數(shù)的副作用。
thing_factory <- R6Class(
"Thing",
public = list(
initialize = function(x, y, z) {
# do something
},
finalize = function() {
# undo something<br># Print a message<br>"Disconnecting from the cooking times database."<br># Disconnect from the database<br>dbDisconnect(private$conn)
}
)
)<em id="__mceDel" style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.5; background-color: #ffffff"> </em>

當(dāng)R的自動垃圾回收器(automated garbage collector)從存儲中清除對象時(shí)調(diào)用finalize() 方法,可使用gc()強(qiáng)制垃圾回收。

數(shù)據(jù)分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個參數(shù)驗(yàn)證碼對象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺檢測極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }