python book of magic(1)

26
0 Introduction Welcome to "Python's Book of Magic". In this book you will find all the knowledge you need to gain a basic understanding of Python magic and how it can be used inside Blender. You will discover how fun, flexible and powerful Python is, and it will open a door of new possibilities. I am not a Python expert nor a Python authority. I am just a young, ambitious Python wizard like you. I started with just a few lines of code, and my addon has grown bigger and bigger from there. If you find errors, mistakes, or you have suggestions about the book, don't hesitate even for a second to contact me or even edit the pages yourself. That's the purpose of the wiki format. It's open, so anyone can contribute. 0.1 Goal The goal of this project is to offer python knowledge to you, the reader, avoiding (as much as possible) anything that isn't absolutely necessary in using Python inside Blender. My aim is to keep this book extremely simple even for those who have zero knowledge of coding or Python. Even though this book is about python, it concentrates solely on how Python can be used inside Blender. For detailed documentation, links are provided for those of you that want to dive deeper into Blender and Python concepts. Tip Each time you see blue text and when you hover your mouse over it, it becomes underlined, that is a link that to more detailed documentation on the relevant subject 0.2 Why learn Python? Before getting into the magic of Python, I have been asked by several people, "Can't I do the things I want with the GUI?- Why should I waste my time with coding?" There is no doubt that coding is a time consuming process. Developing an addon may take days, weeks, months, and even years. You don't click a button and suddenly your script appears. Like any young wizard, you will bury yourself inside books learning new spells and new techniques to achieve your goals. The advantage of coding is obvious. It can help you not only help to implement new features to Blender but also to automate tasks. How much time you spend on it is totally up to you. A python script can range from a single line that should not take you more than a minute to code, to thousands of lines that take months or years to develop. In reality you never truly lose time with coding because what you make is reusable. Think about it, if you make a piece of art it will be faster but you're never going to use it again, most art is used a few times, then we move to the next project. Scripts, on the other hand, stay usable for years. Blender 2.5 has many scripts that come from 2.49. So each time you finish a script you canlook back and realize it took you months to finish it, but it will be a script that you may use for years and, in some cases, a script you may use every day. Python scripts/addons/programs- call them as you like, they all mean the same thing- have added tremendous functionality in Blender. For example, you can create cities with Blended Cities , you can use loop tools as a new way to create meshes, you can change Themes with Theme Manager, you can again create cities Suicidator City Engine , the amazing Bsurfaces revolutionize the way you create meshes, or maybe you want to sync your animation to midi files with MIDI Driver and many, many more. You observed something? Yep, all these addons could be separate applications as well, as they offer a tremendous amount of new functionality. That's how powerful Python is.

Upload: unsharp-dev

Post on 08-Nov-2014

72 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Python Book of Magic(1)

0 IntroductionWelcome to "Python's Book of Magic". In this book you will find all the knowledge you need to gain a basic understanding of Python magic and how it can be used inside Blender. You will discover how fun, flexible and powerful Python is, and it will open a door of new possibilities. I am not a Python expert nor a Python authority. I am just a young, ambitious Python wizard like you. I started with just a few lines of code, and my addon has grown bigger and bigger from there.

If you find errors, mistakes, or you have suggestions about the book, don't hesitate even for a second to contact me or even edit the pages yourself. That's the purpose of the wiki format. It's open, so anyone can contribute.

0.1 GoalThe goal of this project is to offer python knowledge to you, the reader, avoiding (as much as possible) anything that isn't absolutely necessary in using Python inside Blender. My aim is to keep this book extremely simple even for those who have zero knowledge of coding or Python. Even though this book is about python, it concentrates solely on how Python can be used inside Blender. For detailed documentation, links are provided for those of you that want to dive deeper into Blender and Python concepts.

Tip

Each time you see blue text and when you hover your mouse over it, it becomes underlined, that is a link that to more detailed documentation on the relevant subject

0.2 Why learn Python?Before getting into the magic of Python, I have been asked by several people, "Can't I do the things I want with the GUI?- Why should I waste my time with coding?"

There is no doubt that coding is a time consuming process. Developing an addon may take days, weeks, months, and even years. You don't click a button and suddenly your script appears. Like any young wizard, you will bury yourself inside books learning new spells and new techniques to achieve your goals.

The advantage of coding is obvious. It can help you not only help to implement new features to Blender but also to automate tasks. How much time you spend on it is totally up to you. A python script can range from a single line that should not take you more than a minute to code, to thousands of lines that take months or years to develop.

In reality you never truly lose time with coding because what you make is reusable. Think about it, if you make a piece of art it will be faster but you're never going to use it again, most art is used a few times, then we move to the next project. Scripts, on the other hand, stay usable for years. Blender 2.5 has many scripts that come from 2.49. So each time you finish a script you canlook back and realize it took you months to finish it, but it will be a script that you may use for years and, in some cases, a script you may use every day.

Python scripts/addons/programs- call them as you like, they all mean the same thing- have added tremendous functionality in Blender. For example, you can create cities with Blended Cities , you can use loop tools as a new way to create meshes, you can change Themes with Theme Manager, you can again create cities Suicidator City Engine , the amazing Bsurfaces revolutionize the way you create meshes, or maybe you want to sync your animation to midi files with MIDI Driver and many, many more.

You observed something? Yep, all these addons could be separate applications as well, as they offer a tremendous amount of new functionality. That's how powerful Python is.

Page 2: Python Book of Magic(1)

But I can guess your second argument, "Those people know how to code and I am completely noob and my brain is not that smart, either". But that's the beauty of it. There is no requirement for being a Python coder. Anyone can do it.

Okay, assume that you code around 3 lines of code per day- 3 lines is maximum for 1 minute of typing code and 29 minutes of research. Depending on the circumstances, it may even be 1 minute of research, but I'm taking here of a worst case scenario. Twenty-nine minutes, assuming that you don't know a thing about Python, the Blender API, and you have never coded in your life before is not much time. Now this equals to 21 lines of code per week, 84 lines per month, let's say 1000 lines per year. Now imagine 1000 blender users do the same. That will equal to 1,000,000 lines of code per year for Blender. Blender is already around 1,000,000 lines of code, but It's "C" code and only10% is Python. Okay, now taking into consideration that each line of python is about 2-5 lines of "C" code as "C" is a much more complex and verbose language, this leads to the final result of 1000 users coding in Python creating an equal of 2 -5 million lines of code or to be more practical they advance blender 2 - 5 times every year. NOW IMAGINE THAT!!!

