0

Whenever I create an instance of a class, create a variable that's assigned that first instance, and use an attribute of the class on the second variable my first variable changes.

class number:
    def __init__(self, value):
        self.value = value
    def add(self):
        self.value = self.value + 1
a = number(10)
b = a
b.add()
a.value

why does a.value give me 11 when I didn't use a.add()?

  • 6
    because `a is b` – juanpa.arrivillaga Jul 26 '17 at 21:32
  • 2
    You should read [Facts and Myths about Python names and values](https://nedbatchelder.com/text/names.html). – juanpa.arrivillaga Jul 26 '17 at 21:33
  • Also see https://stackoverflow.com/questions/10151080/the-immutable-object-in-python – AGN Gazer Jul 26 '17 at 21:34
  • By the way, this is how *all Python variables work*. – juanpa.arrivillaga Jul 26 '17 at 21:34
  • @juanpa.arrivillaga unless they are immutable. This wouldn't have worked with strings (or tuples, or ints for that matter). – DeepSpace Jul 26 '17 at 21:37
  • @DeepSpace nope. It *always* works this way, *even with immutable objects*. Immutable objects lack mutator methods, so you can't change them in the first place. Reassignment is *not* mutation. – juanpa.arrivillaga Jul 26 '17 at 21:38
  • 1
    @juanpa.arrivillaga `a = 1 ; b = a ; a += 1; print(a, b) ; # 2, 1` – DeepSpace Jul 26 '17 at 21:40
  • @DeepSpace what is your point? `__iadd__` is not a mutator method in the case of `int`s. Again, the semantics of these things work **exactly the same for every single object in Python**. – juanpa.arrivillaga Jul 26 '17 at 21:40
  • 1
    @juanpa.arrivillaga Obviously this example re-assigns to `a`. The point is because ints are immutable `b` ia not affected. – DeepSpace Jul 26 '17 at 21:40
  • @DeepSpace Again, so what? You are essentially saying because `a` wasn't mutated, `a` wasn't mutated. Yes, if you reassign a variable, it gets reassigned. But this works **exactly the same with immutable and mutable objects**. See this [gist](https://gist.github.com/juanarrivillaga/895f89cda1461e7f9f81396a17c85527). Also, there are ways to actually mutate `int`s, if you don't mind doing some [dark magic](http://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/#Python-meta-hacking:-Don't-take-my-word-for-it). And sure enough, `a` and `b` would reflect those changes. – juanpa.arrivillaga Jul 26 '17 at 21:48
  • @DeepSpace fundamentally, Python objects don't have some inherent quality that makes them immutable - they simply lack a public interface to mutate them. There is no way for the semantics to be different. – juanpa.arrivillaga Jul 26 '17 at 21:49

2 Answers2

0

Because when you do b = a you're not creating a new object of the class number just passing the reference of the object which a references.

Carlos Afonso
  • 1,927
  • 1
  • 12
  • 22
0

@juanpa.arrivillaga provided good comments to your question. I just want to add how to fix your code to do what you expect it to do:

Method 1:

class number:
    def __init__(self, value):
        self.value = value
    def add(self):
        self.value = self.value + 1
a = number(10)
b = number(a.value) # create a new object with the same value as 'a'
b.add()
a.value

Method 2:

import copy
class number:
    def __init__(self, value):
        self.value = value
    def add(self):
        self.value = self.value + 1
a = number(10)
b = copy.copy(a) # make a shallow copy of the object a 
# b = copy.deepcopy(a) # <-- that is what most people think of a "real" copy
b.add()
a.value
AGN Gazer
  • 8,025
  • 2
  • 27
  • 45