Яка різниця між полями та властивостями у Джулії?


23

Джулія має функції інкубаційних setproperty!і setfield!і функцію геттера getpropertyі getfieldякі працюють на структури. Яка різниця між властивостями та полями в Юлії?

Наприклад, таке здається вказує на те, що вони роблять те саме:

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)

Відповіді:


27

fieldsпросто "компоненти" структури. Структура

struct A
   b
   c::Int
end

має поля bі c. Заклик доgetfield повернути об'єкт, який пов'язаний з полем:

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

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

У ранніх версіях Джулії синтаксис a.bвикористовується для "нижчого", тобто бути таким же, як і для запису 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! є аналогічною різниці між getfieldі getproperty, поясненою вище.

Крім того, можна підключити функцію, 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

Отже, ви не можете перевантажувати гетфілд?
Альфайзхан

3
Ні, getfieldце спеціальна (вбудована) функція. Намагаючись перевантажити, це призведе до помилки cannot add methods to a builtin function.
Крістофер Карлссон

Може десь додати цю інформацію до відповіді?
Стефан Карпінський

2
У відповіді вже прямо сказано «(не можна перевантажувати getfield)», так що, в певному сенсі, вона вже є.
Крістофер Карлссон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.