user: How do I use Getter/Setter Example in Blender? Include parameters, examples, warnings and best practices.

assistant: Accessor functions can be used for boolean, int, float, string and enum properties.

If `get` or `set` callbacks are defined, the property will not be stored in the ID properties
automatically. Instead, the `get` and `set` functions will be called when the property
is respectively read or written from the API, and are responsible to handle the data storage.

Note that:

- It is illegal to define a `set` callback without a matching `get` one.
- When a `get` callback is defined but no `set` one, the property is read-only.

`get_transform` and `set_transform` can be used when the returned value needs to be modified,
but the default internal storage is still used. They can only transform the value before it is
set or returned, but do not control how/where that data is stored.

```
import bpy

scene = bpy.context.scene

# Simple property reading/writing from 'custom' IDProperties.
# This is similar to what the RNA would do internally, albeit using it own separate,
# internal 'system' IDProperty storage, since Blender 5.0.
def get_float(self):
    return self.get("testprop", 0.0)

def set_float(self, value):
    self["testprop"] = value

bpy.types.Scene.test_float = bpy.props.FloatProperty(get=get_float, set=set_float)

# Testing the property:
print("test_float:", scene.test_float)
scene.test_float = 7.5
print("test_float:", scene.test_float)

# The above outputs:
# test_float: 0.0
# test_float: 7.5

# Read-only string property, returns the current date.
def get_date(self):
    import datetime
    return str(datetime.datetime.now())

bpy.types.Scene.test_date = bpy.props.StringProperty(get=get_date)

# Testing the property:
# scene.test_date = "blah"   # This would fail, property is read-only.
print("test_date:", scene.test_date)

# The above outputs something like:
# test_date: 2018-03-14 11:36:53.158653

# Boolean array.
# - Set function stores a single boolean value, returned as the second component.
# - Array getters must return a list or tuple.
# - Array size must match the property vector size exactly.
def get_array(self):
    return (True, self.get("somebool", True))

def set_array(self, values):
    self["somebool"] = values[0] and values[1]

bpy.types.Scene.test_array = bpy.props.BoolVectorProperty(size=2, get=get_array, set=set_array)

# Testing the property:
print("test_array:", tuple(scene.test_array))
scene.test_array = (True, False)
print("test_array:", tuple(scene.test_array))

# The above outputs:
# test_array: (True, True)
# test_array: (True, False)

# Boolean array, using 'transform' accessors.
# Note how the same result is achieved as with previous get/set example, but using default RNA storage.
# Transform accessors also have access to more information.
# Also note how the stored data _is_ a two-items array.
# - Set function stores a single boolean value, returned as the second component.
# - Array getters must return a list or tuple.
# - Array size must match the property vector size exactly.
def get_array_transform(self, curr_value, is_set):
    print("Stored data:", curr_value, "(is set:", is_set, ")")
    return (True, curr_value[1])

def set_array_transform(self, new_value, curr_value, is_set):
    print("New data:", new_value, "; Stored data:", curr_value, "(is set:", is_set, ")")
    return True, new_value[0] and new_value[1]

bpy.types.Scene.test_array_transform = bpy.props.BoolVectorProperty(
    size=2, get_transform=get_array_transform, set_transform=set_array_transform)

# Testing the property:
print("test_array_transform:", tuple(scene.test_array_transform))
scene.test_array_transform = (True, False)
print("test_array_transform:", tuple(scene.test_array_transform))

# The above outputs:
# Stored data: (False, False) (is set: False )
# test_array_transform: (True, False)
# New data: (True, False) ; Stored data: (False, False) (is set: False )
# Stored data: (True, False) (is set: True )
# test_array_transform: (True, False)

# Enum property.
# Note: the getter/setter callback must use integer identifiers!
test_items = [
    ("RED", "Red", "", 1),
    ("GREEN", "Green", "", 2),
    ("BLUE", "Blue", "", 3),
    ("YELLOW", "Yellow", "", 4),
]

def get_enum(self):
    import random
    return random.randint(1, 4)

def set_enum(self, value):
    print("setting value", value)

bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum)

# Testing the property:
print("test_enum:", scene.test_enum)
scene.test_enum = 'BLUE'
print("test_enum:", scene.test_enum)

# The above outputs something like:
# test_enum: YELLOW
# setting value 3
# test_enum: GREEN

# String, using 'transform' accessors to validate data before setting/returning it.
def get_string_transform(self, curr_value, is_set):
    import os
    is_valid_path = os.path.exists(curr_value)
    print("Stored data:", curr_value, "(is set:", is_set, ", is valid path:", is_valid_path, ")")
    return curr_value if is_valid_path else ""

def set_string_transform(self, new_value, curr_value, is_set):
    import os
    is_valid_path = os.path.exists(new_value)
    print("New data:", new_value, "(is_valid_path:", is_valid_path, ");",
          "Stored data:", curr_value, "(is set:", is_set, ")")
    return new_value if is_valid_path else curr_value

bpy.types.Scene.test_string_transform = bpy.props.StringProperty(
    subtype='DIR_PATH',
    default="an/invalid/path",
    get_transform=get_string_transform,
    set_transform=set_string_transform,
)

# Testing the property:
print("test_string_transform:", scene.test_string_transform)
scene.test_string_transform = "try\\to\\find\\me"
print("test_string_transform:", scene.test_string_transform)

# The above outputs something like:
# Stored data: an/invalid/path (is set: False , is valid path: False )
# test_string_transform:
# New data: try\to\find\me (is_valid_path: False ) ; Stored data: an/invalid/path (is set: False )
# Stored data: an/invalid/path (is set: True , is valid path: False )
# test_string_transform:
```

