On 20 May 2013 15:06, Florian Rathgeber <[email protected]> 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 <[email protected]> wrote:
>>>>> On Mon, May 20, 2013 at 01:09:20PM +0100, Garth N. Wells wrote:
>>>>>> On 20 May 2013 12:44, David Ham <[email protected]> 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:
>>> 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


>> --
>> Anders
>
_______________________________________________
fenics mailing list
[email protected]
http://fenicsproject.org/mailman/listinfo/fenics

Reply via email to