• Are these good ideas?

    From Stephen Tucker@21:1/5 to All on Mon Nov 14 17:14:05 2022
    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.

    In order to achieve this, I hit on the idea that I also supply a module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with each other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the import only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.

    This solution works well.

    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?

    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7
    parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.

    I see nothing wrong with doing that, but I may well be missing something!

    Comments, please!

    Stephen Tucker.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stephen Tucker on Mon Nov 14 17:32:34 2022
    Stephen Tucker <stephen_tucker@sil.org> writes:
    Issue 1 - Global Values
    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.

    One also could gather such functions in a class, then create
    one object of this class in the client and call the functions
    via this object. Your "globals" would become fields of this
    object (class).

    I am now facing another situation where I am wanting to pass 6 or 7 >parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    One could also gather these functions in a class and then
    the client would create an object of this class passing the
    seven values to the object on creation. Then he could
    call the function A on this object, and A could call B from
    the same object. Since the seven values are already stored
    in the object, A would not have to pass them to B.
    If the client would always call A after the object creation,
    A also could be invoked directly from __init__. In this
    case, the invocation of A would be replaced by the creation
    of an object.

    If no one else ever needs to call B, you could also define B
    as a subfunction of A using a nested def statement. Then B
    would already see the seven values passed to A.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Karsten Hilbert@21:1/5 to All on Mon Nov 14 18:39:03 2022
    Am Mon, Nov 14, 2022 at 05:14:05PM +0000 schrieb Stephen Tucker:

    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7 parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.

    I see nothing wrong with doing that, but I may well be missing something!

    Maybe pass and return a class ? Maybe even a data class ?

    Karsten
    --
    GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Bryan@21:1/5 to Stephen Tucker on Mon Nov 14 09:30:13 2022
    Seems like this is a use case for context managers and/or context
    variables:

    https://docs.python.org/3/library/contextlib.html https://docs.python.org/3/library/contextvars.html


    On Mon, 2022-11-14 at 17:14 +0000, Stephen Tucker wrote:
    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.

    In order to achieve this, I hit on the idea that I also supply a
    module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with
    each
    other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the
    import
    only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.

    This solution works well.

    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?

    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7 parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Having had the idea described above, I am considering using it again
    to
    save all the parameter-and-results passing.

    I see nothing wrong with doing that, but I may well be missing
    something!

    Comments, please!

    Stephen Tucker.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Mon Nov 14 17:42:45 2022
    Issue 1.

    Depends very much on your operating system and application environment.

    Issue 2.
    I usually make myself a data class to pass around. Then when I figure out I forgot something, I just update the dataclass and the creator and consumer of it.

    @dataclass
    class CallParameter:
    first : int
    second: str

    etc. I use context specific names, not “first” et. al.

    From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of Stephen Tucker <stephen_tucker@sil.org>
    Date: Monday, November 14, 2022 at 12:16 PM
    To: Python <python-list@python.org>
    Subject: Are these good ideas?
    *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.

    In order to achieve this, I hit on the idea that I also supply a module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with each
    other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the import
    only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.

    This solution works well.

    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?

    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7
    parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.

    I see nothing wrong with doing that, but I may well be missing something!

    Comments, please!

    Stephen Tucker.
    -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!hb_4MXkjG1NsyGoNsLJNDTOruPzfPWJKD-6vj0_2N1yqqtvz8oDZH3cT0EVkFbPTzSC19cAOgXlQdkDp7FZjwbyOjw$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/
    python-list__;!!Cn_UX_p3!hb_4MXkjG1NsyGoNsLJNDTOruPzfPWJKD-6vj0_2N1yqqtvz8oDZH3cT0EVkFbPTzSC19cAOgXlQdkDp7FZjwbyOjw$>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Axy@21:1/5 to Stephen Tucker on Mon Nov 14 19:32:25 2022
    On 14/11/2022 17:14, Stephen Tucker wrote:
    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Your "global variables" module acts exactly as a singleton class. Funny,
    you could (and maybe you do) write in your functions

    import global_vars_module as self

    as the first step of refactoring.

    From personal experience, when I worked at work we used modules for
    globals as well, but over time such an approach looked more and more
    ugly and finally was rejected.
    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7 parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Nothing fancy here, we used dicts for args and results.

    Axy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Stephen Tucker on Mon Nov 14 17:02:54 2022
    For parameter passing like your #2, I have packaged them into a
    dictionary and passed that around. It was easy enough, and worked well.

    The only potential problem is in documenting the key/value pairs the
    dictionary is supposed to contain. You had better make sure it's made
    clear somewhere, preferable where it is consumed.

    For "global" values, sure, put them in a module and import them as
    needed. Just make sure that none of your code is going to mutate those
    values, or you will end up with mass confusion. I suppose you could
    make them be properties that have no setters, if you want to go to that trouble.

    On 11/14/2022 12:14 PM, Stephen Tucker wrote:
    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.

    In order to achieve this, I hit on the idea that I also supply a module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with each other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the import only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.

    This solution works well.

    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?

    Issue 2 - Passed Parameters

    I am now facing another situation where I am wanting to pass 6 or 7 parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.

    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.

    I see nothing wrong with doing that, but I may well be missing something!

    Comments, please!

    Stephen Tucker.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Barry@21:1/5 to All on Mon Nov 14 22:36:43 2022
    On 14 Nov 2022, at 22:06, Thomas Passin <list1@tompassin.net> wrote:

    For parameter passing like your #2, I have packaged them into a dictionary and passed that around. It was easy enough, and worked well.

    I used to use a dict but having been burnt with issues now create a class.

    With a class you can add accessor methods that allow you to run debug code as values are changed. Also you can check that values being set are spelt correctly, have reasonable values etc.

    Barry

    The only potential problem is in documenting the key/value pairs the dictionary is supposed to contain. You had better make sure it's made clear somewhere, preferable where it is consumed.

    For "global" values, sure, put them in a module and import them as needed. Just make sure that none of your code is going to mutate those values, or you will end up with mass confusion. I suppose you could make them be properties that have no setters,
    if you want to go to that trouble.

    On 11/14/2022 12:14 PM, Stephen Tucker wrote:
    Hi,
    I have two related issues I'd like comments on.
    Issue 1 - Global Values
    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.
    In order to achieve this, I hit on the idea that I also supply a module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with each >> other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the import >> only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.
    This solution works well.
    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?
    Issue 2 - Passed Parameters
    I am now facing another situation where I am wanting to pass 6 or 7
    parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.
    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.
    I see nothing wrong with doing that, but I may well be missing something!
    Comments, please!
    Stephen Tucker.

    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Barry@21:1/5 to All on Mon Nov 14 22:53:14 2022
    On 14 Nov 2022, at 22:49, Chris Angelico <rosuav@gmail.com> wrote:

    On Tue, 15 Nov 2022 at 09:38, Barry <barry@barrys-emacs.org> wrote:



    On 14 Nov 2022, at 22:06, Thomas Passin <list1@tompassin.net> wrote:

    For parameter passing like your #2, I have packaged them into a dictionary and passed that around. It was easy enough, and worked well.

    I used to use a dict but having been burnt with issues now create a class. >>
    With a class you can add accessor methods that allow you to run debug code as values are changed. Also you can check that values being set are spelt correctly, have reasonable values etc.


    TBH you could add accessor methods to a dict just as easily

    Its the dict interface that we found allowed for API abuse and lead to hard to fix bugs.

    Barry


    ChrisA
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Barry on Tue Nov 15 09:46:00 2022
    On Tue, 15 Nov 2022 at 09:38, Barry <barry@barrys-emacs.org> wrote:



    On 14 Nov 2022, at 22:06, Thomas Passin <list1@tompassin.net> wrote:

    For parameter passing like your #2, I have packaged them into a dictionary and passed that around. It was easy enough, and worked well.

    I used to use a dict but having been burnt with issues now create a class.

    With a class you can add accessor methods that allow you to run debug code as values are changed. Also you can check that values being set are spelt correctly, have reasonable values etc.


    TBH you could add accessor methods to a dict just as easily

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Barry on Mon Nov 14 18:39:05 2022
    On 11/14/2022 5:36 PM, Barry wrote:


    On 14 Nov 2022, at 22:06, Thomas Passin <list1@tompassin.net> wrote:

    For parameter passing like your #2, I have packaged them into a dictionary and passed that around. It was easy enough, and worked well.

    I used to use a dict but having been burnt with issues now create a class.

    With a class you can add accessor methods that allow you to run debug code as values are changed. Also you can check that values being set are spelt correctly, have reasonable values etc.

    Barry

    Of course, it all depends on how you are going to use the parameters,
    whether you plan to mutate some of them in place, etc. Mutating some of
    the input parameters can be useful, but also can lead to bugs that are
    harder to track down. For simple cases, dicts will probably be fine. Otherwise, classes or data classes may be better, as you suggest.


    The only potential problem is in documenting the key/value pairs the dictionary is supposed to contain. You had better make sure it's made clear somewhere, preferable where it is consumed.

    For "global" values, sure, put them in a module and import them as needed. Just make sure that none of your code is going to mutate those values, or you will end up with mass confusion. I suppose you could make them be properties that have no
    setters, if you want to go to that trouble.

    On 11/14/2022 12:14 PM, Stephen Tucker wrote:
    Hi,
    I have two related issues I'd like comments on.
    Issue 1 - Global Values
    Some years ago, I had a situation where
    (a) I could supply low-level functions that carry out tasks,
    (b) I needed those functions to communicate with each other, but
    (c) I had no access to the module that invoked my functions.
    In order to achieve this, I hit on the idea that I also supply a module
    that I describe as a "global values" module. This module …
    (i) … defines the values that the functions use to communicate with each >>> other;
    (ii) … is the subject of an import statement in each of my functions;
    (iii) … initialises its values at the start of each run (since the import >>> only carries out an actual import once per session);
    (iv) … acts as a repository for the values thereafter.
    This solution works well.
    Given that I am not particularly concerned about efficiency,
    (1) Is this a reasonable way to achieve this goal?
    (2) Do you know of any better ways?
    Issue 2 - Passed Parameters
    I am now facing another situation where I am wanting to pass 6 or 7
    parameters down through several layers of logic (function A calling
    function B calling ... ) and for results to be passed back.
    Having had the idea described above, I am considering using it again to
    save all the parameter-and-results passing.
    I see nothing wrong with doing that, but I may well be missing something! >>> Comments, please!
    Stephen Tucker.

    --
    https://mail.python.org/mailman/listinfo/python-list


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Stromberg@21:1/5 to All on Mon Nov 14 20:36:47 2022
    On Mon, Nov 14, 2022 at 11:33 AM Axy via Python-list <python-list@python.org> wrote:

    On 14/11/2022 17:14, Stephen Tucker wrote:
    Hi,

    I have two related issues I'd like comments on.

    Issue 1 - Global Values

    Your "global variables" module acts exactly as a singleton class.


    Which is apparently a design pattern that some now believe is regrettable.

    It's something I've done before too, but it's pretty much shared, mutable state, which isn't great for functional programming or for parallelism.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Axy@21:1/5 to Dan Stromberg on Tue Nov 15 05:16:02 2022
    On 15/11/2022 04:36, Dan Stromberg wrote:

    On Mon, Nov 14, 2022 at 11:33 AM Axy via Python-list
    <python-list@python.org> wrote:

    On 14/11/2022 17:14, Stephen Tucker wrote:
    > Hi,
    >
    > I have two related issues I'd like comments on.
    >
    > Issue 1 - Global Values

    Your "global variables" module acts exactly as a singleton class.


    Which is apparently a design pattern that some now believe is regrettable.

    Exactly. I dislike it too and always avoid. However, it could be a good starting point. Stepping directly into class-based approach would raise
    the same question: where to place global instance of that class. Gradual refactoring might have greater side effect of better overall design
    where many issues simply vanished by themselves. Maybe, (c) will change
    in favor of well-designed classes, who knows? Dropping singleton code is
    not a difficult task.

    Axy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)