This is an old revision of the document!
Up until now, you should have had some interaction with the C language (or even, with C++). Normally, you would write your code in a source file, compile it with gcc and most likely get a few dozen errors. Eventually, you would end up with a binary executable file (i.e.: an ELF).
Another language that you've recently started learning is Bash. The main difference between the two is that Bash is actually an interpreted language, meaning that you have a program (also called bash; confusing, I know) that continuously reads your input and has pre-determined routines that it executes for known command patterns.
Python can be seen as a combination of the two. On the one hand, it's an interpreted language, just like Bash. Try to run python3 in your terminal and see for yourself. Notice how the prompt changed? The similarities with Bash though, pretty much end there. Python is closer to C/C++ in that it's better structured, implementing concepts from Object-Oriented Programming (OOP) and supporting multiple programming paradigms.
Why should you learn Python:
_do_not_touch_me()
). But if you're keen on it, by all means… do as you wish.In Python you don't have to declare variables. You just… use them. By assigning a value to a variable, you create it. If a variable with the same name already exists, you overwrite it. Just because you don't specify a type during declaration (as in C), it doesn't mean that the variable doesn't have one. The type of the variable is inferred from the type of the value that is assigned. Naturally, performing operations on variables of different types might create problems. Adding an integer and a float is permitted because both are numeric types. Adding a string and boolean however…
$ python3 Python 3.9.7 (default, Aug 31 2021, 13:28:12) [GCC 11.1.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> a = 'ana are mere' >>> b = 55 >>> type(a) <class 'str'> >>> type(b) <class 'int'> >>> c = True >>> type(c) <class 'bool'> >>> a = 3.1415 >>> type(a) <class 'float'> >>> 'ana are mere' + c Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate str (not "bool") to str
Let's take a look at each of the more common types in Python:
As you probably noticed in the snippet above, Python makes a distinction between different numeric types, such as float or integer. It, however, is not limited to only these two types. Complex numbers are also natively supported:
>>> a = 3 >>> b = 5 >>> c = 1 - 8j >>> isinstance(c, complex) True >>> c.real 1.0 >>> c.imag -8.0 >>> a *= 1j >>> a 3j >>> c * a - b (19+3j)
Notice how we we accessed the real and imaginary parts of the complex number c
? Being able to do this should immediately remind of structures in C, or classes in C++. We should investigate this further…
>>> help(c) >>> # use the arrows or PageUp / PageDown to navigate the help window >>> # press 'q' to exit back to the shell prompt >>> # yes, these are all comments >>> # no, you don't have to copy them :p
The help() function is an interpreter built-in that accesses the documentation of a specific type, module, etc. The output might be a bit too… complete. But if you scroll all the way down, you will find what we're interested in:
| conjugate(...) | complex.conjugate() -> complex | | Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | imag | the imaginary part of a complex number | | real | the real part of a complex number
So the complex type has two internal variables that hold the real and imaginary parts of the number. But what's this? It also has a method (i.e.: function) defined. Try to invoke conjugate() for c
. Does it work? Does it change the imag and real internal variables?
Well, that was an interesting detour. But let's get back to our numbers. As you might imagine, all the basic arithmetic operators work in python pretty much like they would in C; even the modulus operator. There are, however, two extra ones that might be useful: exponentiation and floor division:
>>> 5 ** 3 125 >>> # regular division can produce a float even if the operands are integers >>> 9 / 4 2.25 >>> # floor division acts like regular division on integers in C >>> 9 // 4 2
“What about bitwise operators?” Of course they're supported ;)
Here is a reminder if you forgot how the binary representation of numbers works.
>>> x = 8 >>> bin(x) '0b1000' >>> bin(x << 1) '0b10000' >>> bin(x >> 2) '0b10' >>> bin(x | 0b0010) '0b1010' >>> bin(x ^ 0b1010) '0b10' >>> bin(x & 0b0111) '0b0'
Strings in Python are more similar to the std::string in C++ than with those in C. Just a heads up, but this will be a running theme while you learn Python. Knowing about OOP and C++ is not necessary to understand the basic concepts in Python but it does help somewhat. Anyway, a string declaration works pretty much as you expect. Note that you can use both single and double quotes in their declaration. It doesn't matter which you prefer.
${MY_VAR}
). Double quotes do not. Make sure you don't mix up these concepts.
>>> # here, we use the + operator to concatenate four strings into one >>> # we use \ to break the current line and continue our command on the next >>> # do not copy the ... at the start; that's the multiline prompt >>> # bonus point if you recognize the quote ;) >>> s = "'I was there,' he would say afterwards, until afterwards " + \ ... "became a time quite devoid of laughter. 'I was there, the " + \ ... "day Horus slew the Emperor.' It was a delicious conceit, " + \ ... "and his comrades would chuckle at the sheer treason of it." >>> the length of the string can be obtained using len() >>> len(s) 230 >>> # we can access a single character from the string, but it's still a string >>> s[3] 'w' >>> type(s[3]) <class 'str'> >>> # we can also extract a substring >>> # if we specify [x:y], it starts from the letter indexed x, but stops at y-1 >>> # if we avoid specifying x, it will consider it to be 0 implicitly >>> # if we avoid specifying y, it will consider it to be len(s) implicitly >>> s[0:38] "'I was there,' he would say afterwards" >>> s[:38] "'I was there,' he would say afterwards" >>> s[210:] 'sheer treason of it.' >>> # here, things get funky >>> # you can use a *negative* index to count *backwards* from the end >>> s[-20:] 'sheer treason of it.'
As you can see, we access individual characters and substrings just like how you'd expect to access elements in an array. The fact is, everything we've just seen here applies identically to generic arrays. We'll see that, and more, in the next section. For now, look in help(str)
; identify a function to convert all characters to lowercase, and another to find a substring in a string. Apply both of them to s
in one command in order to find the string 'emperor' (all lower case).
One final thing about strings: formatting. There are multiple ways of doing this, but this is most similar to the formatting in printf() and honestly, it's the one I prefer :p
>>> '%-10s are %.2f mere' % ('Ana', 15) 'Ana are 15.00 mere'
When you think “array”, you might be reminded of the constant-sized arrays in C. But arrays in Python are closer in design to the std::vector container from C++, in that they can be arbitrarily resized at runtime. One difference, however, is that the elements contained in an array do not have to be of the same type (although it would be preferable if they were).
# notice how we don't need \ to split the command # the interpreter expects that we may want to extend the declaration on multiple lines >>> months = [ 'January', 'February', 'March', ... 'April', 'May', 'June', ... 'July', 'August', 'September', ... 'October', 'November', 'December' ] >>> # most of what we tested in the Strings section also applies here >>> len(months) 12 >>> months[0] 'January' >>> months[-1] 'December' # here, we display all months starting with the one indexed 3rd, up until the 3rd from the end >>> months[3:-3] ['April', 'May', 'June', 'July', 'August', 'September'] # here, we display every second month starting with January # the z in [x:y:z] is basically the iteration step # in this case, x and y didn't need to be explicitly stated >>> months[0:12:2] ['January', 'March', 'May', 'July', 'September', 'November'] >>> months[::2] ['January', 'March', 'May', 'July', 'September', 'November'] # here, we display months ranging from the one indexed 6th to the one indexed 0th, in reverse order >>> months[6:0:-1]