假设我有以下类型:
type Foo
a::Int64
b::Int64
end
Run Code Online (Sandbox Code Playgroud)
我可以用它来实例化
bar = Foo(1,2)
Run Code Online (Sandbox Code Playgroud)
有没有办法在这里使用关键字,因为在上面我必须记住它a是第一个,并且b是第二个.像这样的东西:
bar = Foo(a=1, b=2)
Run Code Online (Sandbox Code Playgroud)
编辑:
如果从函数调用,spencerlyon2的解决方案不起作用:
#!/usr/bin/env julia
type Foo
a::Float64
b::Float64
end
function main()
Foo(;a=1, b=2.0) = Foo(a,b)
bar = Foo(a=1, b=2.0)
println(bar.a)
end
main()
Run Code Online (Sandbox Code Playgroud)
为什么?有解决方法吗?
编辑2:
在函数内部不起作用:
#!/usr/bin/env julia
type Foo
a::Int64
b::Int64
end
function main()
Foo(;a=1, b=2) = Foo(a,b)
bar = Foo(a=1, b=2)
println(bar.a)
end
main()
Run Code Online (Sandbox Code Playgroud)
但如果把它从功能中取出 - 它可以工作:
#!/usr/bin/env julia
type Foo
a::Int64
b::Int64
end
# function main()
Foo(;a=1, b=2) = Foo(a,b)
bar = Foo(a=1, b=2)
println(bar.a)
# end
# main()
Run Code Online (Sandbox Code Playgroud)
是的,但您需要参数的默认值:
julia> type Foo
a::Int64
b::Int64
end
julia> Foo(;a=1, b=2) = Foo(a, b)
Foo
julia> Foo(b=10)
Foo(1,10)
julia> Foo(a=40)
Foo(40,2)
julia> Foo(a=100, b=200)
Foo(100,200)
Run Code Online (Sandbox Code Playgroud)
让我们分解语法Foo(;a=1, b=1) = Foo(a, b).
首先,定义与类型同名的函数定义该类型的新构造函数.这意味着我们正在定义另一个将创建类型对象的函数Foo.手册中有关于构造函数的整章,所以如果你不熟悉这个术语,你应该阅读它们.
其次,Julia区分位置和关键字参数.位置参数是Julia中的默认参数.使用位置参数,根据定义参数的顺序将名称分配给函数参数,然后将其传递给函数.例如,如果我定义一个函数,f(a, b) = ....我知道我传递给的第一个参数f将被称为a函数体内(无论变量的名称在调用范围内).
Julia中对关键字参数的处理方式不同.argument=value在调用函数时,使用语法为函数的关键字参数提供非默认值.在Julia中,您告诉编译器某些参数是关键字参数,方法是使用分号(;)将它们与标准位置参数分开并赋予它们默认值.例如,如果我们定义g(a; b=4) = ...我们可以给a通过使传递给第一件事值g和b说的值b=something.如果我们想g用参数调用函数a=4,b=5我们会写g(4; b=5)(注意;这里可以替换为a ,,但我发现它有助于我记住,b如果我使用的话,这是一个关键字参数;).
有了这个,我们终于可以理解上面的语法:
Foo(;a=1, b=2) = Foo(a, b)
Run Code Online (Sandbox Code Playgroud)
这将创建零个位置参数和两个关键字参数一个新的构造:a和b,其中a给出的默认值1和b默认2.该函数声明的右侧简单地a使用b和传递它们以便默认的内部构造函数(在我们声明类型时为我们自动定义)Foo.
我想出了在函数中定义新的外部构造函数时遇到的问题.
线条
function main()
Foo(;a=1, b=2.0) = Foo(a,b)
Run Code Online (Sandbox Code Playgroud)
实际上创建了一个函数Foo本地的全新main函数.因此,左侧创建一个新的本地Foo,右侧尝试调用新的本地Foo.问题是没有为本地定义的方法Foo需要两个位置Int64参数.
如果你真的想要这样做,你需要告诉函数通过指定属于全局范围main的方法向Foo外部函数添加方法Foo.这有效:
function main()
global Foo
Foo(;a=1, b=2.0) = Foo(a,b)
bar = Foo(a=1, b=2.0)
println(bar.a)
end
Run Code Online (Sandbox Code Playgroud)
关于使用内部构造函数.当然你可以这样做,但你也想要定义一个默认的内部构造函数.这是因为如果您没有定义任何新的内部构造函数,Julia会为您生成一个默认构造函数.如果您决定创建自己的一个,那么如果您想拥有它,则必须手动创建默认构造函数.这样做的语法是
type Foo
a::Int64
b::Int64
# Default constructor
Foo(a::Int64, b::Int64) = new(a, b)
# our new keyword constructor
Foo(;a::Int64=1, b::Int64=2) = new (a, b)
end
Run Code Online (Sandbox Code Playgroud)
我应该注意,对于这个特定的用例,你几乎肯定不希望将关键字版本定义为内部构造函数,而是将其作为外部构造函数,就像我在答案开头时所做的那样.Julia中的约定是尽可能使用最少数量的内部构造函数 - 仅在需要确保字段之间的不变关系或部分初始化对象的情况下使用它们.
| 归档时间: |
|
| 查看次数: |
377 次 |
| 最近记录: |