The secret of coding is that it may be a slow process, but it is a process that is well worth the time, and leaves you with a result you can use for years, if not decades. So, there is no doubt that users should learn python so they can automate tasks and also be able customize Blender. Even if you can only spend half an hour a day, in a few months you will gain very useful skills and improve your knowledge of programming tremendously. It's easy, it's simple, it can be done by EVERYONE, and if you dont stress yourself with unreasonable demands, it can be lots of fun.

Summary: LEARN PYTHON, AND IT WILL PAY YOU BACK MANY TIMES OVER FOR THE TIME SPENT.

What is Python ?Probably this is the very first question you will be asking . Python is a programming language . A programming language is a language that help the user communicate with the machine. The machine itself understand only machine language which nothing more that a series of 0s and 1s , known as the binary format. Those 0s and 1s operate like switches with 0 being "off" and 1 being "on". Of course coding in 0s and 1s is not ideal, so programming languages have been invented with the sole purpose of bringing coding as much close to a natural (e.g. English) language as possible.

Example Cosmac 1802 CPUCommand Mnemonic Hexadecimal Op-code

Load immediate LDI F8 1111 1000

Shift right SHR F6 1111 0110

Short branch BR 30 0011 0000

etc.

On my (PKHG) Cosmicos, I had to to fill memory bytes (really!) by pressing for each 1 a corresponding button, there where 8 for the op-codes and a button fill in the op-code!

First version had in total 64 (sixty four!!!) memory places and could make a tune via good sequence of commands like you can see in the table and an ear-hearer.

Programming languages that are close to machine code are known as "low level" , Assembly is the only low level programming language, while it can use some commands that make some sense like "MOV" for data movement , its still very much machine (CPU) dependent in its syntax . High level languages move away from machine code and are more English like, those are Java , C , C++ , C# , D , Objective C and many many more. Higher level Languages are much close to English language and generally they implement concepts that are not technical and not closely tied to the machine architecture, some of the are visual basic , ruby, runrev and others

Page 3: Python Book of Magic(1)

Why use Python ?Using python offers the following advantages :

•Python is a highly readable language. It is ease to read and understand Python source code.•Python is popular with million of coders worldwide•Python is powerful , used by demanding companies Like Google , YouTube and NASA•Python is flexible, able to run together with JAVA , .NET , Javascript and many more•Python is portable , without changing a line of code it runs in Windows , Linux and MacOS•Python is compact, code can be 2 -10 times shorter and simpler compared to C /C++ , JAVA etc•Python is easy to debug , cause the source code is short and easy to understand

Most importantly for you python is an excellent choice for absolute beginners. Visiting any programming forum or any user forum , when a poster asks "what language should I first learn" , python is by far the most recommended choice. Of course python is not the only language that easy to learn for a beginner but it is certainly one of the very easy if not the easiest.

How to install Python ?You don't have to worry about installing python with blender. Blender comes with python installed. Python is a folder containing an executable which is the python interpreter and the rest is the library of python commands and functions .If you want to use python without using blender you can get python from the python website

What is an interpreter ?As I said earlier your machine, your computer, understand only machine code. So a tool is needed to convert python commands to machine code and this what the interpreter does, it takes your python module , reading it line by line and converting any python command to machine code which then executes. Other languages use a compiler, again the compiler converts source code to machine code , but does not executes it. The beauty of the interpreter is that you can execute code interactively one command at a time and thus really test what works and what does not , making it easy to debug code , find errors, mistakes and test different approaches.

2 Python ConsoleIt does not take long to ask the magic question. How do I use python ? One way of using python interpreter inside Blender is through the Python Console. Python Console is one of the windows types , and it looks like this.

That's alot of text isn't it ? But it actually is easy to explain. The first line is the version of python and the version of the C compiler that was used to compile the python source. Python like Blender is made using the C programming language.

The next lines, on the other hand, are much more interesting. Command history is able to browse through the commands we have already entered , for now its empty because we have given it zero commands.

Page 4: Python Book of Magic(1)

Remove or deleting text is done using backspace or delete, we execute each command by hitting enter , autocomplete can be ignored for now and the rest are python libraries that have been loaded for us to make our life easier which also will not deal with now.

2.1 Basic Types2.1.1 Integer TypeOk without any further delay lets make some magic. ">>>" means "after this enter your command" let's type 1+2 . Don't forget to press enter to execute the command. You will see this.

Believe it or not you just made your first program. We have entered data and we have entered also a command. Data is 1 and 2 while the command is "+", also called an "operator" , a mathematical operator in this case. Python has all the usual mathematical operators.

Multiplication

and division

2.1.2 String Typewe can also print text on screen using the command , surprise surprise , print() !

