0

Let me clarify my question. I've found myself not know what to choose in the following scenarios

Scenario 1 - Function that modifies an array (or other mutable object)

Option 1: Modify array in function and return it.

def double(arr):
    arr = 2*arr
    return arr

def main:
    # do stuff
    arr = np.array([1, 2, 3])
    arr = double(arr)
    # do more stuff

Option 2: Modify array in place

def double(arr):
    arr = 2*arr

def main:
    # do stuff
    arr = np.array([1, 2, 3])
    double(arr)
    # do more stuff

Scenario 2 - Class method which uses class property

Option 1: Pass class property as parameter

class Class():
    def __init__(property):
        self.property = property

    def main():
        result = calculate(self.property)
        return result

    def calculate(property):
        # do stuff with property
        return result

Option 2: Just reference the property directly

class Class():
    def __init__(property):
        self.property = property

    def main():
        result = calculate()
        return result

    def calculate():
        # do stuff with self.property
        return result

I can think of some cases where the choice is clear but just wondering if there are some rules of thumb or common practices.

I would like to get answers with reputable references if possible as I know this type of topic can be very opinion driven.

Alexander Soare
  • 2,825
  • 3
  • 25
  • 53
  • 1
    I think you swapped the code of `double` for Scenario 1 options 1 and 2 – Corentin Pane May 24 '20 at 15:10
  • 2
    Scenario 1: Nothing is performed in-place here. In the Python builtins and stdlib functions usually return a copy and methods return an in-place modified version, e.g. compare `sorted` and `list.sort`. Scenario 2: it depends if `calculate` works on the class state not. It can be `staticmethod` if not, otherwise it should use `self`. – a_guest May 24 '20 at 15:11
  • 1
    Have you tried the example codes? They don't work. – Asocia May 24 '20 at 15:16
  • `result` is also a local name; as soon as `main()` exits, the name is gone. It's not available to `Class.calculate`. – chepner May 24 '20 at 15:35
  • Read https://nedbatchelder.com/text/names.html. – chepner May 24 '20 at 15:35
  • @CorentinPane sorted – Alexander Soare May 24 '20 at 15:41
  • @Asocia I didn't test them. I'm not checking to see if the code will work or not. It's more of a best practices question. Anyway I made one thing clearer by using a numpy array instead – Alexander Soare May 24 '20 at 15:42
  • @chepner just added a return to sort that out. But for clarity, I'm aware of that distinction between a local variable and a class property – Alexander Soare May 24 '20 at 15:44

1 Answers1

2

Scenario 1

When you pass in a variable in python, reassigning the value of a passed variable (not to be confused with modifying the value IN a passed variable), does not modify that variable in-place (see How do I pass a variable by reference?).

So the below won't actually modify mylist outside the scope of the function:

def double_list(mylist):
    mylist = 2 * mylist

But this will (again see the post I linked for a better explanation):

def add_to_list(mylist):
    mylist.append(0)

So for scenario 1, option 2 won't actually do anything so stick with option 1.


Scenario 2

You forgot to add self as the first parameter to all the class function. Unless any of the functions are intended to be @classmethods or @staticmethods your probably better off just sticking with option 2 and use the properties directly:

class Class:
    def __init__(self, property):
        self.property = property

    def main(self):
        result = self.calculate()
        return result

    def calculate(self):
        # do stuff with self.property
        return result

Your use of main here however is not usual. Main shouldn't be part of a Class. Why not just call Class.calculate() directly? All main does in this scenario is return the same thing as calculate.

Jay Mody
  • 3,727
  • 1
  • 11
  • 27
  • Thanks for the answer. regarding self and main that was just me hastily writing pseudocode. Regarding the in place editing that won't work, thanks I didn't notice that. I must have been doing it when I was woking with a function in the same scope as the call...? Anyway point taken – Alexander Soare May 24 '20 at 20:34