Properties, the Defaults for Property keys, and when to use get() First, I've encountered a confusing situation regarding property defaults and the use of getters. When I use a getter, I end up having to supply the default of the property a second time, even though the property has a default specified. Is this normal? Does a property's default attribute become obsolete once you define a getter for it?

Here is a simple situation to illustrate. The relevant lines are the getter() return value and the property default assignment:

flag_list=[
            ('A', "A", "Info", global_flag_a ),
            ('B', "B", "Info", global_flag_b ),
            ('C', "C", "Info", global_flag_c ),
            ('D', "D", "Info", global_flag_d ),
            ]

class PropsPrefs(bpy.types.AddonPreferences):

    # getter
    def getter(self):

        # must supply defaults a second time here?
        return self.get( "enum_flag_var", global_flag_a | global_flag_b | global_flag_c )

    # setter
    def setter(self,value):

        # assign new value if not none
        if value != 0:
            self["enum_flag_var"] = value

    # enum flag variable
    enum_flag_var : EnumProperty(
        name="flags",
        options={'ENUM_FLAG'},
        items=flag_list,
        description="info",
        default={'A', 'B', 'C'}, # never gets used?
        get=getter,
        set=setter
        )


My second area of confusion is why we need to use self.get("property") instead of self.property (as well as self["property"]) in certain situations? I'm assuming it is because these properties are generated at run-time as they are written to for the first time?

Would anyone be able to elaborate on how this works, and when to use one syntax over the other? Any documentation about this behavior? My current (limited) strategy is to use self.property until it throws an error, then switch to self.get("property"). But because of my lack of understanding, I have no way of knowing which of these situations might throw an error under different circumstances.
The default value will not be automatically applied when declaring a property with a getter and setter.

In Python you can use the .get() function when accessing a key in a dictionary that may not exist. It allows you to specify a second argument which will be used as default value in case the key cannot be found. This is necessary for your use case, because the key "enum_flag_var" may not yet exists in the bpy_struct dictionary. Accessing it using self["enum_flag_var"] will result in a KeyError.

KeyError: 'bpy_struct[key]: key "enum_flag_var" not found'


The key will exist once you've assigned a value to the property in your script or when the user sets a value in the UI. You cannot use self.property in the getter, because that would in turn also call the getter and therefore cause an infinite recursion. That's why the value is accessed through the dictionary.