-2

Here's my code :

hp1 = 100
health1 = 'you have', hp1

hp1 = hp1 - 50
health1

print hp1
print health1

This is what it prints :

50
('you have', 100)

Why doesn't the hp1 change inside the health?

8
  • 1
    Why do you expect it to change? Commented Dec 18, 2017 at 15:45
  • because i subtracted 50 from hp1. I'm new to python so I don't reallly know what i'm doing haha Commented Dec 18, 2017 at 15:47
  • 4
    Recommended reading: nedbatchelder.com/text/names.html Commented Dec 18, 2017 at 15:58
  • 1
    You evaluated hp1 at the point where you assigned it to health1. After that they had no connection. You're not thinking this through. Suppose you had instead used 5 + hp1**2/(1 - hp1). Would you still expect the value to track? Did you think you were creating a closure, and that the expression was reevaluated each time health1 was referenced? Clearly not. Commented Dec 18, 2017 at 16:02
  • 1
    @StefanPochmann Yes, it's true that health[1] is hp1 is True at that point. But that's not what I meant. I meant that changing either has no effect on the other. Commented Dec 18, 2017 at 16:44

5 Answers 5

2

To automatically change the output with any mutations of hp1, you can use a class:

class Health:
   def __init__(self, health):
       self.health = health
   def __add__(self, val):
       return Health(self.health + val)
   def __sub__(self, val):
       return Health(self.health - val)
   def __repr__(self):
       return "you have {}".format(self.health)

hp1 = Health(100)
hp1 -= 50
print(hp1)

Output:

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

4 Comments

This is the first answer that addresses the intent of the question, rather than just explaining the observed results.
@chepner Well, to be fair, the OP explicitly asked "Why doesn't the hp1 change inside the health?", and not "How to...?"
To be fair, in your example, you could have done a = 0 ; a += 50 ; print a. I believe you should have written what I answered to be in the OP's scope.
Uh... what is this? That does not do the desired thing.
2

The following line:

health1 = 'you have', hp1

Is creating a tuple with two values: "you have" and 100 (Note that the value of hp1 is copied, and not referenced). It's then assigning this tuple to a new variable named health1.

health1 has nothing to do with hp1. If hp1 get overriden, deleted, thrown away, or anything happens to it, health1 doesn't care.


If you are so eager to pass this variable a reference, you can create a wrapper class around the int type:

class IntWrapper(object):
     def __init__(self, value):
          self.value = value
     def __add__(self, value):
          return IntWrapper(self.value + value)
     def __iadd__(self, value):
          self.value += value
          return self
     def __sub__(self, value):
          return IntWrapper(self.value - value)
     def __isub__(self, value):
          self.value -= value
          return self
     def __str__(self):
          return str(self.value)
     def __repr__(self):
          return str(self)

hp1 = IntWrapper(100)
health1 = 'you have', hp1

hp1 -= 50

print hp1          # 50
print health1      # ('you have', 50)

14 Comments

If "the value is copied, not referenced", then why is health1[1] is hp1 true?
Terminology nitpick: there are no primitive types in Python. int objects are full objects, just like any other.
@StefanPochmann I agree. However, if it don't change the internal value then it will not accomplish what OP wants, because hp1 would point to a new reference, and health1 would be pointing to a stale one.
@MatiasCicero Yes, but you'd better not do that with __sub__. Do that with __isub__ instead. Or maybe better with decrease or so, calling it as hp1.decrease(50) without assignment notation.
|
0

To do what you wish to do, you must use a class. This is the closest form of a pointer you will encounter in python.

Here is an example :

class Health():
    def __init__(self, value):
        self.hp = value

    def __repr__(self):
        return 'You have {}.'.format(self.hp)

health = Health(100)
hp_clone = health
health.hp -= 50

print hp_clone
# Program outputs : You have 50.

Your question is also a possible duplicate of Pointers in Python? .

What is happening here in your program has been explained by the others.

Comments

0

Because you defined health1 - a (string, int) tuple - as hp1 was still 100 and didn't change it since then. This is not a pointer in C/C++ sense, just a copy by value.

3 Comments

what's the solution though?
Solution to what? Change the variable if you want it to change. Don't change them otherwise. I don't see a problem. Work through a tutorial to get a feeling for how these things work: docs.python.org/3/tutorial
There was no copy by value. Assignment in Python never copies
0

In your code you have done like this,

hp1 = 100 # setting hp1 as 100
health1 = 'you have', hp1 # making a tuple 

hp1 = hp1 - 50 # subracting 50 from hp1 -> gives 50 as result
health1 # simply calling health1

print hp1 # displaying hp1
print health1 # displaying health1

In this code,

You defined hp1 as 100, let it be stored in a location 1000

You made a tuple names health1 as 'you have', hp1. It will be stored in a location say 2000

You subtracted 50 from hp1 making hp1 50, this will make no change to health1 variable because it is stored in different location. But it will change the value of hp1

Hope this helps.!!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.