Close
Community Post

Python Tips'N'Tricks #2

>>>Part 1<<<

PRoperties

Properties are a really convinient way of making your extensions much more readable and easier to use. One prime example are parameters.

Getter

Lets imagine we have some kind of network extension and have a port parameter for the user to edit. When we now want to acces the port-number in our extension we would need to write

self.ownerComp.par.Portnumber.eval()

We can now use the property feature to encabsulate this expression into its one property the following way

@property
def Port(self):
    return self.ownerComp.par.Portnumber.eval()

To acces the Portnumber from outside we now only need to acces the comps Port member and from inside the self.Port member

print( self.Port )

Note that this member will not be dependable and force refferencing Operators to cook, but it can be very handy for scripting.

But there is more! We are not limited to one line in the definition, but could also add extra functionality, like logging everytime the Port member gets accesed.

@property
define Port(self):
    debug( 'Port member of {} got accesed'.format (self.ownerComp.name) )
    return self.ownerComp.par.Portnumber.eval()

Setter

Properties also enable the definition of a setter.

@Port.setter
def Port(self, portnumber):
    self.ownerComp.par.Portnumber.val = portnumber

We can now set the Portnumber parameter of our component simply by setting the Port member

op('NetworkComponent').Port = 1337

Super convinient.

Nesting op refferences

I see alot of people building the path to a component out of the names of the component like this

mastercomp = 'NetworkComponent'
child = 'Connection'
connectionnumber = 2
connectioncomp = op( mastercomp + '/' child + str(connectionnumber) )

But instead, you can just chain the getter functions like op and parent to on another. Using the code above, to get the child of our NetworkComponent we simply chain them together.

network_comp = op( 'NetworkComponent' )
conectioncomp = network_comp.op( 'Connection' + str(2) )

This can also be done with the parent method. Lets say we have a component with a global op shortcut, and we want to know where in the projekt it resides

parent_path = op.NetworkComponent.parent().path

run

Sometimes you have a script that you want to execute. For example you want to define a script as a parameter that gets executed when we pulse another parameter. For simplicity lets use the script

debug( me )

For thiis we could use the eval() function, feeding it the given script in a parameter execute.

eval( parent().par.Script.eval() )

But this will print out the path to the parameterExecuteDAT, and not the component holding the script. For this, its better to use the run() method. Here we can define, if the script shall be executed as if it comes from another parameter.

run( parent().par.Script.eval(), fromOP = parent() )

Now, the debugstatement will spit out the parameter with the Script-parameter. Nice!

Delay frames

Sometimes it is neccesarry to execute a script in another frames. For example some stuff is not possible inside of the init function of an extension or directly during startup. Just set the delayFrames argument.

run( parent().par.Script.eval(), delayFrames = 1 )

 

chan index

Many CHOPs enable you to write expressions in on or another way. As an example, we have a midiInCHOP. The problem is, that all of the channels will range from 0 to 127. We could now use a selectCHOP, in combination with a mathCHOP to re-range every incoming channel. But that will hurt performance, the more single channels we have, and also you will end with a lot of spagetty in your network. Instead, let us create a table with to colums, one for max and one for min. We can now use the re-range feature of the mathCHOP and use another value for every channel in our CHOP. The expression in the min and max-parameter now is

op('range_table')[ me.chanIndex, 0]
op('range_table')[ me.chanIndex, 1]

The complete setup looks like this:

 

 

 

Comments