This python command is called "function" , we know its a function because it starts with its name , print , and then open parentheses ,( , it takes a parameter , "this is pure python magic" and then closes parentheses , ")" . That is the basic syntax for any python function. But dont worry about exactly what a function is for now , we will deal with it later.

The "this is pure python magic" is called , string. Wait a minute , why it is not called a text ? Well its easy to explain. Type the following.

Wait , Wait ... This cant be right ! 1 + 2 does not equal to 12 !!! You are right it does not , but this is not what we did here , we did "1" + "2" . Both "1" and "2" are not python numbers , they are python strings and since python can do mathematical operations ONLY with numbers the + operator in this case is doing something different. It unites the 2 strings into one string so "1" + "2" , becomes "12". Let's try something different .

Oh Oh seems we released the evil Red Dragon. Also known as , python error. We hate those don't we? I mean everyone wants to type perfect code and never come through all the pain of correcting mistakes. But this is not an ideal or perfect world and neither are you . Python knows that and python is there to help and, in order to help, it is telling you what you did wrong.

Page 5: Python Book of Magic(1)

The error may seems a bit cryptic but it's not hard to decipher. The first line tells that it reports the first error it found, the second line tell us that the error exist in python console in the first line of code and third line tell us what the error is. TypeError means there is an error with the type and reading the rest of the line it's obvious that it expected data of type int and it got type str which is short for string. Well ok, but what is int ? Int is one of the types of numerical data , int is short for integer like 1, 2, 3 etc . Float is another numerical type with a floating point like 0.1, 0.003 , 3.456 etc

Types matter a lot for all programming languages including python, though python tends to be more forgiving with mixing different types in the same command. Okay, lets try something slightly different.

Ok now it works like a charm. We gave it a str and also an int as it expected. Or to be precise we used correct python syntax. Ok all this is good but I still have not explained why its called a string . Ok do this.

We got a string and then [0], what does that mean? Well a string is called a string because it is a string of characters, one character after another. In this case we tell it to give us the first character from the string which is of course is "y". Zero should not confuse , the computer uses 0 as the first of many types of continuous data. Zero here indicated first. Bear in mind that a character can be anything not necessarily just a letter. It can be "!" or "@" or "4" or of course any mix of that.

2.2 Text editorThe python console is pure fun and useful , but scripts and addons rarely are one line long. So we need something that will allows us to type and execute multiple lines as one unit. That unit is actually a regular text file with *.py extension called python module. A python application may have several modules but for now we will use only one. In order to edit a python module we will need an editor that can edit text files, and since all editors can edit text files we can use whatever we like. The preferred choice is an editor that can highlight python syntax, which means that it colors differently different python commands to make them easier to notice. Blender already comes with a text editor that it works very good for python coding. So choose as window type "Text Editor" and you should see this.

e

Ok next to "+ New" click the 3 buttons to enable them, they will display the number of lines, highlight syntax and wrap lines that exceed the boundaries of the text editor. Now click "+ Next" to create a new text , click

Page 6: Python Book of Magic(1)

on the popup to confirm , and then click "Text" menu and then "Save As" to save your file, remember to put a .py extension so if your python module is named myfirst you should type myfirst.py

Thats it ! we created our first python module and we are ready to use text editor for inserting multiple commands. Before doing any coding there is one more thing we need to do , we need to enable the OS (Operation System) console. We need to do this because we no longer use python console and python console works seperately from text editor and each time we run our module / script / program (they mean the same thing ) it wont report errors. Of course blender does report an error but that error most of time is incomplete and not suitable for us. If we enable the OS console / terminal we will be able to see our errors in full detail. How you do that it depends on your OS , for windows users you just go to the main menu , help menu and then click toggle system console , for macos and linux you need to run blender from the terminal and here it explains how to do that for all operation systems

3 Variables3.1 AssignmentOk let's get back to coding. Where were we ? Ah yes we explained Data types like , integers, floats and strings . But would it not be cool if we could store data in some way, after all our computers already store data in files on a hard disk , or on memory , online etc Data changes all the time so storage is a must.

Well programming languages store data in variables . Lets see this example.

a = 12

b = "I have"c = "ideas"

print(b+" "+str(a)+" "+c)Ok lets take this step by step. First line we define a variable called a and we store inside it the integer type of 12. Assigning variables is that easy , you basically provide the name then use the equal sign and then the value it gets. Second line we assign b the string "I have" and third line c is assigned "ideas". The next line takes a bit of explaining but is easy to figure it out. Its a print function as you remember its function cause it has a name and there is open parentheses , parameter and close parentheses. + is used as an operator to unite the strings and then there is another function inside it . already A variable can be of any python type, but as I said python does not like it when you mix different types , because our print function takes as parameter strings already if we did +a it would complain with an error cause it is an integer. So we use str(a) to convert a to a string.

In the same way we can use int() and float() to convert a type to an integer or float. Now if you type the code in the text editor and click the "run script" button (it can be found also in menu Text). The OS console / terminal will print "I have 12 ideas" . Notice that we used +" " as part of the parameter of the print function to type spaces between the strings. We could have as well included those spaces in the strings when we assigned the variables. The beauty of coding is that it allows us to be flexible.

3.2 User InputOk all that is nice but would not be more fun if we could communicate with the user in some way ? A program that does not interact with a user is not a very useful program. We can, using the input() function. Make sure you have your OS terminal / console open before running this code or it may freeze blender.

name = input(" What's your name ? ")print("Hello "+name+". My name is Python , nice to meet you." )This code will freeze blender but dont worry it wont harm it, actually it freezes because it waits for an input from us. Switch to the terminal/console window and you will see "What's your name ? ", go ahead and type your name and hit enter , if you typed John it will print "Hello John. My name is Python, nice to meet you". Isn't Python fun !

Page 7: Python Book of Magic(1)

I think the code above speak itself , but lets do some explaining. As you can see we assign to a variable the output of the function input(). Function can take input with parameters but also they can output data with returning types. In this case it returns data of type string and to be precise a string with the name we input. From there on we just unite the name variable with the 2 other strings to form the final print.

Ok lets try something else

number1 = int(input("Give me the first number : "))

number2 = int(input("Give me the second number : "))print( "If I add " + str(number1) + " and "+str(number2)+" it equals to

"+str(number1+number2))ok this is abit lengthier but its still easy to understand. The first thing you observe is that it is possible for a function to take as parameter another function. What we do in line 1 and 2 is that we take input from the user and convert it into integer, remember that input returns only strings. Then in the print statement we reconvert the variables to strings in order to unite them in one string and in then we add them together and the result is converted to string to which is then united to the final string.

There is another way of doing this

number1 = input("Give me the first number : ")

number2 = input("Give me the second number : ")print( "If I add %s and %s it equals to %d" %(number1 ,number2,

int(number1)+int(number2)))So this is doing the exact same thing, it only does it diffirently. %s inside our string in not actually part of string it only tell print that here it should place a string , which string is defined inside %() , so the first %s places the string value of number1 the second %s places the string value of number2 and %d places an integer which is the the result of converting number1 variable and number2 variable to integers and then adding them together. As you see with this way we don't have to convert our variables except only when we add them together. This process is called string formatting and it is useful for when you do alot of conversions between different types and want to join everything in a single string or find the first example kind of ugly. What you use is up to you. Want to learn more about string formatting ? Then go here.

3.3 Variable RulesThere is some rules to be followed for variables. First when you name them , you are allowed to use numbers inside but the name of the variable must start with a letter , so this is wrong

123 = 3and this is wrong too

123b = 3this is also wrong , cause variable names cannot contain spaces.

number 1= 3you could do this instead though and it will be valid

number_1= 3Another thing to remember is that a variable can be reassigned at any time so this is valid

number_1= 3

number_1 = 4the final value of the variable in this case will be 4. Variables can also be assigned values contained in other variables

number_1= 3

number_2 = 4number_1 = number_2in this case the final value for number_1 will be 4. However if we do this.

number_1= 3

number_2 = 4

Page 8: Python Book of Magic(1)

number_1 = number_2number_2 =10again the final value of number_1 will be 4 . It does not matter that the final value of number_2 is 10 , it does not effect number_1 after assignment.

3.4 Case SensitivityAnother EXTREMELY IMPORTANT RULE THAT APPLIES TO EVERYTHING IN PYTHON IS CASE SENSITIVITY. Case sensitivity is the capitalization of letters for example Var1= 5 and var1=5 are two different variables. That means that capitalization matters A LOT. So many programmers use it for naming like MyFirstVariable which is of course diffirent from myfirstvariable or mYfirsTvariable etc. Personally I don use capitalization to anything I define or assign , I prefer the use of underscores , so instead of MyFirstVariable I name it my_first_variable. For me this way its much easier to understand the name but is completely up to you. Bare in mind that capitalization applies to everything inside python so you need to be careful how you type your commands.

ListsYou may think that since we got integers and floats and strings we have pretty much finished with Data types. However python is a huge programming language, there is ton of stuff available . Of course the goal of this book is not to teach you all of python just enough to get you started and working with blender so we will keep things as simple as possible. However there are still some types that even though they are not absolutely necessary for making a working program they are absolutely necessary for keeping code simple and short. One of those types is list.

I can hear you wondering whether a variable can be assigned not one but several values. Lists do exactly that. Actually lists work very similarly to strings. Lets see how we assign a list to variable.

a = [ 1, 2, "hello" ,4 , 5.0 ]print(a)

print(a[2])a variable is assigned a list and we know its a list because we start the declaration with [ and end it with ]. Its important for python to recognize that this is a list because list are not the only way to assign multiple values to a single variable. Lists work similarly to strings in a sense that we access them via an index, a[x] will return the value of variable a from index x . In this case its clear that index 2 contains the string "hello" . Remember what we said earlier 0 is always first for computer so here value 1 is in index 0 , that is why "hello" is in index 2.

ok lets do the following

a = "hello"a[0] = "y"It gives this error --> TypeError: 'str' object does not support item assignment. Basically it says we are not allowed to assign value in a string in a specific index. Why ? Because strings are immutable , or read only. Remember the string is immutable not the variable if we add to the previous example a = "yello" its perfectly ok.

One may wonder why python implements mutable types that can be changed but also immutable types that cant be changed. The reason is of course to provide means to protect values the same way some of your files in your system are read only . Because they are very important files and you dont want anyone or anything messing with those files. The same happens with data inside a python module.

This is where a list comes handy because list is mutable and thus it can be changed.

a = "hello"

b=list(a)b[0] = "y"

Page 9: Python Book of Magic(1)

print(str(b))print("".join(b))so we assign a the string "hello" , b is assigned the value of a after it has been converted to a list , we can now change the h to y because lists are mutable but when we convert b back to string and print it we get spaces between and also "[" "," and "]". This happens because python converts the full declaration of the list to a string, but we dont want that . We want only the values joined together in a single string. So we use the function join.

You will observer here the weird dot between "" and function join. Types in python are objects and objects are groups of both data and/or functions. Actually there are alot of functions we can use for each types some are part of their object some are just built in functions so they dont need a dot in the syntax. Dont worry about objects right now and how they work we will talk about them when we explain Object Orientated Programming.

Lets see some cool functions about lists

names = ["john" ,"mary" ,"peter" ]

names.append("jane")print(names)Append is member function of the object list , and of course it appends another index to the list. Observe that we use the dot to access the function. We can also split lists.

names = ["john" ,"mary" ,"peter" ]names = names[0:1]

print(names)in this case it prints ['john'] . Observe that we dont use a second variable as names is reassigned the result of the split. However now names has lost its previous values. [0:1] means give me the indexes started from index 0 and ending on index 1 , index 1 is not included.

Another cool thing about lists is that they can be multidimensional , there is no limit to how many dimensions a list has. For example lets create a 3d list.

data3d = [ [["x1"],["x2"],["x3"]] , [["y1"],["y2"],["y3"]] , [["z1"],["z2"],["z3"]] ]print(data3d[0][1][0])The comma allows us to use multiple lines for this one statement making our code easier to read. Basically each dimension is a list inside another list for example this [] is one dimension list this [[]] is a 2d list this [[[]]] is 3d list and so on . So [0][1][0] means the first sub-sub-sub list from the second sub-sub list from the first sub list. It may get abit confusing to understand multidimensional lists so its better that you do your own tests to make sure you have a good feeling about it because multidimensional lists is something that you may use several times in blender as their advantages are obvious. The important thing to remember is that a dimension is just a list inside another list.

Bare in mind that when accessing a list the dimensions are optional for example using the above source code we could do data3d[0][1] or just data3d[0]. Try it and get a feel of how a list really works. There is no hurry , take your time. These foundations you build now they will help a lot in the future. There are many more things that can be done with lists , but I wont go to full detail, I only care of giving you basic knowledge but if you want to learn more you can visit the official documentation here.

TuplesTuples behave like lists the big difference is that they are not mutable so they cannot be changed , so they are preffered for sensitive data that should not change. This is how you define a tuple

names = ("john" ,"mary" ,"peter" )

Page 10: Python Book of Magic(1)

print(names)Line 1 is not a function because even though it has open , close parentheses and parameters that are separated via commas there is no name in front of the parentheses so this way we know its a tuple and not a function. Tuples like lists are accessed via index exactly the same way and like lists they can be multidimensional.

data3d = ( (("x1"),("x2"),("x3")) , (("y1"),("y2"),("y3")) , (("z1"),("z2"),("z3")) )print(data3d[0][1])

ReferencesBefore continuing to Dictionaries , I would like to explain a very important and fundamental concept of python that applies to pretty much anything. Its a concept that is crucial to understand because if you don't you will come against problems that will be impossible to solve. No worries though this concept is very easy to understand.

When you assign a variable lets say a =1 or name= "john" its easy to assume that basically what is happening is that the computer finds an address in memory and stores there number 1 and assign the variable to that address and then finds another address in memory stores there the string "john" and assign this address to variable name. So far so good.

But if we then do variable b=1 and name2="john" we assume once more that previous process is repeated. This assumption is wrong .What it really has happened here is that the previous address that has stored 1 now is assigned to both a and b and the address that has stored "john" is assigned to both name and name2. Ok so where is the problem ?

Lets try this

list1 = ["one","two","three"]list2=list1this means that now list 2 is ["one","two","three"] if we do

list2[0]=1this means that now list2 is [1,"two","three"] so far so good , but if we check list1 again list one is [1,"two","three"]

and if we do

list1[0]="bazooka"then of course list1 is ["bazooka","two","three"] but also lists2 is ["bazooka","two","three"]

This phenomenon is called "shared references" and it is used alot by Python in order to save memory. Imagine what would happen if our program generated thousands of lists all of them having the exact same data , that would be mean using loads of memory while in this case shared reference means that we can save 1000 times more memory and of course it is absolutely crucial when your application deals with megabytes or even gigabytes of data. One will ask how then we seperate the reference of list1 from the reference of list2, notice here that the entire list is referenced not just its indices. On way doing this is by copying the data in case of list it can happen this way

list1 = ["one","two","three"]

list2=list1[:]if you remember we used [0:2] to spit a list but in this case because there is no start and end index the list is copied index by index and thus the copy returned is assigned in a different memory address and we can change it without affecting the original data.

Page 11: Python Book of Magic(1)

So this all was references, we will discuss how we deal with deep copies (no reference) and references in later chapters, but it is crucial you remember the basic concept and that it applies to pretty much anything data wise inside python.

DictionariesDictionaries are by far my favorite type of data in python. Actually I think they are the favorite type of python data for most python wizards out there. Dictionaries are very similar to lists, like lists they store multiple types, like lists they are mutable so their data can be modified . like lists they are accessed via index but unlike lists their indexes can be not only numbers but names as well.

This is the basic syntax

record = { "Name" : "James" , "Surname" :"Bond" , "age" : 32 , "license to kill":

[0,23,12,45,67], 5 : "ok" }print(record["Name"])So there some things that are obvious from the start.

•First ,that python knows that this is a dictionary because of { and }•Second, the index names also called keys are strings like "name"•Third, a dictionary can contain a list•Forth, the key is separated from its data using the : symbol.•the print will print the string value "James" , since that is what corresponds to keyword "Name".

You may ask why keys dont use names like {name:"James"] . Because in this case python will actually try to search for a variable named name and use its data as a name for our key and this is not what we want here.

Another advantage of dictionaries over lists is that the numerical indices are not in a sequence, so you have index 1 and 3 for example (or more correctly key 1 and key 3) but not index 2 . This is useful when data is in not continuous.

I dont want to go very deeply into dictionaries, we will use them later , but more or less this what they do and how they behave.Two important functions you should remember is dict.keys() which return the names of the keys and dict.values() that returns only the values stored in the keys. Observe that both functions use dot sign so that means they are members of the object of dictionary type so in the above example you would do record.keys() or record.values()

" What if ? "Humans are amazing beings , capable for extraordinary good an evil, but what is most extraordinary is their ability to improve and adjust. There is not doubt that Knowledge is the ultimate power , the most arcane form of magic, without it we can not go forward , without it none of the amazing feats and accomplishments or even disasters of our civilization would have occurred. And what gives birth to knowledge is the ability to ask questions and seek answers . Every atom of knowledge has been conquered by asking the ultimate question.

WHAT IF ?

It stands to reason that we want to infuse this capability to code as well, that we want to build applications that are intelligent , that can take action according to decisions of the user and the programm itself. We want a program that is intelligent. We want a program that asks

WHAT IF ?

Page 12: Python Book of Magic(1)

Boolean TypeIn order to be able to answer any question we must be able to compare things, Comparison is an essential part of knowledge and decision making , without it we cant move forward. So its comes as no surprise that python has its own data type that can store result of comparison. And what most important comparison there is than whether a statement is True or False ?

Assigning a boolean type is straight forward

a = Trueb = FalseBoolean is an extremely basic type, it can only take a value True or False , nothing else. All this is good but how do we compare different data ?

#two assignments used to explain the four different comparisons of numbersa = 1

b = 5a > b

a < b a == b

a != b

Apart from the first 2 lines that are assignments, the rest means the following :

•Is a more than b? 1 is less than 5. Returns False•Is a less than b? 1 is less than 5. Returns True•Is a equal to b? 1 is not equal to 5. Returns False•Is a not equal to b? 1 is not equal to 5. Return True

There are some more comparisons possible between numbers <= (less or equal) as well as >= (greater or equal).

If statementBecause python is such an easy programming language all it takes to ask a "what if" question is a if statement like the following :

a =1b = 5

if a < b : print("Yes a is less than b")if a > b: print("No a is more than b")if a == b: print("Aaaah a is equal to b")This will give use the desired result , an alternative version is this

a =1

b = 5 if a < b : print("Yes a is less than b")elif a > b: print("No a is more than b")elif a == b: print("Aaaah a is equal to b")

Page 13: Python Book of Magic(1)

elif is not different from if other than the fact it needs at least one if to exist before it . Its just a way to make our code more readable and easier to understand, elif help us understand that comparisons are around a specific data set , and there is a relation between them. Observe that the equal comparison is == and not =. This extremely important to remember. = is used ONLY for assignment and == ONLY for comparison. Another way of doing this is this.

if (a=5) < (b =a) : print("Yes a is less than b")elif a > b: print("No a is more than b")else : print("Aaaah a is equal to b")Observe that we did the assignment inside the if statement this is completely legit, and that is why it is crucial to use == for equal comparison. Also we replaced the equal comparison with an else, this is also legit cause we already examine all the other possibilities in the previous 2 ifs so else can be only equal.

Another way

a =1

b = 5 if a < b : print("Yes a is less than b")elif not a < b: print("No a is more than b")elif a == b: print("Aaaah a is equal to b")not command reverses the boolean type. For example not True is False and not False is True. So in this case instead of a > b , we did , not a < b . The problem is that in this case we capture the possibility of a being equal to b , because in that case of a being equal to be means that a is not less than b . So in this case that a may be equal to b both last 2 prints will be executed. To correct it do the following.

a =1b = 5 if a < b : print("Yes a is less than b")elif not a < b and (not a == b): print("No a is more than b")elif a == b: print("Aaaah a is equal to b")and command takes 2 booleans and unites them in one boolean, the boolean is True if both booleans are true any other combination will result into False.

So in this case a <b is examined first then its boolean is reversed by "not" then a==b then not reverses the boolean of a==b and then and unites the 2 booleans into one. Remember always substatements inside ifs are executed only when if is true. In this case a =1 and b =5 so the following happens.

•1 < 5 -> True•not True -> False•1 == 5 ->False•not False -> True•False and True -> False•If statement returns False so print("No a is more than b") is not executed.

If we want one of them to be true we can use "or" command instead. We use also parentheses because parentheses dictates the order of execution so in this case first "not a == b" comparison is executed and then

Page 14: Python Book of Magic(1)

the "and" comparison. You can use parentheses also with mathematical operations again to dictate in what order the execution/operation will be performed. For example ((((1*2)*3)/4)+5)

Lastly but not least we can encapsulate if statements inside other ifs like this

a = 1

b = 5 if a < b : if not a<b: if not a==b: print("Yes a is less than b")we use always spaces to indicate that python statements/commands are associated with other substatements. So its possible this way to sub statement inside statements and of course sub sub statements and sub sub sub statements etc.In this case print("Yes a is less than b") will execute only if all associated ifs return True.

Another thing we can do with ifs is to examine whether something is part of something else. For example:

alist = ["john", "mary" , "david"]

name= "john" if name in alist : print("Yes the value of variable name is also inside the alist")Here we examine whether the string "john" exist also inside our list , alist , with the in command.

Dont worry if that stretches your brain abit more, you cant expect the magic to energize inside because you just read something, do your own test, experiment with this code and dont worry as long you have a vague understanding its more than enough because we are going to use all these concepts again and again and again , till they become second nature to you

Now what you waiting for ? Go make an intelligent python program, maybe use some user input as well with the input function make your own Borg Cube that can asks question and replies with intelligence . I guarantee you will have loads and loads of fun.

And if you hesitate to start your own Borg cube here is a sample to get you going

print("We are the Borg resistance is futile !!!")

being = input("What species are you ? ") if not (being == "human" or being =="HUMAN" or being == "Human"): print("We have assimilated your species")else: print("we have not assimilated humans yet") name = input("Whats your name ? ") if name == "oprah" or name == "OPRAH" or name == "Oprah" : print("We hate Oprah, aaaaahhhhh") print(" Box cube goes to warp speed and abandons the galaxy")else: print("%s prepare for assimilation" %name)

Exercise: Improving upon the above example

As you can see, when comparing strings for equality, case sensitivity once again matters. Typing out the different conditions quickly can become tedious, so let's make our life easier by simply converting the the string to lowercase beforehand. Luckily, the string type provides the utility function lower() for this:

"sPaMsPAmSPAm".lower()

Page 15: Python Book of Magic(1)

evaluates to:

'spamspamspam'(Note that we can enclose strings either in double or single quotes - it makes no difference that is relevant for now, but the python interpreter will put strings in single quotes)

Thus, this will work for any combination of upper and lower case input:

if not (being.lower() == "human"): print("We have assimilated your species")else: print("we have not assimilated humans yet")Of course, it would be a bit presumptuous even for the Borg to claim that they have assimilated all possible species. Let assimilated_species be a list of species known to have been assimilated by the Borg:

assimilated_species = ["Arturis","Ferengi","Talaxian","Kazon"](Completing this list is left as an exercise for the reader)

Remember the in keyword from earlier? We can use it to check whether a given element is contained in a collection (such as our list here):

if being.lower() in assimilated_species: print("We have assimilated your species")else: print("we have not assimilated %s yet" %being)(Python will use the equality criterion to determine this, thus string case sensitivity matters once more)

So, pay attention: your list of assimilated_species should all be lower-case! Or you use listcomprehension (in boldface) to change on the fly all your elements of assimilated_species too to lower-case:

if being.lower() in [el.lower() for el in assimilated_species]:

UNLEASH THE MAGIC!!!!!

7 LoopsSo far we had good fun, and if you have done homework and as I suggested you start to build up your Borg Cub game, you will soon notice that you repeating or copy pasting alot of code, and the more complex your code becomes that harder it is to read it and understand what is going on.

What will happen if you wanted to print numbers from 1 to 1.000.000 , would you really need to call print 1 million times , write 1.000.000 lines of code ? Obviously this is far from efficient and that is why Python implements loops . All loops do is repeating a fragment of your program .

7.1 While

The while loop is a lot similar to an <if> statement, you can even say that it is an <if> statement that can repeat itself until it returns the boolean type False. Lets print one million numbers

Note: a # ends a line for the Python interpreter (if not in a text!), therefore one can add comment inside of a code-line as you see below ;-).

x = 0 # any other (integer) valuewhile x < 1000000: print("x : ",x) x = x+1 # later you will use preferable '''x += 1''' ,

Page 16: Python Book of Magic(1)

# which does the same but allows at once runtime optimizationWe managed to compress one million lines of print statements (that abit less that the entire source code of blender) to just 5 lines ! Not bad, not bad at all. As you can see <while> acts very similar to an <if> , it examines the comparison and only if it returns true it executes it, and the big difference with <if> is that after execution of the sub-statements it repeats the examination of the comparison and the execution until the comparison returns False. When it returns False the looping/repeating ends. In this case it stops when x became 1000000.

This is still not an ideal way of coding it. <While> is used for repeating execution of code based on whether some specific criteria have or have not been met. If you want just to make a loop that repeat a specific amount of times then a For loop is more suitable syntax, but you can accomplish the same results with a while loop just fine.

7.2 For

In this case we can change our code into this

for x in range(1000000): #later you learn about #'''range(startvalue, endvalue, stepvalue)'' print("x : ",x)You already see the benefit, we decreased the code from 5 lines to only two. We could have written the above code < for x in range(1000000): print("x : ",x) > , pretty much anything that takes a <:> can be put in a single line like that. It makes sense for small code but it is not ideal for anything big that could create a long ugly line.

Th above code does not say much in such a tiny program but when you programs start getting bigger and bigger and less readable you will wish that you used <for> instead of <while> to make your life easier.

As you can see here there is no reason to define x , or increase x value by 1 for each loop, for syntax defines x for us and uses the built in function range to build a range of values between 0-1.000.000 which are assigned one by one to the x variable.

Observe that the last value x takes is 999.999 , so if you really want it to end at 1 million the range should be range(0,1000001)

<range> function could be used in many different formats. We could write the above code range(0,1000001), or range(0,1000001,1) which basically says "start from zero end in 1000001 increasing by 1 each time" , of course you can change the arguments of the function to anything you want and thus change how for counts and how many times is executed. If you omit the first and third argument they will default to 0 and 1 , so in this case we don't need to use them.

Another useful way of using loops is with the "in" keyword we talked about in the if statement Chapter.

x=["john","david","mary","tom","james","bill"]for y in x: print("x contains : ",y)Here y instead of a range of numerical values it get the values contained in the x's list indices .

Sometimes you need to know at which place the y was to be found too. To do that there is the is the possibility using enumerate and the code changes for example like this:

x=["john","david","mary","tom","james","bill"]for i, y in enumerate(x): print("x contains : ",y , " found on place ", i + 1)Note: if you start counting at zero and not at one', as Python does, change i + 1 into i.

Page 17: Python Book of Magic(1)

8 FunctionIf 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 .

Page 18: Python Book of Magic(1)

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

Page 19: Python Book of Magic(1)

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

Page 20: Python Book of Magic(1)

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

Page 21: Python Book of Magic(1)

"RELEASE THE KRAKEN"

9 ObjectsWe have already talked about objects in Chapter 4 Lists when we talked about "".join in strings. But we have not really explained what is an Object and why we need it. Learning why is crucial because the Blender Python API makes heavy usage of them

Objects like functions are a way to group things , both data (variables) and functions

9.1 Definition

class x: def __init__(self): self.a = 10 self.b = 20 def add_together(self): print("a + b = ",(self.a + self.b)) y = x()y.add_together() n = x()

n.a = 20n.add_together()Like <def> command for functions , <class> command is used here to define a class. A class is the blueprint of an object. What class tells python is how exactly each object ( also called "class instance" ) derived from this class should be constructed , which function it should include and which variable with which values.

In this case we define a class named <x>. This class has 2 functions. a) __init__() b)add_together()

