Using Python Commands

This section assumes you are very familiar with the concepts, terms and ideas for protograf as presented in the Basic Concepts , that you understand all of the Additional Concepts and that you’ve created some basic scripts of your own using the Core Shapes.

Note

Note that if you already know the Python programming language, you can skip this section, unless you have any uncertainty about any of these topics!

Background

Working with an actual programming language, if you’re not a programmer, can be a little intimidating. Hopefully though, by the time you’ve started to look at this section, you will already be somewhat comfortable with writing and running protograf scripts and therefore already on your way to controlling a computer through a written language.

The concepts and methods represented here are relatively small increments to what you likely already know, but should give you more flexibility in terms of the way you can write scripts — without adding too much complexity. These are not essential but may be very useful.

Introduction

As you may already have worked out; the normal operation of the script is to start with the first command and then go on to the next one and so on until the last one has been carried out - this is the normal or “default” behaviour of any program.

However, most programming languages have the concept of loops and if statements. These commands are used to change the default behaviour of the program in some way. Similarly, functions are used in many languages to create a set of items that must all carried out together, and which need to be used/activated multiple times.

Any statement or functionality that is part of the Python programming language can be used in a script if you want to. The ones below are just to give you some idea of “the basics”.

Loops

A loop represents a section of your script that you want to repeat a certain number of times.

If you were reading a recipe, for example, it might say: Add a cup of flour and add an egg and mix; add another cup of flour and add another egg and mix; add a third cup of flour and a third egg and mix. So this is really the same set of actions that gets repeated three times. You could rephrase this in a different way. Repeat three times: Add a cup of flour, add an egg, and mix. The two parts of this statement represents what happens in a loop. The first part indicates how many times the loop happens, and the second part is the action, or set of actions, that need to be repeated.

In a Python, or protograf, script, a loop can be set-up by using the following kind of statement:

for number in range(1, 4):
    add_egg()
    add_flour()
    mix()

In this case the first line is the loop set-up:

  • the for indicates that we want to set-up a loop

  • the range part limits how many times the loop will happen by using a start and end value inside a pair of brackets — the 1 and 4 respectively

  • number stores how many times the loop has happened so far (for the very first time the value of number will be set to the start value of 1); this is referred to as the loop’s counter

The first line ends with : to show that it is expected that more lines will follow that describe what must happen each time the program goes through the loop.

The lines immediately following this set-up line are all the actions that must happen each time. These lines must all be indented 4 spaces and lined up below each other to show they are part of the loop. (Note: ignore the actual words used here; they are just to indicate the concept of actions… more practical examples are shown below!).

Once the action(s) have been carried out, the program goes back to the line starting with the for — this is where the “loop” concept comes from — to increase the number value and prepare to carry out the action(s) again.

Note

When the loop counter’s value stored in number matches that of the end value, the loop will stop right away and not process any of the action(s) again.

In the case of protograf, a loop can be used to draw an item a number of times; for example:

for number in range(1, 4):
    Circle(x=1, y=number)

Here the value of y for the Circle will be set to a different number every time the loop operates:

  • for the first time it will have a value of 1 (one);

  • for the second time a value of 2 (two); and

  • for the third time value of 3 (three).

As noted above, when number reaches the value of 4, the loop ends right away. This loop will cause a Circle to be drawn in three different y locations on the page but with the same x location.

You can combine the value of the number with other information to do more complex kinds of operations. In this next example, the values for y will be 0.5, 1.0 and 1.5 over the three iterations of the loop - which is achieved by “halving” the value of the loop counter:

for y_location in range(1, 4):
    Circle(x=1, y=y_location * 0.5)

Note that we have used a different word in place of the usual number. It does not matter too much which word you use; so just pick one that makes most sense in terms of what you’re trying to achieve by using it.

The value of the loop counter normally goes up by 1 each time; but you can set a third value, inside the brackets, for the range that is a different increment number.

For example:

for number in range(1, 7, 2):
    Circle(x=1, y=number)

Here number takes on the values 1, then 3 and then 5; because the third value of 2 is added to the loop counter each time the loop operates.

When the loop counter value stored in number reaches 7, then the loop ends right away.

Multiple Loops

Multiple loops can be used to control different values. For example:

for y_location in range(1, 3):
   for x_location in range(1, 3):
        Circle(x=x_location, y=y_location)

Here the outer loop runs twice, setting values for both x and y. The outer loop happens twice, and for each time it happens, the inner loop happens twice. So there are actually four times i.e. 2 times 2 that the actions — in this case, drawing a Circle — are carried out.

Python has a shortcut for handling multiple loops that you can use at your discretion — its called zip (for more see zip function).

If you wanted to draw a Circle at three locations, in three different colors, you can store all of these in lists and then do the drawing in a loop.

For example:

x_pos = [1, 2, 3]
y_pos = [3, 2, 1]
fills = [red, green, yellow]
for x, y, fill in zip(x_pos, y_pos, fills):
    Circle(cx=x, cy=y, fill=fill)

If Statements

An if statement is a way to allow the computer to make choices based on the information available to it.

All of us have to make choices. When we are driving a vehicle along a road and we approach a traffic light, we evaluate the color of the traffic light and make a decision; if the light is green we carry on driving, but if the light is red we come to a stop.

