2

I wonder, how could I pass by reference the four values into the array? It seems that they are passed by value. Here's the minimal reproducing example:

class SomeObject:
    def __init__(self, w, x, y, z):
        self.w = w
        self.x = x
        self.y = y
        self.z = z
        self.q = [self.w, self.x, self.y, self.z]

    def __mul__(self, other):
        q0, q1, q2, q3 = other
        self.w *= q0
        self.x *= q1
        self.y *= q2
        self.z *= q3


test = SomeObject(1, 1, 1, 1)
print(test.q)
>> [1, 1, 1, 1]
test * (2, 2, 2, 2)
print(test.q)
>> [1, 1, 1, 1]
print(test.w)
>> 2

Edit: I could use get/set decorators but that's pretty wordy.

1
  • I'm sure there's a reason why this is a bad idea—and while the outcome is the same as what you're going for, it doesn't accomplish pass-by-reference—you could call __init__ from within __mul__ to set the new values. Commented Apr 3, 2022 at 23:29

2 Answers 2

2

In Python, it's idiomatic to use the property decorator to create a read-only attribute, like this:

class SomeObject:
    def __init__(self, w, x, y, z):
        self.w = w
        self.x = x
        self.y = y
        self.z = z

    def __mul__(self, other):
        q0, q1, q2, q3 = other
        self.w *= q0
        self.x *= q1
        self.y *= q2
        self.z *= q3

    @property
    def q(self):
        return [self.w, self.x, self.y, self.z]



>>> test = SomeObject(1, 1, 1, 1)
>>> test.q
[1, 1, 1, 1]
>>> test * (2, 2, 2, 2)
>>> test.q
[2, 2, 2, 2]
>>> test.w
2

You still cannot modify w/x/y/z via q here, e.g.

>>> test.q[0] = 7
>>> test.q
[2, 2, 2, 2]

but it'd be much more clear to write this as:

>>> test.w = 7
>>> test.q
[7, 2, 2, 2]

since referencing the 0th index means you know which underlying value you want to change anyhow. (Explicit better than implicit and all that good stuff.)

Sign up to request clarification or add additional context in comments.

Comments

0

In Python, all parameters are passed by reference. However, that doesn't quite mean the same thing as it does in a language like C++. For example, certain built-in types, such as int, are immutable. Let me give an example.

x = 5

Right now, x is a reference to an object. That object is an int and holds the value 5. However, since ints are immutable,

x += 1

doesn't change the object to which x refers from a 5 to a 6. Instead, x is changed to refer to a new object which holds the value 6.

So, when, in __mul__, you do self.w *= q0, that doesn't change the underlying int that self.w and self.q[0] used to refer to. self.w now refers to a different int and self.q[0] remains unchanged.

In addition to the mutable/immutable distinction, there's another way in which Python references differ from, say, C++ references. Reassignment, depending on how it's done, can change the referent object. For example,

x = [1, 2, 3]
y = x # x and y now refer to the same object
y.append(4)
print(x) # [1, 2, 3, 4], because x is y
x = [5, 6, 7] # x now refers to a new object
print(y) # [1, 2, 3, 4]

With in-place arithmetic reassignment, such as +=, it goes back to the mutable/immutable issue. For example, since ints are immutable, they can't be changed in place and so the referent has to change. However, for lists,

x = [1, 2, 3]
y = x
x += [4]
print(y) # [1, 2, 3, 4]

This is because lists have an __iadd__ method which alters the list in place.

For something to chew on, consider these examples:

def add_one(x):
    x += 1

def append_one(x):
    x.append(1)

def add_one_list(x):
    x += [1]

def add_one_list_part_2(x):
    x = x + [1]

x = 5
add_one(x)
print(x) # What will be printed?

y = [4, 3, 2]
append_one(y)
add_one_list(y)
add_one_list_part_2(y)
print(y) # What will be printed?

1 Comment

Thank you for your answer, cleared the confusion. I indeed had the impression it worked as C++. So the easy fix is to refer to object instead. I find it counter intuitive to treat immutable object differently (both object should still hold the same reference no matter what).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.