__init__() is very important function used by classes to define instance variables known as "attributes". An instance is basically an object made using a class.

The second function is add_together() and the only thing it does is to add the 2 attributes together and prints out the sum.

y=x() may seem abit weird cause we have not really defined a x() function.But what really happens in this case is that x.__init__() is called. __init__ is actually the heart of an object and what makes objects so useful. They are called "constructor" in Object Orientated Programming for a very specific reason. It is called when an class instance is created and in this case it creates the instance variables. Instance variables are regular variables , the only special thing is that they are separate from other instance's variables.

We can create as many instances from the class x and we will create also variables that they will belong to those instances and they will not be affected by the variables of the same name in another instance.

So in this case even if we change a to 20 in the n instance , a remains 10 in the y instance. This way we isolate our values and variables without using new names for each instance. Isn't this fun ?

The <self> command here represents the instance. Its mandatory when we create a new function definition inside a class definition that the first parameter is <self>. Of course our functions can have as many parameters we want as we have described in the previous chapter. But as you can see we don't use <self> when we call an instance's function, nor when we access its variables.

<self> is used however to access the instance variables inside the class definition as the above example illustrates.

Page 22: Python Book of Magic(1)

9.2 Why we need Object Orientated Programming ?

Object Orientated Programming also called OOP is basically the type of programming that is based around the creation of classes and class instances, in short object creation. Bare in mind that even classes are objects , which means that they have their own functions (of course outside the ones that defined in class definition) that helps us manage and modify classes.

