1

ANSWERED! :)

I have to create a function that

  1. Initializes a new object
  2. Creates and adds data to that object
  3. Returns the object containing the data.

The object basically contains a json dict (geojson) and offers a way of oop with geojson data.

In the python script in question, I create multiple instances of the class Feature. However, for some reason, the second Feature object I create already has the attributes of the first Feature object - at a different RAM address AND without passing anything to the 2nd object (obj_1 and obj_2 are created in different functions, completely unrelated to each other...)

I am relatively new to OOP with Python so maybe I am missing something obvious. This is also my first question on stackoverflow so just keep that in mind :) I just can't wrap my head around this problem though.

This is the code I use (I will only give you the Feature init, if you need more I'll happily provide more!):

class Feature:

def __init__(self, featuretype: str="Point", coordinates: list=[], \
             properties: dict={}, dictionary: dict={}):
    # basically loads a provided dictionary or auto-creates one in json format
    if dictionary:
        self.dict = dictionary
    else:
        self.new(featuretype, coordinates, properties)
    self.update()

First function (outside class):

def create_checkerboard(extent, dist_x, dist_y) -> bk.Feature:
    checker_ft = bk.Feature(featuretype="MultiPoint") #init
    checker_ft.gen_grid_adv(extent, dist_x, dist_y, matrixname="checkerboard") #populate
    return checker_ft

The returned checker_ft object now has a checker_ft.dict which is now populated with a MultiPoint grid. All is well.

Second function (outside class):

def random_grid(extent, grid_spacing_x, grid_spacing_y, shift) -> bk.Feature:
    shift_ft = bk.Feature(featuretype="MultiPoint") #init
    shift_ft.gen_grid(extent, grid_spacing_x, grid_spacing_y) #populate
    return shift_ft

Now, for a reason which is obviously beyond me, the shift_ft.dict contains data from the checker_ft. And both objects are at different RAM locations:

<bk_functions.Feature object at 0x000001A726A3CF70>
<bk_functions.Feature object at 0x000001A726A1F190>

I hope that this is a simple oversight on my part. Thank you for your kind attention!

Ben Kraas
  • 11
  • 4
  • A problem with Mutable Default Arguments? https://docs.python-guide.org/writing/gotchas/ ("A new list is created once when the function is defined, and the same list is used in each successive call.") – qrsngky Aug 05 '22 at 10:21
  • You mean in a sense that I mutated the default __init__ dictionary in the first function? But if I for example call a function with a default value once by providing a value, and another time without providing one, the value is not preserved between calls... I might not have understood this yet, will look into it though! Thank you! – Ben Kraas Aug 05 '22 at 10:30
  • It happens if the defaults you set are `{}` or `[]` (or the likes), but not if it's simpler values like `0` or `1` – qrsngky Aug 05 '22 at 10:32
  • In your function, coordinates has a default of `[]` , properties has a default of `{}`, dictionary has a default of `{}`. Those can cause problems. – qrsngky Aug 05 '22 at 10:34
  • I'm beginning to wrap my head around this, I'll try the method described on the website! I'll let you know if this is the problem! – Ben Kraas Aug 05 '22 at 10:36
  • Spot on, this solved the problem. I was not aware of this -I assumed default value instantiation on every function call. Thank you for the help! – Ben Kraas Aug 05 '22 at 10:42
  • Let met put a link to another Stack overflow thread: https://stackoverflow.com/questions/8257372/mutable-default-arguments-in-python – qrsngky Aug 05 '22 at 10:45
  • Ah, now I get why the object address was a different one for each object - I didn't check the list address passed to each object. I am guessing that both objects were getting data from the same list... Makes sense now! – Ben Kraas Aug 05 '22 at 10:49
  • It's potentially more 'dangerous' than "the second Feature already has the attribute of the first Feature": when you try to change the second Feature, you can accidentally change the first Feature. So, it should be avoided except in some exceptional cases (or, as the website puts it, "When the Gotcha Isn't a Gotcha"). – qrsngky Aug 05 '22 at 10:52
  • Well, strictly speaking the first feature was not changed: its property is still the same list, but the content (which the user may think belongs to the feature) is changed – qrsngky Aug 06 '22 at 00:29

0 Answers0