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.
..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:
or a more bpy related version:
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')) | |
here's another:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') |