One may wonder why its necessary to use OOP to complicate our lives. Well it happens that it is not. Python allow you to do only procedural programming (use only functions) or OOP or even mix the two , its completely up to you. However Blender uses OOP heavily for the Blender Python API. So its absolutely crucial that we understand it before proceeding.

OOP generally is not desirable for programs of few hundreds lines of code. However when programs get bigger , it becomes more helpful to divide and sort data and functions into small manageable groups and this is one of things that OOP can do for us. Blender as you can imagine is rather big program , over a million lines of code so OOP can really make life easier here. However this is not the only reason.

9.3 Inheritance

A neat feature of OOP is "inheritance" . Its a very formal / scary word for something that is nothing more than a glorified "copy and paste" feature inside our source code.

class x: def one(self): print("I do one thing") def another(self): print("I do another thing") class x_child(x): def one_more(self): print("I do more than one thing") def another_more(self): print("I do more than another thing") y = x_child()y.one()

y.another()y.one_more()

y.another_more()The first thing that probably your eye will notice is that weird parentheses next to the class x_child command. Till now we learned that parentheses are used for both defining and calling functions but this is an exception. What class x_child is doing here is inheriting from class x . Or to be precise it copies x contents to x_child , including class definitions and any instance variables (but we have no instance variables in this example). Its not truly "copy n paste" as you will find it in a text editor but I think you get the idea.

