On Mon, May 20, 2013 at 06:00:56PM +0100, David Ham wrote:
>    On 20 May 2013 15:12, Garth N. Wells <[1]gn...@cam.ac.uk> wrote:
>
>    On 20 May 2013 15:06, Florian Rathgeber
>    <[2]florian.rathge...@gmail.com> wrote:
>    > On 20/05/13 15:03, Anders Logg wrote:
>    >> On Mon, May 20, 2013 at 02:58:53PM +0100, Florian Rathgeber wrote:
>
>    >>> On 20/05/13 14:49, Garth N. Wells wrote:
>    >>>> On 20 May 2013 14:33, Anders Logg <[3]l...@simula.no> wrote:
>    >>>>> On Mon, May 20, 2013 at 01:09:20PM +0100, Garth N. Wells wrote:
>    >>>>>> On 20 May 2013 12:44, David Ham <[4]david....@imperial.ac.uk>
>    wrote:
>
>    >>>>>>> Hi all,
>    >>>>>>>
>    >>>>>>> I'm writing Dolfin-compatible wrappers for PyOP2 as previously
>    advertised at
>    >>>>>>> FEniCS '13, which is causing me to bump into one of the
>    "interesting" quirks
>    >>>>>>> of the Python Dolfin API. Lots of things which would appear to
>    naturally be
>    >>>>>>> properties are actually methods and have to be called to be
>    accessed. For
>    >>>>>>> one among many, many examples, consider the value_size method
>    of a Function.
>    >>>>>>> This is accessed with:
>    >>>>>>>
>    >>>>>>> f.value_size()
>    >>>>>>>
>    >>>>>>> while
>    >>>>>>>
>    >>>>>>> f.value_size
>    >>>>>>>
>    >>>>>>> would seem more natural. Given the existence of the @property
>    decorator in
>    >>>>>>> standard Python which translates the former into the latter,
>    this is
>    >>>>>>> particularly mysterious. Is there a reason why this is done in
>    Dolfin?
>    >>>>>>>
>    >>>>>>
>
>    >>>>>> A few of us discussed this in January.  I agree that the latter
>    is cleaner.
>    >>>>>>
>    >>>>>> First point, the Python interface is largely generated
>    automatically,
>    >>>>>> so that's our starting position. We would save on C++ code and
>    get the
>    >>>>>> syntax ' f.value_size' in many cases by not accessing member
>    data via
>    >>>>>> functions. I like skipping the function, and have been doing so
>    lately
>    >>>>>> with new code. The issue we discussed in January was backwards
>    >>>>>> compatibility - we could make a lot of C++ changes to get the
>    syntax
>    >>>>>> 'f.size', but users would have to update their code (this point
>    >>>>>> bothers me less than it does others :)).
>    >>>>>>
>    >>>>>> In some cases we need a method, e.g.  to get the size of a
>    vector from
>    >>>>>> a linear algebra backend. Storing the size in a wrapper is error
>    >>>>>> prone.
>    >>>>>>
>    >>>>>> In summary, the reason for the interface in some parts is
>    >>>>>> history/convention (with no technical reason), and in other
>    cases it's
>    >>>>>> a method for technical reasons. We could move more towards
>    direct
>    >>>>>> access to member data.
>    >>>>>
>    >>>>> I don't agree with these conlusions.
>    >>>>>
>    >>>>> The reasons for the use of methods are:
>    >>>
>
>    >>> I think David didn't argue for direct access to member data (as in
>    >>> access to the C++ members), or in fact about changing the C++ layer
>    at
>    >>> all. Rather we would like the semantic attribute access on Python
>    layer
>    >>> provided by @property, which I think circumvents most of the issue
>    >>> Anders raises (note again I'm only talking about the Python
>    interface):
>    >>>
>
>    >>>>> 1. Tradition: following some C++ guidelines we read 10 years back
>    that
>    >>>>> member data should never be accessed directly.
>    >>>>
>    >>>> It's done at times in the STL, e.g std::pair.
>    >>>
>
>    >>> One reason of using @property is not accessing member data
>    directly.
>    >>>
>
>    >>>>> 2. Safety: Being able to access member variables means they can
>    be
>    >>>>> changed from the outside (for a non-const object). This might
>    lead to
>    >>>>> all kinds of unwanted behavior. A member variable can rarely be
>    >>>>> changed safely without changing a whole bunch of other data.
>    >>>>>
>    >>>>
>    >>>> If the data must be hidden, then it can be hidden behind a
>    function.
>    >>>> Otherwise, if the object is const, then member data cannot be
>    changed
>    >>>> and only const functions can be called on the data.
>    >>>> Something that would make things cleaner around the code would be
>    to
>    >>>> let more objects have immutable data (e.g., not allow Vector
>    >>>> resizing), which allows some member data to be made const.
>    >>>>
>
>    >>>> At present we have annoying code duplication in numerous classes
>    to
>    >>>> provide const and non-const access functions.
>    >>>
>
>    >>> @property is read-only be default. You can also define a setter,
>    which
>    >>> would then be able to take care of changing all the other data.
>    >>>
>
>    >>>>> 3. Consistency: Sometimes, there is no member data to be accessed
>    but
>    >>>>> it gets computed or extracted by the accessor function. This
>    means if
>    >>>>> we moved to more access of member data, there would be mix of
>    both and
>    >>>>> it would be confusing and inconsistent.
>    >>>>
>    >>>> This is a major plus to accessing data directly. It makes explicit
>    >>>> that accessing a data member involves no computation.
>    >>>
>
>    >>> With @property you would keep the accessor function as it is but
>    access
>    >>> it as if it were a property. In addition, if the access involves
>    >>> expensive computation that would only need to be done once, it can
>    be
>    >>> cached directly on the attribute using e.g. cached_property:
>    >>> [5]http://www.toofishes.net/blog/python-cached-property-decorator/
>    >>>
>
>    >>>>> On top of theses strong reasons (2 + 3), we would also break the
>    >>>>> interface.
>    >>>>
>    >>>> Which is a drawback.
>    >>>
>
>    >>> Yes, also using @property would be an interface-breaking change.
>    >>
>    >> I guess it's not possible to have both?
>    >
>    > Not in Python, since there is no way to overload functions. The
>    property
>    > would override the function of the same name.
>    >
>
>      I'm not keen on additions that diverge the C++ and Python
>      interfaces,
>      or changes that require more Swig glue or Python wrappers than are
>      absolutely necessary. It more than doubles the work (2 x testing, 2
>      x
>      documentation, plus making sure both interfaces do the same thing).
>      Garth
>
>    I think this is rather weak divergence: it's on the level of Python
>    syntax looking different from C++ syntax. If I understand the swig
>    process correctly (and I may not), this involves a change to the recipe
>    for generating code, rather than more wrappers.

How is member function vs member variable an issue of C++ vs Python?
Both are equally useful with the same pros and cons in both languages.

--
Anders
_______________________________________________
fenics mailing list
fenics@fenicsproject.org
http://fenicsproject.org/mailman/listinfo/fenics

Reply via email to