bpy.props.BoolProperty(*\**, *name=''*, *description=''*, *translation_context='\*'*, *default=False*, *options={'ANIMATABLE'}*, *override=set()*, *tags=set()*, *subtype='NONE'*, *update=None*, *get=None*, *set=None*, *get_transform=None*, *set_transform=None*)
:   Returns a new boolean property definition.

    Parameters:
    :   - **name** (*str*) – Name used in the user interface.
        - **description** (*str*) – Text used for the tooltip and api documentation.
        - **translation_context** (*str*) – Text used as context to disambiguate translations.
        - **options** (*set**[**str**]*) – Enumerator in [Property Flag Items](bpy_types_enum_items/property_flag_items.html#rna-enum-property-flag-items).
        - **override** (*set**[**str**]*) – Enumerator in [Property Override Flag Items](bpy_types_enum_items/property_override_flag_items.html#rna-enum-property-override-flag-items).
        - **tags** (*set**[**str**]*) – Enumerator of tags that are defined by parent class.
        - **subtype** (*str*) – Enumerator in [Property Subtype Number Items](bpy_types_enum_items/property_subtype_number_items.html#rna-enum-property-subtype-number-items).
        - **update** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), [`bpy.types.Context`](bpy.types.Context.html#bpy.types.Context "bpy.types.Context")], None]) – Function to be called when this value is modified,
          This function must take 2 values (self, context) and return None.
          *Warning* there are no safety checks to avoid infinite recursion.
        - **get** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct")], bool]) –

          Function to be called when this value is ‘read’, and the default,
          system-defined storage is not used for this property.
          This function must take 1 value (self) and return the value of the property.
        - **set** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), bool], None]) –

          Function to be called when this value is ‘written’, and the default,
          system-defined storage is not used for this property.
          This function must take 2 values (self, value) and return None.
        - **get_transform** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), bool, bool], bool]) –

          Function to be called when this value is ‘read’,
          if some additional processing must be performed on the stored value.
          This function must take three arguments (self, the stored value,
          and a boolean indicating if the property is currently set),
          and return the final, transformed value of the property.
        - **set_transform** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), bool, bool, bool], bool]) –

          Function to be called when this value is ‘written’,
          if some additional processing must be performed on the given value before storing it.
          This function must take four arguments (self, the given value to store,
          the currently stored value (‘raw’ value, without any `get_transform` applied to it),
          and a boolean indicating if the property is currently set),
          and return the final, transformed value of the property.

bpy.props.BoolVectorProperty(*\**, *name=''*, *description=''*, *translation_context='\*'*, *default=(False, False, False)*, *options={'ANIMATABLE'}*, *override=set()*, *tags=set()*, *subtype='NONE'*, *size=3*, *update=None*, *get=None*, *set=None*, *get_transform=None*, *set_transform=None*)
:   Returns a new vector boolean property definition.

    Parameters:
    :   - **name** (*str*) – Name used in the user interface.
        - **description** (*str*) – Text used for the tooltip and api documentation.
        - **translation_context** (*str*) – Text used as context to disambiguate translations.
        - **default** (*Sequence**[**bool**]*) – sequence of booleans the length of *size*.
        - **options** (*set**[**str**]*) – Enumerator in [Property Flag Items](bpy_types_enum_items/property_flag_items.html#rna-enum-property-flag-items).
        - **override** (*set**[**str**]*) – Enumerator in [Property Override Flag Items](bpy_types_enum_items/property_override_flag_items.html#rna-enum-property-override-flag-items).
        - **tags** (*set**[**str**]*) – Enumerator of tags that are defined by parent class.
        - **subtype** (*str*) – Enumerator in [Property Subtype Number Array Items](bpy_types_enum_items/property_subtype_number_array_items.html#rna-enum-property-subtype-number-array-items).
        - **size** (*int* *|* *Sequence**[**int**]*) – Vector dimensions in [1, 32]. An int sequence can be used to define multi-dimension arrays.
        - **update** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), [`bpy.types.Context`](bpy.types.Context.html#bpy.types.Context "bpy.types.Context")], None]) – Function to be called when this value is modified,
          This function must take 2 values (self, context) and return None.
          *Warning* there are no safety checks to avoid infinite recursion.
        - **get** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct")], Sequence[bool]]) –

          Function to be called when this value is ‘read’, and the default,
          system-defined storage is not used for this property.
          This function must take 1 value (self) and return the value of the property.
        - **set** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), tuple[bool, …]], None]) –

          Function to be called when this value is ‘written’, and the default,
          system-defined storage is not used for this property.
          This function must take 2 values (self, value) and return None.
        - **get_transform** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), Sequence[bool], bool], Sequence[bool]]) –

          Function to be called when this value is ‘read’,
          if some additional processing must be performed on the stored value.
          This function must take three arguments (self, the stored value,
          and a boolean indicating if the property is currently set),
          and return the final, transformed value of the property.
        - **set_transform** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), Sequence[bool], Sequence[bool], bool], Sequence[bool]]) –

          Function to be called when this value is ‘written’,
          if some additional processing must be performed on the given value before storing it.
          This function must take four arguments (self, the given value to store,
          the currently stored value (‘raw’ value, without any `get_transform` applied to it),
          and a boolean indicating if the property is currently set),
          and return the final, transformed value of the property.