That is why when we create the y instance from the x_child class we are able to call all of x functions as well as x_child functions.

Inheritance is a big deal in OOP because it allows us to abstract. That is we can make classes that implement general functions and child classes that can implement more specific functions. This way we create tree like

Page 23: Python Book of Magic(1)

hierarchies that keep everything neatly organised and its hard to get lost inside our own source code. This is what the Blender Python API does alot. You are going to see in the next part when we start creating our own addons that hierarchies play a huge role inside Blender and every part is nothing more than a branch of a big tree.

9.4 Summary

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

•Objects are a neat way to group variables and functions•An Object needs a class to be created, also called "class instance"•A class is a blueprint of the object , telling python how to make the object•A class can define instance variables•Instance variables of the same name can have different values in each instance and will be independent.•You need to use the self word when defining class functions and instance variables and when you access instance variables from inside the class•An instance is created when we call a class as if it was a function•we can access instance variables and functions using the dot <.> sign•Inheritance allows our classes to share instance variables and class functions

Is that all we can learn for OOP ? Far from it, we only touched the surface but we know enough to start making our addons. We are going to talk about OOP in the next part when we see OOP in practice . The only thing that remains for Part I is an introduction to the concept of modules. Here we go !

10 ModuleIts pretty hard to miss the functionality of modules inside python. No module means no python program. Modules are the source of our technomagic its where everything resides.

