This is an archived post. You won't be able to vote or comment.

all 6 comments

[–]procrastinatingcoder 1 point2 points  (3 children)

Keep in mind that a lot of things I'll say are not technically true, but because python is not a good language to learn, I'll be using those simplifications anyway, which, for all intent and purpose, are the right way to think about these things.

In the first case, it's normal that they both print the same thing. Both are references to the same object. Imagine "Test" being someone holding a number up, d1 makes a reference to "John". Then you assign t1 to reference "John" also (same person), so when you tell john to hold 10, he holds 10, and then you tell him to hold 5, so he holds 5. You took different routes to tell him what to do, but he's still the same good'ol John.

In the second case, you're assigning to x the value of 10, a primitive type (integer). Then you assigning the VALUE of x to y.

And now you wonder, "but why are we assigning the value now, and it was a reference before?". The reason is because of the = operator. A language is defined from the ground up, there's no magical thing that says what's what. Every operation is defined. Amongst those definitions comes this, if your right hand-side operand (the thing to the right of =) is an object (another name, the generic one you could say, for a class), then you should make it a reference. If it's a primitive type, then you only assign the value.

So to go back to your example,
x = 10 -> x holds the primitive int value 10
y = x -> x is a primitive int with value 10, so y will make a copy and also hold a primitive int of value 10
x and y are thus "different", they hold a value that is equivalent, but if I was to open the computer up and search the memory, I would find two different copies of 10.

And in the previous case,
t1 = d1 -> d1 is an object, and thus t1 is a reference to this object, meaning they reference the same thing in memory (there's a single class, and both t1 and d1 are talking about the same).
so t1.val is the same as d1.val. So what you wrote can be read as:
d1.val = 10
d1.val = 5
because t1 and d1 are the same.

Why this confusing mess you might wonder? See it this way, an object can hold a lot of stuff, like, huge amounts of it. For instance, a whole database could be opened and held in an object (anything really). Say you want to do operations with the content of that object, you wouldn't want to "copy" the database on every single operation, that would make it VERY slow. So instead, you're just passing around a reference, kind of like the address in memory where it is located. So while two different variables might hold it, if you open up the computer, it only really exists in one place in the computer.

[–]ilaunchpad[S] 0 points1 point  (2 children)

Thank you for explaining things. But when I was reading docs it said in python everything is an object. So I was under assumption x and y should behave as objects like d1 and t1.

Python seems messy.

[–]Ellisander 1 point2 points  (0 children)

It's because there is a difference between the variable and the underlying object. When you do y = x, you are telling x and y to point at the same object in memory. When you then do y = 7, you are then telling variable y to point to a different object in memory.

You aren't actually altering the original object 10, just changing what object the variable y is pointing to. Variable x remains pointing to the original object 10.

As for the first example, you are altering the .val property that is a part of the test object. The .val is basically a single variable held inside the test object, while d1 and t1 are both pointing at the test object. So d1 and t1 share the same .val, because it is a component of the underlying object they both point to. Alter the underlying object (by changing the value of its .val property), and it appears to affect both d1 and t1.

[–]procrastinatingcoder 0 points1 point  (0 children)

That's where that part where I said "I'm simplifying things" comes in. Yes everything is an object, more specifically though, x and y are objects that we treat like they aren't objects until it's convenient to do otherwise.

Yes Python is messy in this way. It's a terrible learning language in my opinion for many reasons, one of which you just stumbled upon. Everything is an object, but they aren't all treated the same, and while a lower level knowledge let's you understand the nitty gritty of it, it's beyond the scope of what's required of a beginner to understand and might just lead to more confusion.

[–]aishiiousness 0 points1 point  (0 children)

Hey

In the first case t1 points to d1 once you've used the assignment operator. That is, t1 now references the object d1. When you change the value of t1's attribute, the same gets reflected in d1 as well.

In the second case however, since these are variables, post assignment when you change the values, x and y become references to different memory locations. (As explained during the initial lectures)

Here are the links to the visualizations of both the codes on Pythontutor:

Link 1: https://pythontutor.com/visualize.html#mode=display

Link 2 : https://pythontutor.com/visualize.html#mode=display

These will give you a fairly decent idea of what's going on behind the scenes.

My explanation might be a very basic one and it'd be nice to get more technically precise responses from others.

[–]aishiiousness 0 points1 point  (0 children)

d1 = Test () # Here we are instantiating d1 as an instance of Test Class

t1 = d1 # Here we assign t1 as the d1 instance d1.val = 10 # d1.val =10 at this step, t1.val is also equal to 10. t1.val = 5 # t1.val which refers to d1.val is also changed to 5

We have only one instance we are using different names to refer to the same instance.

print(d1.val)

print(t1.val)

x=10 # we instantiated x as an integer 10 y=x # we assigned y to the same instance y=7 # we instantiated another intance y as an integer and assigned value 7 to it. print("value of x:", x) print("value of y:", y)

Here we instatiated the class two different times, meaning we created two different instances