Julia中的字段和属性之间有什么区别?


23

Julia具有setter函数setproperty!setfield!getter函数getpropertygetfield并且在结构上运行。Julia中的属性和字段之间有什么区别?

例如,以下内容似乎表明它们执行相同的操作:

julia> mutable struct S
           a
       end

julia> s = S(2)
S(2)

julia> getfield(s, :a)
2

julia> getproperty(s, :a)
2

julia> setfield!(s, :a, 3)
3

julia> s
S(3)

julia> setproperty!(s, :a, 4)
4

julia> s
S(4)

Answers:


27

fields仅仅是结构的“组件”。结构

struct A
   b
   c::Int
end

有字段bc。调用会getfield返回绑定到该字段的对象:

julia> a = A("foo", 3)
A("foo", 3)

julia> getfield(a, :b)
"foo"

在Julia的早期版本中,语法a.b用来“降低”,即与Writing相同getfield(a, :b)。现在发生的变化是 使用默认后备广告a.b降低到getproperty(a, :b)

getproperty(a::Type, v::Symbol) = getfield(a, v)

因此,默认情况下,什么都没有改变。但是,结构的作者可以重载getproperty(不可能重载getfield)以为点语法提供额外的功能:

julia> function Base.getproperty(a::A, v::Symbol)
           if v == :c
               return getfield(a, :c) * 2
           elseif v == :q
               return "q"
           else
               return getfield(a, v)
           end
       end

julia> a.q
"q"

julia> getfield(a, :q)
ERROR: type A has no field q

julia> a.c
6

julia> getfield(a, :c)
3

julia> a.b
"foo"

因此,我们可以为点语法添加额外的功能(如果需要,可以动态地添加)。作为一个有用的具体示例,它是用于PyCall.jl包的,您以前必须编写该包,pyobject[:field] 而现在可以实现它以便可以编写pyobject.field.

之间的差setfield!setproperty!类似于之间的差getfieldgetproperty,如上所述。

另外,可以挂钩该函数Base.propertynames以在REPL中提供属性的制表符补全。默认情况下,仅显示字段名称:

julia> a.<TAB><TAB>
b c

但是通过重载,propertynames我们可以使它也显示额外的属性q

julia> Base.propertynames(::A) = (:b, :c, :q)

julia> a.<TAB><TAB>
b c q

所以你不能重载getfield?
阿尔法兹汗(Alfaizkhan),

3
不,getfield是一种特殊的(内置)功能。尝试使其过载将产生错误cannot add methods to a builtin function
克里斯托弗·卡尔森,

也许将该信息添加到答案中的某个地方?
StefanKarpinski,

2
答案已经明确指出“(不可能过载getfield)”,因此从某种意义上说,它已经存在。
克里斯托弗·卡尔森,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.