10.1 Modules and Bytecode

We have met modules before , if you remember, modules are nothing more than text files which the python interpreter uses to produce python bytecode. The Python intepreter is nothing more than a program, an executable, like anything else and bytecode is the intermediate between source code (module) and machine code which is the only thing your computer can understand. Bytecode files come with the extension *.pyc and what makes them unique is that they are cross-platform (meaning they will run unchanged on many different OS), and they are actually faster to execute than modules. Actually to be even more precise they are the only thing that python executes.

Each time you run a module you basically run its bytecode file. Python checks its date/time signature: if no bytecode file exists, python compiles it and thus creates it; if it exists but has a different date/time signature (meaning it was created in a different date and time) then the module is recompiled, if it is of the same date and time module it is ignored and python uses the bytecode file. The big advantage here is that the only slow down you will experience with this method is when the module is compiled, each time you re-run it will start way faster because no compilation will be performed.

10.2 What is a module ?

Sensible question my young apprentice. A module is a simple text file with a *.py extension. However a module can also be a python library

Page 24: Python Book of Magic(1)

10.3 Python libraries

Python libraries are modules that can be imported using the import statement.

Let's put one of our previous examples in a file called <mylib.py>. How you name your module does not matter as long as you use the appropriate name to import it .

class x: def __init__(self): self.a = 10 self.b = 20 def add_together(self): print("a + b = ",(self.a + self.b))in a file called <myapp.py> put the following

