Featured post

new redirect for blender.org bpy docs.

http://www.blender.org/api/blender_python_api_current/ As of 10/11 november 2015 we can now link to the current api docs and not be worr...

October 04, 2012

Decorators Python

Despite the many hours I spend writing python code, it's not often that I come across concepts that don't make sense. But it does happen, and one of those concepts (patterns?) is the decorator.

Blender scripting uses a class method (@classmethod) sometimes, so the notation isn't alien. Stackoverflow has an explanation that managed to finally break it down for me. Now I know from experience that with every new concept that comes into the repertoire it's likely i'll use and abuse it for a while until I can judge more sanely when to use the pattern, and when it gets in the way of readability.

I will avoid explaining here how this works, read the stackoverflow article. But as usual here is a snippet that sums up what I managed to get from it.
def add_bold(fn):
def perform(input_string):
return '<b>' + fn(input_string) + '</b>'
return perform
@add_bold
def regular(input_string):
return input_string
print(regular('chop'))
view raw for the sake.py hosted with ❤ by GitHub
..Perhaps come back to this post with more blender related reasons to use a decorator. Or if you know of a use that you would like to showcase, let me know below.

here's another:
def mouse_change(func):
def add_mouse_change(*args):
print('mouse wait')
func(*args)
print('mouse normal')
return add_mouse_change
@mouse_change
def monkey_business(a, b, c):
print('a={0}, b={1}, c={2}'.format(a, b, b))
monkey_business(10, 20, 30)
view raw punga.py hosted with ❤ by GitHub
or a more bpy related version:
import bpy
import time
# declare the decorator
def mouse_change(func):
def add_mouse_change(*args):
bpy.context.window.cursor_set("WAIT")
func(*args)
bpy.context.window.cursor_set("DEFAULT")
return add_mouse_change
class SimpleCBOperator(bpy.types.Operator):
bl_idname = "node.some_callback_identifier"
bl_label = "Short Name"
# bl_options = {'REGISTER', 'UNDO'}
fn_name = bpy.props.StringProperty(default='')
@mouse_change
def dispatch(self, context, type_op):
if type_op == 'some_named_function':
time.sleep( 5 )
print(type_op)
elif type_op == 'some_named_other_function':
time.sleep( 5 )
print(type_op)
def execute(self, context):
self.dispatch(context, self.fn_name)
return {'FINISHED'}
def register():
bpy.utils.register_class(SimpleCBOperator)
def unregister():
bpy.utils.unregister_class(SimpleCBOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.node.some_callback_identifier(fn_name='some_named_function')