Thank you everyone. The specific requirements for that class:

*(1)* Provide the values of the "input" (via constructors).
     *I think everyone agrees with the way it is implemented in the
example. *

*(2)* Provide other products such as *b* that can be of any type (array,
object, etc.). It is like an "output" if you will.
     *I think everyone suggests that it should be designed such that people
should not be able (inadvertently) to change the value from outside the
class.  I agree, as a matter of fact this is my intent as well.*

*(3)* About the function calc(), my intent is NOT to expose it outside the
class: it is "private".
     *And I see the way to do that from your suggestions. *

Based on all your valuable suggestions, I should be able to accomplish the
3 goals.

By the way, I am writing this code for finite element analysis (FEA):
number crunching. Even though the final goal is to get the correct results,
I still want to write it following the correct python "grammar" and style.

Best regards,
-Irfan

On Mon, Jul 25, 2022 at 3:54 AM Peter Otten <__pete...@web.de> wrote:

> On 25/07/2022 02:47, Khairil Sitanggang wrote:
> > Regarding your comment : "
> > *However, usually object creation and initialization iscombined by
> allowing
> > arguments to the initializer:*" , so which one of the two classes Node1,
> > Node2 below is more common in practice? Option 2, I guess.
> > Thanks,
> >
> >
> > # option 1:
> > class Node1:
> >      def __init__(self, a):
> >          self.a = a
> >          self.b = self.calculation()
> >
> >      def calculation(self):
> >          r = self.a + 10
> >          return r
> >
> > # option 2:
> > class Node2:
> >      def __init__(self, a, b):
> >          self.a = a
> >          self.b = b
> >
> >          self.b = self.calculation()
> >
> >      def calculation(self):
> >          r = self.a + 10
> >          return r
> >
> > nd1 = Node1(10)
> > nd2 = Node2(10, 0) # 0 is dummy, will be overwritten by the call to
> > calculation()
>
> An attribute that can be calculated from other attributes should never
> be modified through other means. Some day you may want b to become
> something else, write, for example,
>
> node = Node2(10, "twenty")
>
> and because by then you have forgotten about the calculation() call end
> up with a buggy script. But manually invoking the calculation() method
> is also bug prone. You have to remember to repeat it every time you
> change a:
>
> node = Node1(10)
> assert node.b == 20  # OK
>
> node.a = 20
> assert node.b == 30 # fails, a and b are out of sync.
>
> The solution Python has to offer is called "property". Properties in
> their simplest form are calculated read-only attributes, i. e. when you
> write
>
> print(node.b)
>
> under the hood node.a + 10 is calculated. Here's how to change Node1 to
> turn b into such a property:
>
> class Node3a:
>      def __init__(self, a):
>          self.a = a
>      def calculation(self):
>          return self.a + 10
>      b = property(calculation)
>
> node = Node3a(42)
> print(node.b)  # 52
>
> node.a = 1
> print(node.b)  # 11
>
> Often you are not interested in exposing both the calculation() method
> and the property. For cases when you only want to access the property
> Python provides a way to define the property with a "decorator":
>
> class Node3b:
>      def __init__(self, a):
>          self.a = a
>      @property
>      def b(self):
>          return self.a + 10
>
> When you compare the two classes you can see that I
>
> (1) renamed calculation() to b() and
>
> (2) replaced
>
> def b(self): ...
> b = property(b)
>
> with
>
> @property
> def b(self): ...
>
> thus avoiding the repetitons of the name.
>
> Are there any disadvantages to properties?
>
> What I presented as an advantage, that the value of the attribute is
> recalculated every time the attribute is accessed, may sometimes become
> a disadvantage, e. g. when it takes a very long time to calculate. In
> most cases that should not be a problem, though.
>
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to