0

I discovered some (for me) really strange behavior of python 3.6. I use pytest to test some behavior of a Vehicle class, I defined. I create an instance of the class and initialize it with three vectors, namely position, velocity, and acceleration, slightly alter these vectors and then create a second instance of the same class and initialize it with slightly different vectors, explicitly defining one and relying on the default values provided in the __init__() method. However, after the initialization, it seems that python does not use the default value of the constructor, but uses the last value of the first instance.

Here is the code I use to test my implementation:

def test_vehicle_movement():
  vehicle = Vehicle2d(velocity=Vector(1.0, 0.0))
  assert vehicle.velocity == Vector(1.0, 0.0)
  assert vehicle.position == Vector(0.0, 0.0)
  vehicle.move()
  assert vehicle.position == Vector(1.0, 0.0)
  vehicle2 = Vehicle2d(acceleration=Vector(2.0, 0.0))
  assert vehicle2.position == Vector(0.0, 0.0)   # fails

And here is the constructor of the vehicle class:

class Vehicle2d:
  def __init__(self, position: Vector = Vector(0.0, 0.0), 
               velocity: Vector = Vector(0.0, 0.0),
               acceleration: Vector = Vector(0.0, 0.0)):
    self.position = position
    self.velocity = velocity
    self.acceleration = acceleration

  def move(self):
    # changes the velocity and position vectors according to acceleration

I found this answer on another thread but in my case, different memory addresses are used, which is why I expect some error in the class vs. instance variable area. However, being rather new to python, I don't understand what I did wrong. To make things worse: The velocity vector gets reset as expected properly, only position is troublesome. Also, if I explicitly define position of vehicle2 to be a zero vector, this works fine. For some reason, I conclude, the default parameter is not used properly and or there is some unwanted connection between my vehicle instances. Any idea anyone?

  • 1
    Please, include your Vector class. As it is your code cannot be executed. – Ignacio Vergara Kausel Mar 12 '18 at 10:16
  • 3
    Don't use mutable values as default arguments. – Daniel Roseman Mar 12 '18 at 10:25
  • As the vector class is dependent on a library, not part of the standard packages, and I hoped that someone could answer the question without execution, I skipped it. I've had a look at [this explanation](http://effbot.org/zone/default-values.htm), given in [the question, mine was marked a duplicate of](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument). It suggests placeholders like `None` as default arguments. If Python does offer the functionality of default values, is there not a more obvious way of how to use them than this workaround? – Christian Steinmeyer Mar 12 '18 at 13:37

0 Answers0