Beginning Python Programming — Part 2

That is referred to as a null terminator.

The slash tells the program to get ready for a command and the zero stands for nothing.

This is how string values are stored and let the program know when the string is finished while still allowing spaces to be used.

Numbers are a little different.

Numbers are stored as binary numbers.

Binary is easy to understand, start at 1 in the far right of the memory block and work your way left, multiplying the current value by 2 every time.

If you are familiar with graphics cards or memory sticks, it’s why we see 8-bit (Atari, NES), 16-bit (Sega Genesis, SNES), 32-bit (PlayStation), 64-bit (Nintendo 64), and so on.

In binary, if a position is 0, it is off, it’s false.

If a position is 1, it’s on, or true.

Based on this logic we only need to count the positions with a 1 in them.

Can you figure out the number in the image above?Now, this is a group of 8 bits of memory, that’s right, it is a full byte of memory.

Previously I said each character in a string was 2 bytes, that means we used 16 bits to store a character.

16-bits in binary gives us the maximum value of 256.

However, when we talk about positions, we always start with 0.

So 16-bits gives you a full range of 0-255.

If you are wondering how we can get characters out of that range, I’ll point you to the ASCII table where you can see the values for yourself.

You’ll even see the hidden characters such as the null terminator /0 as shown above.

Memory stores values in three places: static memory, the stack, and the heap.

Static memory and stack memory are quickly accessed, however accessing things from the heap is slow (in computer time).

While it may not seem slow to you, what could take a millisecond or less to load from the stack, could take 10 ms to load from the heap.

In most languages, you’d be able to choose where a variable is instantiated by its type.

In Python, the interpreter (the underlying engine) looks at your code and makes assumptions about where the variable should be stored in memory by its scope.

Its too early to talk about scope, but I promise we will talk about it in a future article.

Without further ado, let’s dig in.

Reference Types and PointersReference types use pointers to store values in memory.

Before we go too in-depth on how you use them, we really need to cover pointers.

If you look at a typical C program, you’ll see pointers used everywhere.

When we use char *name = “Bob";, we make a pointer by using *.

This tells the system, give me an address where I can store this value in memory.

The system then says “O.

K.

, you can use block 3 for your value.

” You then save "Bob" in block 3 (without quotes of course).

If you asked for the value of name using printf(name);, you’d just see the address, which may look something like 0x03 only much longer.

This is the hexadecimal representation of that block of memory.

If you want the value Bob then you’d have to use printf(*name); (both print statements are in C).

In C, if you wanted to change the value from anywhere you would use &name , which says to take the address of this value and do something with it.

As the value changes, you can use it immediately with the new value by referencing *name.

Under the hood, Python looks at your variables and does all of this * magic for you.

It makes every programmer's job easier because of it.

Because it handles all of this for you, you don’t have to worry as much about creating memory leaks, however, you do still need to worry about something called race conditions which we will cover later on.

The reason why I bring up reference types is because of the more advanced types that we will cover in the next part of this series.

I just want you to be familiar with how reference types work before we get started.

The way that I remember reference types is by imagining a treasure chest.

It doesn’t belong to anyone, but as soon as I find it, I write down where it is so I can come back to it any time I want.

If I want to look at the map to see where it is or to tell someone else, I use &.

If I want to open it and look at the treasure inside, I use *.

If I want to put something inside it or take something out, I still have to use * to get to it first.

When you store a value such as Bob in a C pointer, you actually put each letter in a separate piece of memory.

All you really know is where B is; the null terminator /0 tells the computer when to stop iterating through pieces of memory and return whatever value it has.

Think of it as a one button combo in Street Fighter.

I’ll talk more about this when we get to collection types, if you make the connection as to how strings work in C (also called C-Strings) based on the type I will be presenting, then you are correct.

As we continue, you’ll have some ideas.

If you want to learn C, C++ or Objective-C this is all very important information, however, with Python, they hide all of this complexity very well so you hardly ever have to worry about the & or the * operator.

Reference types can be stored in either the stack or on the heap.

You’ll know if a reference type is stored on the heap if memory is manually allocated by the programmer for it using malloc.

**Any variable created with malloc will not go away on its own when the program ends, you must call dealloc or free depending on your language in order to remove the value from memory, otherwise, it will stay in memory until the computer is restarted.

This is what is referred to as a “memory leak”.

Python handles all of this for you, so you don’t have to worry about malloc, dealloc, or free.

There is one exception where you can use del to clear memory where a variable is stored, but you usually don’t need to use this.

Photo by Kelly Sikkema on UnsplashCollection TypesCollection types are types that contain a collection of items.

There are two main types: lists and dictionaries.

Some languages refer to lists as arrays.

If you are needing to translate code between an example in another language and Python, know that these refer to the same type of collection.

Lists — Lists contain ordered like elements which are addressable by their index.

The index is defined by the number of items from the beginning of the list.

If we defined a list as such: my_list = ["eggs", "milk", "butter", "cheese"] we are able to retrieve each of those values by using ‘my_list[0]’, which would give us the value eggs because it’s 0 places from the start of the list.

Using this logic, if we wanted butter we would use my_list[2] because it is 2places away from eggs.

If we wanted to change the value stored in a list we could use my_list[2] = "Sugar"In C-Strings this surprisingly makes a little more sense.

When we stored Bob in a C-string, we actually made an array of characters (hence the char type).

If we said name[0] it would just return B because it was 0 pieces of memory from the start of the array.

If you go outside of the array you will run into problems.

Most of the time the computer will save you saying “index out of range” or something similar to that.

If you run into this issue while your program is running, it will crash.

More specific to Python, you can use slices of lists using the following syntax:my_list[1:3] which will return the 2nd and 3rd items in the list.

You can also use open-ended ranges with the following examples:my_list[:2] returns everything from the start to the second item in the list, my_list[1:] starts at the second element and continues to the end.

The way this can be understood is:my_list[<start position>:<stop position — 1>]You can also use negative numbers to exclude values at the end.

my_list[:-2] returns everything but the last two elements of the list.

Dictionaries — I’ll give you one guess at why this is named the way it is.

Dictionaries are similar to arrays in that they contain values of a common type, however, they are different as they are unordered.

They do contain an index but the index is typically a string value.

With that in mind, you might be thinking of a word in the dictionary followed by its definition.

That’s about how it works!.You can define a dictionary using the following:my_dictionary = {"Kevin": "Lead Minion", "Bob", "Determined Minion", "Stewart": "Rocker Minion"} The : separates the key from the value.

We can get at the value of any one of these by using: my_dictionary["Kevin"]You can set the value in a dictionary using the same syntax as a list just using the key to set the value.

Python doesn’t care about ensuring the values are of the same type, for instance:my_dictionary["Bob"] = "King Bob" is allowed.

 my_dictionary["Bob"] = 2 is also allowed.

You can declare and instantiate dictionaries by using my_dictionary = {}.

Dictionaries and Lists are used extensively in Python.

You need to be careful with lists to stay within the bounds of its elements.

If you try to access a value that doesn’t exist in a dictionary, you’ll receive a KeyValue error.

SummaryToday we learned about reference types, collection types, and a little bit more about memory.

What’s NextIn the next post, we will go over operators and None.

Most of the preliminary background information is over, and soon we will be having fun with programming.

Beginning Python Programming Part 3 — Operators and NoneIn the last post, we covered reference types, pointers, and collection types.

medium.

com.. More details

Leave a Reply