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
网友评论