美文网首页
julia中参数传递方式介绍,以及注意事项

julia中参数传递方式介绍,以及注意事项

作者: 昵称违法 | 来源:发表于2020-09-20 12:44 被阅读0次

    1、 什么是变量的值,地址,什么是指针?

    (1)值。
    变量的值就不讲了,a = 1,定义了一个叫a的变量,它的值是1。
    (2)地址。
    什么是变量的地址:当我们定一个变量的时候,实际上是开辟了一个存储区域,这个存储区域在内存中,【地址】就是变量在内存中保存的位置(内存中该存储区域的起始位置)。
    (3)指针
    什么是指针,指针也是一个变量,它的保存的内容是别的变量的地址,也就是指向别的变量。

    下面的例子,ary1 和 ary2指向同一个数组[同一个内存地址]

    ary1 = [1,2,3]
    ary2 = ary1
    pointer_from_objref(ary1) |> add -> println("ary1的内存地址是$(add)") # @0x0000000016fa07f0
    pointer_from_objref(ary2) |> add -> println("ary2的内存地址是$(add)") # @0x0000000016fa07f0
    

    变量的绑定案例一
    两个变量绑定到同一个值上,修改彼此的值,不影响对方的值

    #两个变量绑定到同一个值上,修改彼此的值,不影响对方的值
    a = 123
    b = a
    # a = 123 , b = 123
    println("a = $(a) , b = $(b)")  
    
    b = 456 #修改b的值,看看a会不会变化
    # a = 123 , b = 456
    println("a = $(a) , b = $(b)")
    
    

    [out]
    a = 123 , b = 123
    a = 123 , b = 456

    变量的绑定案例二
    两个变量绑定到同一个值上,修改一方的值,影响到另一方的值

    #两个变量绑定到同一个值上,修改一方的值,影响到另一方的值
    a = [123]  #注意,这是数组
    b = a
    # a = [123] , b = [123]
    println("a = $(a) , b = $(b)")
    pointer_from_objref(a) |> add -> println("a的内存地址是$(add)")
    pointer_from_objref(b) |> add -> println("b的内存地址是$(add)")
    
    b[1] = 456 #注意,不是 b = [456]
    # a = [456] , b = [456] #更改b的值,结果a的值也改变了
    println("a = $(a) , b = $(b)")
    pointer_from_objref(a) |> add -> println("a的内存地址是$(add)")
    pointer_from_objref(b) |> add -> println("b的内存地址是$(add)")
    
    

    [out]
    始终指向同一个内存地址

    a = [123] , b = [123]
    a的内存地址是Ptr{Nothing} @0x00000000165b77f0
    b的内存地址是Ptr{Nothing} @0x00000000165b77f0
    
    a = [456] , b = [456]
    a的内存地址是Ptr{Nothing} @0x00000000165b77f0
    b的内存地址是Ptr{Nothing} @0x00000000165b77f0
    

    以上的代码,稍做一些改变,你会发现,他们又不互相影响了。看下面的案例

    变量的绑定案例三 (案例二的变种)
    两个变量绑定到同一个值上,重新绑定(对,是重新绑定,不是修改)其中一个变量,不影响另外一个变量,不影响对方的值

    a = [123]
    b = a 
    println("a = $(a) , b = $(b)") # a = [123] , b = [123]
    pointer_from_objref(a) |> add -> println("a的内存地址是$(add)") # @0x000000001691ae30
    pointer_from_objref(b) |> add -> println("b的内存地址是$(add)") # @0x000000001691ae30
    
    b = [456] #这里发生了重新绑定,注意代码的差异"b[1] = 789"这是修改现有值、
    println("a = $(a) , b = $(b)") #a = [123] , b = [456]
    b[1] = 789 #修改b现有的值 # b = [789]
    println("a = $(a) , b = $(b)") # a = [123] , b = [789]
    pointer_from_objref(a) |> add -> println("a的内存地址是$(add)") # 0x000000001691ae30
    pointer_from_objref(b) |> add -> println("b的内存地址是$(add)") # 0x000000001697ebf0
    

    [out]

    a = [123] , b = [123]
    a的内存地址是Ptr{Nothing} @0x0000000016a08670
    b的内存地址是Ptr{Nothing} @0x0000000016a08670
    a = [123] , b = [456]
    a = [123] , b = [789]
    a的内存地址是Ptr{Nothing} @0x0000000016a08670
    b的内存地址是Ptr{Nothing} @0x0000000016a826b0
    

    两个变量指向同一个值,修改值后,为什么有的会变有的不会变?
    这就涉及到类型的【可变】和【不可变】的性质。

    2、Julia如何传递参数?

    【官方:参数传递行为】

    Julia 函数参数遵循有时称为 “pass-by-sharing” 的约定,这意味着变量在被传递给函数时其值并不会被复制。函数参数本身充当新的变量绑定(指向变量值的新地址),它们所指向的值与所传递变量的值完全相同。调用者可以看到对函数内可变值(如数组)的修改。这与 Scheme,大多数 Lisps,Python,Ruby 和 Perl 以及其他动态语言中的行为相同。

    官方指南的链接

    把一个dataframe传入到一个函数中,在函数中修改传入的dataframe,结果发现,原来的dataframe也被修改了,这就是引用传值

    function test()
        #定义一个dataframe
        df = DataFrame()
        df.得分 = rand(3)
        df.姓名 = ["王$(i)" for i in 1:3] 
        df |> display
        
        #在函数里面修改dataframe的内容    
        df1 = modify(df)
        df1 |> display
        df |> display
        df = nothing
        df1 |> display
        df |> display
    
    
    end
    
    function modify(df)
        df.姓名 = ["张$(i)" for i in 1:3]   
        return df
    end
    
    test()
    

    [out]

    #初始的df
    
           得分   姓名
    Float64 String
    1   0.989634    王1
    2   0.405917    王2
    3   0.000650257 王3
    
    #修改后全部变成以下df
    
         得分 姓名
    Float64 String
    1   0.989634    张1
    2   0.405917    张2
    3   0.000650257 张3
    
    

    in-place操作模式下,函数定义遵循原则:函数名字后面增加后缀“!”

    function test()
        df = DataFrame()
        df.得分 = rand(3)
        df.姓名 = ["王$(i)" for i in 1:3] 
        df |> display
        
        #df1 = modify!(df) #inplace操作,不用重新定义一个变量
        modify!(df)    
        df |> display
        
        df = nothing  #清空引用  
        df |> display
    end
    
    function modify!(df)
        df.姓名 = ["张$(i)" for i in 1:3]   
        return df
    end
    
    test()
    

    [out]

    得分  姓名
    Float64 String
    1   0.455671    王1
    2   0.397311    王2
    3   0.868001    王3
    3 rows × 2 columns
    p
    得分  姓名
    Float64 String
    1   0.455671    张1
    2   0.397311    张2
    3   0.868001    张3
    
    同理:数组、字典也是引用传值,大家在使用的时候,注意数据的修改。说明:tuple是值传递,本身tuple就是不可变的。

    相关文章

      网友评论

          本文标题:julia中参数传递方式介绍,以及注意事项

          本文链接:https://www.haomeiwen.com/subject/gxyyyktx.html