Defining and initializing object models using specklepy

Sure thing! By “typed attributes” I mean the class attributes you’ve defined on your custom object that are annotated with specific type (eg length: float). I’m referring to these in particular because we do some light type checking for these types of class attributes on assignment. By “initialise” yes I mean assigning it a default value which you can do when defining (eg length: float = 0.0) or in the init method as shown in the Block example.

So in summary, as long as you have default non-mutable values for the attributes you care about, you don’t need an init

more info 😎

To further expand on why there is this is, the attributes assigned to custom Speckle Objects are actually instance attributes that overshadow class attributes. This is a little hack that helps us in a few ways, but particularly in serialisation / deserialisation. For optimal performance, the Speckle Objects that come with specklepy do not have init methods. This significantly decreases deserialisation time for us because an unnecessary init isn’t getting called every single time the deserialiser creates an empty speckle object to fill with values from the incoming json. This works great and is perfectly safe, however it can be a footgun if you aren’t smart about how you’re defining your classes.

Since there is no init, a fresh object’s attributes if you haven’t assigned them will be referring to the class attribute. So if for example you have a default value for an attribute that is a mutable value (eg an empty list) then mutating it on an instance will mutate the class attribute and affect future instances of the class.

This is why the simplest and most failsafe method of defining classes is with an init and this is what’s shown to you first in the speckle.guide example. However, as long as you follow the simple rule of always initialising with non-mutable default values (None being the simplest way to go) or if the val will only ever be changed by reassignment (eg you only do attr = new_val rathre than attr.append(blah)) then it will not be a problem!

2 Likes