From BlenderWiki

Jump to: navigation, search
Note: This is an archived version of the Blender Developer Wiki. The current and active wiki is available on wiki.blender.org.

Contents | Previous | Next


8 Function

If you had more than enough fun with our Borg Cube game and you took it a lot further, you kept adding code for assimilation, like assimilation of cells using the Borg nanobots, integrating the individual to the the hive mind and erasing its individuality, even implement different assimilation procedures for each specie, you will come up against a problem.

You will replicate the same code again and again, sometimes only slightly modified sometimes heavily modified even if you use sophisticated loops with clever if statements etc. Most likely your code will look more and more messy and will be hard for you to figure what is what. Then you will ask yourself "is this the best way to do this?".

The answer is no. There is an easy way to group code and call it by name, like a shortcut in your desktop, a name can not only point to a variable or a single statement / command but to multiple commands. Ladies and gentlemen I present to you (deep voice with echo) THE FUNCTION !

8.1 Definition


Defining a function is very easy

print("hello world")
 
def print_hello_world():
    print("hello world")
 
print_hello_world()

The code is straightforward, we created a function with the <def> command and name <print_hello_world> that contains only one command -> print("hello world) and we later called it by name plus parentheses to inform python that this is a function and not a variable we are calling.

Function are an easy way to simplify coding, by grouping code and calling it we don't need to know exactly what the code is doing as long as the function is named reasonably. It's a nice way to hide code and make it simple. In this case the name print_hello_world leave no doubts what the function is doing. You can of course put as many commands as you want inside a function, a thousand even a million, but its better to keep functions as short as possible, this way we make them easier to be understood and more difficult for us to get lost inside their code.

You can have functions that call other functions.

def print_hello_world():
    print("hello world")
 
def print_goodbye():
    print("goodbye")
 
def print_hello_and_goodbye():
    print_hello_world()
    print_goodbye()
 
print_hello_world()
print_goodbye()
print_hello_and_goodbye()

8.2 Parameters


A function can have parameters, also known as arguments.

def box_print(text):
    print("*************")
    print(text)
    print("*************")
 
box_print("Hello There")

So what goes inside the parentheses are the arguments or argument. In this case we have a single argument. We can have as many as we want

def box_print(text,times):
    print("*************")
    for x in range (0, times):
        print(text)
    print("*************")
 
box_print("Hello There", 5)

Observe the names we gave in these parameters matters only to the definition part of our function, we don't need to use <text> or <times> variables as parameters when we call the function, we can use values as we did with the above example or variables with any kind of name. The only issue is the type of the data that we pass as parameters when we call the function. For example if we passed to the first argument <text> a number, that will cause no problem because the print that use that argument can print numbers too, but if we passed a string for the second argument <times> it would report an error in the line of the for loop command cause range function expects numbers as arguments not strings. But of course this the kind of behavior that we expect from python.

8.3 Return


If arguments are the input of the function what is the output? The output is <return>

def box_string(text):
    a=["*************",
       text,
       "*************"]
    return a
 
print(box_string("hello"))

As you can see <return> goes inside your function definition and all it does is to output specific data, in this case whatever is contained inside variable a. As you can see we can input and output any kind of data type, python does not care as long as we handle it properly. We could even do instead of print

def box_string(text):
    a=["*************",
       text,
       "*************"]
    return a
 
b= box_string("hello")

in this case b is assigned the contents of a, which is a list of three elements and which is what the function returns. So as you can see with functions its possible to move data around process and change it in a way that is readable and thus easy to understand. This form of programming is called "Procedural Programming", procedure meaning functions in the case of python.

Functions are extremely important and we will heavily use them when we start making blender addons so its absolutely crucial to feel comfortable with them.

8.4 Local Scope


One trap of functions is local scope. Local scope means that what happens inside an function stays inside a function.

def box_string():
    text="hello"
    a=["*************",
       text,
       "*************"]
    return a
 
print(box_string())
 
print(text)

The above fails at print(text) and it complains that it can't find the <text> variable. Why? Well as I said what is defined inside a function definition stays there. Because <text> is defined inside our function definition it cannot be seen by the outside world.

Well actually there is a way.

def box_string():
    text="hello"
    global text
    a=["*************",
       text,
       "*************"]
    return a
 
print(box_string())
 
print(text)

The <global> command tells to python to change the scope for the <text> variable from local which is its default to global. Global is anything defined outside a function definition and a variable with global scope can be seen from anything and anywhere insidea python module even inside a function definition. So you don't need to use global for anything defined outside a function definition as defaults to global anyway.

OK OK OK.... I know you just throwing things to me asking why we need this extra complexity in our lives.

Well it happens that name collisions are a big pain in the... hat for coders. Let's face it people are not perfect and as an imperfect being nothing stops you from naming another variable with exact same name and carry on coding. Python has no problem with it, because when it sees a name again it assumes that you redefine the same variable, Python has no oracle skills to see that you made a mistake and you wanted to define a new variable. So you suddenly see your variable for some strange reason change values and don't know why. There is no error, the program does not crash and you may spend hours upon hours if you code is big enough to find the error.

So python as many other languages uses local scope to avoid this problem, now you know that anything defined inside a function <def> stays there and there is no way to conflict with another variable outside even if it uses the same name in another function definition. You are safe, but not from global variables, as you remember globals can be seen everywhere.

So the recipe is Don't use globals, or use as less globals as you can and you will never have to worry about name conflicts again.

You may wonder whether not using globals is possible at all, actually it is, if you remember we can pass data around with function through arguments and returns ( input and ouput) so we don't really need globals. But you as a coder will decide what type of programming suits you best.

8.5 Keyword Arguments


Last but not least are keyword arguments. One thing I forgot to mention is that with regular arguments we explained above its absolutely crucial that you respect their sequence, there is no way to make the first argument second, the second first, etc. Also its not possible to omit arguments, you have to use all of them at the sequence they have been defined. However all this changes when you use Keyword arguments. Ho Ho !

Keyword must ring a bell to you, if you remember key from dictionaries its very similar in this case.

def print_hello(text="hello", times = 10):
    for x in range(0, times):
        print(text)
 
 
print_hello()
print_hello(text = "man")
print_hello(text = "fish", times = 3)
print_hello(times = 4)
print_hello(times = 5, text = "bear")

Oooooh don't tell me I need to explain this ! Ah ok, I guess I should. What we observer here?

  • keyword arguments are your usual variable assignments
  • they are optional when we call a function because their assigned value is their default value, so we don't need to set it.
  • it does not matter in what order they are called cause we call them by name not sequence.
  • we can change their value (but not their default value) while we call the function

The most important thing is that they are optional and can be in any position making your function very flexible in the way it is called. This way you can have function doing a million different things. But that is bad thing, why? Remember the golden rule

A Function must be small, easy to understand, doing a single thing and with a name that says everything you need to know about it. This rule is absolutely crucial so remember it and will save you tons of time debugging errors and weird behaviors.

Keyword arguments are used quite heavily by blender so make sure you understand them before moving on, or else I wont be held responsible if you blow up yourself because of a weird python magic, however I will laugh, alot.

8.6 Conclusion


Oh boy that was big one wasn't it?

Well sorry but you need to learn this stuff if you have any hope to become an addon developer. Hehe don't worry if you don't feel confident, we are going to use every chapter of the "BASIC" part, in every addon we make together, so you will have plenty of time to get used to the syntax and functionality.

What I want you to keep from all this, is the following

  • Keep your functions close
  • Keep your globals closer

This may sound funny, but its also very serious.

  • Try to avoid the use of globals
  • try to make functions as small as possible
  • use names that tell everything we need to know about a function

The why and how we will learn them together when in PART II of this book we start making addons. So All I want from you is to have a basic understanding of PART I when we start putting everything to practice you will be able to say

"RELEASE THE KRAKEN"



Contents | Previous | Next