import mylib y = mylib.x()y.add_together() n = x()

n.a = 20n.add_together()Yes its that easy. Importing is a bit like copy and paste , however as you can see it creates a scope for us , exactly like Objects. We did mylib.x() , if we wanted to just do a y = x() then our import should be like this.

from mylib import *Again you see how much readable and simple python syntax is, isn't it a beauty. * here is use as "everything" (but is deprecated?!) you could as well have done this

or we could have imported only the x class

from mylib import xyou could even have done this

from mylib import x as myclasshere we import x from mylib but also rename it to mycalss so our instance creation will look like this

y = myclass()y.add_together() n = myclass()

n.a = 20n.add_together()So as you can see you can do some pretty nice tricks with import. One thing you need to remember is that you can import a module as many times inside your code as you want, but if it has been imported before, python does not import it again so that it does not waste time.

10.4 __main__

What import is doing is basically executing the module , so its like running the module in the first place. However that is not always desirable. Its possible to run a module in such that when is run from the python intepreter runs specific code and when import as module run different code. Here is how.

class x: def __init__(self): self.a = 10

Page 25: Python Book of Magic(1)

self.b = 20 def add_together(self): print("a + b = ",(self.a + self.b)) if __name__ == "__main__": print("you run mylib module, which contains the class named x ")the global variable here __name__ and its value string "__main__" informs us that the module is not imported but run from the python intepreter. If we did try to import mylib like we did in the previous section then the if would return False and the print would not execute.

This another technomagic spell for creating a module that can be both an application and a library at the same time, and behave differently when run as an app and differently when imported as a library .

10.5 Package

Putting every library feature in a single python module is perfectly possible, but from the first chapter I tried to teach you a single rule, a rule that I believe applies to every part of life and more in coding.

"DIVIDE AND CONQUER"

Or to put it more technically, divide your code into small manageable chunks that are easy to read, easy to understand and easy to relate with each other. So in this case we could divide a big library to several modules and import them . However there is a way to make all those modules group together with python packages.

A Python package is simple enough, it is basically a folder with __init__.py inside it and of course can contain many other modules too. That module works very similarly to __init__() function we used in the Object chapter and like __init__() __init__.py sets variables and even executes code that prepares our library for import. What that means differs from library to library and its completely up to the coder.

Packages are used by many addons that use several python modules, so its important to understand them.

You import the package like a module but not using the name __init__ , instead __init__ takes the name of you folder , so if your folder is named mypackage ,you will do a

import mypackageby the way the above will import only __init__.py inside the mypackage folder. Again what name you choose for the folder is completely up to you. This WILL NOT import any other module inside your folder but you could make your __init__.py import other modules so each time you do the above you will also import other modules , some of them , all of them, again its up to you. Python never ties your hand, you are the boss.

10.6 Summary

•Modules are nothing more than text files•Modules are compiled to python bytecode if they have not been compiled before•Modules can be used as python libraries too•We import modules with the import command•We can check whether a module is run as a app or imported as a library with __name__•Python packages can group multiple modules

10.7 End of PART I

YOU DID IT !!! you learned all the very basic of python language and you are ready to move to the next Part where we will finally start making some powerful addons. The knowledge you gained here is not useful just for making blender addons but for making any other python application. What we will learn from now on is

Page 26: Python Book of Magic(1)

only a variation of what we have learned so far. This is the source of your magic, before moving on make sure you understand and remember at least a substantial part.

So prepare your spell books, we go for a deep divide inside the magic of blender python....