bpy.props.CollectionProperty(*type*, *\**, *name=''*, *description=''*, *translation_context='\*'*, *options={'ANIMATABLE'}*, *override=set()*, *tags=set()*)
:   Returns a new collection property definition.

    Parameters:
    :   - **type** (type[[`bpy.types.PropertyGroup`](bpy.types.PropertyGroup.html#bpy.types.PropertyGroup "bpy.types.PropertyGroup")]) – A subclass of a property group.
        - **name** (*str*) – Name used in the user interface.
        - **description** (*str*) – Text used for the tooltip and api documentation.
        - **translation_context** (*str*) – Text used as context to disambiguate translations.
        - **options** (*set**[**str**]*) – Enumerator in [Property Flag Items](bpy_types_enum_items/property_flag_items.html#rna-enum-property-flag-items).
        - **override** (*set**[**str**]*) – Enumerator in [Property Override Flag Collection Items](bpy_types_enum_items/property_override_flag_collection_items.html#rna-enum-property-override-flag-collection-items).
        - **tags** (*set**[**str**]*) – Enumerator of tags that are defined by parent class.

bpy.props.EnumProperty(*items*, *\**, *name=''*, *description=''*, *translation_context='\*'*, *default=None*, *options={'ANIMATABLE'}*, *override=set()*, *tags=set()*, *update=None*, *get=None*, *set=None*, *get_transform=None*, *set_transform=None*)
:   Returns a new enumerator property definition.

    Parameters:
    :   - **items** (Iterable[tuple[str, str, str] | tuple[str, str, str, int] | tuple[str, str, str, int, int] | None] | Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), [`bpy.types.Context`](bpy.types.Context.html#bpy.types.Context "bpy.types.Context") | None], Iterable[tuple[str, str, str] | tuple[str, str, str, int] | tuple[str, str, str, int, int] | None]]) –

          sequence of enum items formatted:
          `[(identifier, name, description, icon, number), ...]`.

          The first three elements of the tuples are mandatory.

          identifier:
          :   The identifier is used for Python access.
              An empty identifier means that the item is a separator

          name:
          :   Name for the interface.

          description:
          :   Used for documentation and tooltips.

          icon:
          :   An icon string identifier or integer icon value
              (e.g. returned by [`bpy.types.UILayout.icon`](bpy.types.UILayout.html#bpy.types.UILayout.icon "bpy.types.UILayout.icon"))

          number:
          :   Unique value used as the identifier for this item (stored in file data).
              Use when the identifier may need to change. If the *ENUM_FLAG* option is used,
              the values are bit-masks and should be powers of two.

          When an item only contains 4 items they define `(identifier, name, description, number)`.

          Separators may be added using either None (nameless separator),
          or a regular item tuple with an empty identifier string, in which case the name,
          if non-empty, will be displayed in the UI above the separator line.
          For dynamic values a callback can be passed which returns a list in
          the same format as the static list.
          This function must take 2 arguments `(self, context)`, **context may be None**.
        - **name** (*str*) – Name used in the user interface.
        - **description** (*str*) – Text used for the tooltip and api documentation.
        - **translation_context** (*str*) – Text used as context to disambiguate translations.
        - **default** (*str* *|* *int* *|* *set**[**str**]*) – The default value for this enum, a string from the identifiers used in *items*, or integer matching an item number.
          If the *ENUM_FLAG* option is used this must be a set of such string identifiers instead.
          WARNING: Strings cannot be specified for dynamic enums
          (i.e. if a callback function is given as *items* parameter).
        - **options** (*set**[**str**]*) – Enumerator in [Property Flag Enum Items](bpy_types_enum_items/property_flag_enum_items.html#rna-enum-property-flag-enum-items).
        - **override** (*set**[**str**]*) – Enumerator in [Property Override Flag Items](bpy_types_enum_items/property_override_flag_items.html#rna-enum-property-override-flag-items).
        - **tags** (*set**[**str**]*) – Enumerator of tags that are defined by parent class.
        - **update** (Callable[[[`bpy.types.bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct"), [`bpy.types.Context`](bpy.types.Context.html#bpy.types.Context "bpy.types.Context")], None]) – Function to be called when this v