In a similar way we can set up a statement to allow the script to behave differently according to information that it has.

So an if statement will look something like this:

if color == green:
    keep_driving()
else:
    stop_driving()

You’ll see that there are really two parts to the if. The first part is the condition that we are trying to evaluate - in this case what the value of the color is - and the second part is the alternative which is contained in the else.

As with the loop, a statement that ends with a : is followed by one or more lines that are all indented below each other; these represent the actions that are to be carried out in that part of the script.

The statement itself that forms part of the if, is termed a “true or false” check. This means that it’s a comparison of some kind. In this case, the script examines the value stored inside color and checks if it is “equal to” — by using the double-equals sign — the value of green. And because the script understands what is meant by green it can carry out this comparison.

Should the comparison be dealing with two values that are equivalent then the check is deemed to be correct or “true”, and so the actions that are in the first part of the if are carried out - in this case the keep driving action - and the rest will be ignored. However, should the comparison be false, for example because the value stored in color is red or orange, then the second part of the if statement will be carried out - in this case the stop driving action.

An if statement can be used inside a loop, for example:

for number in range(1, 5):
    if number < 3:
        Circle(x=1, y=number)
    else:
        Rectangle(x=1, y=number)

Here, the script will either draw a Circle or a Rectangle depending on the value of number: if its less than than 3 — the < comparison is a “less than” check — then draw a Circle, otherwise if its 3 or more, then draw a Rectangle.

This example is shown below.

lpi

An example of a loop and an if used together:

Blueprint()
Text(common=txt, text="Loop and If")
for number in range(1, 5):
    if number < 3:
        Circle(x=1, y=number, label=number)
    else:
        Rectangle(x=1, y=number, label=number)
PageBreak()

The value of number is used to locate the lower corner positions of the shapes that are being drawn.

The value of number can easily be seen as it is also used to create the text for the shapes’ labels.

Multi-part If Statements

An if statement can deal with multiple choices as well.

To continue with the driving example, we know there are three colors and so the program must handle all of them. Any options after the first one are handled with an elif prefix — short for “else if”:

if color == green:
    keep_driving()
elif color == orange:
    slow_down()
elif color == red:
    stop_driving()
else:
    pull_over()

In this example, the driver might be unsure what to do if the light has malfunctioned - best to be safe!

Functions

A function is the workhorse of a language. It allows you to define your “recipe” and then use that recipe multiple times with differing values for its properties.

Effectively, it allows you to create a mini protograf script inside your main script. As with loops, functions embed a set of steps to be carried out when they are activated, but functions are more powerful because they can allow control of the behaviour of any of the properties or commands that are part of them.

A function is simply created/defined by using a def command, followed by the name you want to give the function — using a word with no spaces in it — followed by the set of property names and their default values — if any. These properties are only available as part of the function, and represent aspects of that function that you need to be able to change every time the function is activated.

The def line is followed by one or more lines that are all indented and all aligned; these represent the actions that are to be carried out in that functions; this can include drawing of shapes, but could also involve use of loops and if statements.

When a function is defined, it is not activated; its only when you issue a command for it — name() — that it will perform the actions defined as part of it, and the script will carry on from the point where it was activated.

Function Example 1. Drawing Shapes

^

fn1

An example of a function:

def capitol(a=0, b=0, c="red"):
    Circle(
        cx=a+1, cy=b+1, radius=0.5, fill_stroke=c)
    Rectangle(
        x=a, y=b, height=1, width=2, fill_stroke=c,
        notch_y=0.1, notch_x=0.5,
        notch_directions="nw ne",)
    Triangle(
        cx=a+1, cy=b+1.5, side=0.25, fill_stroke=c)

Create(paper="A8", margin=0.25)
Blueprint()
capitol()  # uses default values
capitol(a=1, b=2, c="gold")
capitol(a=2, b=4, c="lime")
PageBreak()
Save()

The function named capitol has three properties that can be set, called: a, b and c. These, in turn, are used to help control or determine some of the properties of the three shapes that are drawn by this function.

The values have defaults - 0, 0 and "red" - respectively, which are used if no values are provided; this can be seen in the first example on the upper left.

If values are provided to a and b, these will change where the shapes are drawn; if a value is provided to c it will change the shape’s color.

These changes to the function’s properties can be seen in the other uses made of it above; the shapes are drawn in different colors and different locations.

The function is activated by simply including its name as part of the script, along with its brackets, such as in the line:

capitol()

or, if setting custom values for the function’s properties:

capitol(a=1, b=2, c="gold")

Function Example 2. Modifying Data

^

A function can also be used for a “non-drawing” operation, such as a calculation.

You can, for example, create one that generates or modifies the value of a property used by a shape.

The use of return is a key step for most functions; any time that it used, the function will stop operating and “go back” to the main part of script. The script will resume from the point where the function has just been activated.

def shift(a=0):
    return a + 1

Circle(cx=3, cy=3, diameter=shift())
Circle(cx=3, cy=3, diameter=shift(1))
Circle(cx=3, cy=3, diameter=shift(2))

Here the different circles each are assigned a slightly larger value by the function simply adding 1 to them.

This is a trivial example, but it serves to show how functions can be added and used by your script.