Quick reference
Variables
Arduino
int a;
int b = 5;
CircuitPython
b = 5
Arrays
Arduino
int a[5];
int a = {1, 2, 3, 4, 5};
CircuitPython
a = [1, 2, 3, 4, 5]
Discussion
Variables
Variables are like little boxes or pigeonholes in computer memory in which you can keep values.
To create a variable in C/C++ you must declare it. That entails giving it a type, a name, and optionally a value.
int a; int b = 5;
In CircuitPython you don't declare variables. They get allocated the first time you assign a value.
b = 5
You use the value of a variable in both languages simply by using the name.
int x = a_number; // in C/C++ x = a_number # in CircuitPython
In both languages, it is an error to use a variable that isn't known: either it hasn't been declared (in C/C++) or initialized (in CircuitPython)
In C/C++, variables are declared with a type, and are statically typed. They only have values of that type.
In contrast, CircuitPython is dynamically typed. Variables do not have an associated type, and can have values of different types at different times. There are advantages and disadvantages to each approach, but in reading someone's CircuitPython code, you should remember this in case someone reused a variable and changed its type.
Both languages have a way to create and manipulate collections of values.
"Ultimate" - Better than any other collection. Just don't click it.
(image from wikipedia, under fair use license)
Arduino
Arduino has only one way to create collections as part of the language: arrays. Since the language is C++, you are able to use most C++ libraries. With enough CPU performance and memory you can even make use of an Arduino version of the standard C++ and Boost libraries with their collection classes, but for the purposes of this discussion we'll assume you are using the basic language features.
An array is simple a fixed size, fixed order sequence of values. All values in a C array have the same type. In fact, since C is statically typed, the type of the array items is part of the type of the array itself.
For example, if you want to create an array that can hold 5 int
values in the variable a
, you would declare it as:
int a[5];
If the initial values are known at compile-time, you can initialize the array when it's created, and omit the size as it will be inferred from the number of initial values.
int a[] = {1, 2, 3, 4, 5};
To access a specific item in an array you use a subscript notation. This can be used to fetch a value out of the array, or to set it to a new value.
int x = a[0]; a[1] = x + 1;
CircuitPython
The basic CircuitPython collection is the List, which looks and works a lot like C's array. However, it's a far more dynamic structure: you can freely remove and insert items. It's length is a function of how many items are currently in it, not what it was created to hold. Since they are dynamic, you generally don't need to allocate them in advance. You create a list by enclosing the items in square brackets.
>>> a = [1, 2, 3, 4, 5]
As with C arrays, you use a subscript notation to access items.
x = a[0] a[1] = x + 1
CircuitPython's list provides far more functionallity than C arrays, but that's beyond the scope of this guide. CircuitPython also has additional builtin collections: tuples and dictionaries. See this guide on Python's basic data structures and this one more focused on lists and streams.
The scope of a variable is where and when it is available in the code. Both C/C++ and CircuitPython are lexically scoped. That means that a variable's scope is defined by the structure of the code. If you create a variable in a function, it is available in that function but not outside.
void f() { int a = 5; print(a); // 1 } print(a); // 2
The line at 1 is valid since a
is in scope. I.e. it's defined in the function f
and is available to be used. The line at 2, however, will cause a compile error because the name a
is not known at that point. The situation is similar in CircuitPython:
def f(): a = 5 print(a) # 1 print(a) # 2
Local and Global
The code above illustrates local state. i.e. local to a function. That's why referencing the variable from outside the function was a problem. Another scope is global scope. Things with global scope are available throughout the code.
int b = 1; void f() { int a = 5; print(a + b); } print(b); // prints: // 6 // 1
This works because b
has global scope so it can be used both inside and outside of f
. The same holds in CircuitPython.
b = 1 def f(): a = 5 print(a + b) print(b) # prints: # 6 # 1
What if we have variables with the same name, but in both scopes. Now things start differing. In C/C++ there is no trouble. The variable with the most local scope is the one used.
int a = 1; void f() { int a = 5; print(a); } print(a); // prints: // 5 // 1
However, things work quite differently in CircuitPython.
a = 1 def f(): a = 5 # 1 print(a) print(a) # prints: # 5 # 1
The assignment of a
is potentially a problem. This is because there is no variable in the local scope named "a", so one will be created because this is the first assignment to a
in this scope. For the rest of the function, this local variable a
will be used and the variable a
in the global scope will be untouched (and unused).
If that's what you want, good. However it's possible that your intent was to change the value of the global a
to be 5. If that's the case, then you have a problem. A tool like pylint will alert you to the fact that the name "a" from an outer scope (the global scope in this case) is being redefined. That will at least draw your attention to it. If you did want to be using the global a
, you can tell CircuitPython that is your intent by using the global
statement.
a = 1 def f(): global a a = 5 # 1 print(a) print(a) # prints: # 5 # 5
Now pylint might warn you that you're using a global statement. This is because global variables are generally frowned upon. But in a simple script that's fine [in this author's opinion]. In a larger, more structured program they have less use and you have ways to avoid them.
An interesting capability of CircuitPython and C/C++ doesn't share is being able to make closures. This is a somewhat more advanced feature and has been covered in another guide, so find out more there.
Page last edited March 08, 2024
Text editor powered by tinymce.