Learning Python
Tags: python, beginners
Published: 2020-08-22 13:36:56

As of now, I've spent a little over a month searching for my first software engineering position. While JavaScript proficiency seems to be one of the most sought after qualifications, Python, typically paired with Django, appears as a requirement nearly as often. I decided to spend some time with Python, and I plan to learn more about Django soon. The following describes my thought process and discoveries as I dive into the language for the first time.

Usually, the first step would involve downloading and installing the latest version of Python. Luckily, I had chosen to install Python 3.7 when I initially installed Visual Studio, and 3.8 was automatically installed with Chocolatey, which I chose to install along with Node.js. This brings us to the next obvious step, which is to write a groundbreaking 'Hello World' program.

Writing a 'Hello World' program involves discovering the languages primary function for outputting information to the console. Those who are familiar with Ruby will instantly recognize Python's `print()` function. There is, however, a slight difference between the signature of this function within the two languages. In Python, `print()` appends a new line to the end of the output, similar to Ruby's `puts()` function. If we want to avoid this behavior, we need to pass a second argument to the function.

```python
print("Hello World", end = '')
```

Obviously, this implies that the function has a formal parameter with the key of `end`, and its default value is `'\n'`. None of this truly matters at this point, but I like to have a solid understanding of how basic I/O works before I dive deeper into a language. I'd like to mention that, in accordance with Python's simplicity of the `print()` function for output, the `input()` function is used to capture input; imagine that.

So, now that we're reasonably comfortable working with I/O in a simple Python program, let's look at branching. While there are strategies for implementing switch statements in Python programs, the if/else structure is the only available option out of the box. Again, the syntax is extremely close to Ruby's, however, pay attention to the lack of a traditional block delimiter. This is due to the fact that blocks in Python are indentation delimited.

```python
x = 5

if x > 10:
    print("x is greater than 10")
elif x == 10:
    print("x is equal to 10")
else:
    print("x is less than 10")

# Output: x is less than 10
```

This is great, but what if we want to capture the value of `x` from the user at runtime, and display its value dynamically? We need to capture input from the user, using `input()`, convert the input to an integer, using `int()`, and format/interpolate the argument of each call to `print()`. Below is an example of the previous if/else statement which leverages some of the techniques available to us, to implement the desired result.

```python
x = int(input())

if x > 10:
    print(f"{x} is greater than 10")
elif x == 10:
    print("{} is equal to 10".format(x))
else:
    print("%s is less than 10" %(x))

# Input: 20
# Output: 20 is greater than 10
```

Next, we should learn how to work with collections in Python. Although there are many types of collections available to us, including, dictionaries, lists, sets, and tuples, we will focus on lists for the moment. Declaring a list in Python is similar to declaring an array in almost any dynamically typed language.

```python
my_list = ["A", "B", "C"]
```

Below are a few examples of list indexing.

```python
x = my_list[1]
print(x)
# Output: B

x = my_list[-1]
print(x)
# Output: C

x = my_list[1:]
print(x)
# Output: ['B', 'C']

x = my_list[-2:]
print(x)
# Output: ['B', 'C']

my_int_list = [1, 2, 3, 4, 5]
x = my_int_list[1:3]
print(x)
# Output: [2, 3]
```

Now let's look at a few strategies for iterating over our collection.

```python
for element in my_list:
    print(element)

for i in range(len(my_list)):
    print(my_list[i])

i = 0
while i < len(my_list):
    print(my_list[i])
    i += 1

# Output of each: A
#                 B
#                 C
```

Not too many surprises here, however, the `len()` function may stand out as a little odd to those familiar with other languages. This function will return the length of the the collection which is passed in as an argument, rather than being a method of the collection itself.

With a basic understanding of declarations and control structures, I figured it would be a good time to focus on encapsulation. Implementing a class is obviously the next milestone, but let's take a brief look at function definitions.

```python
def print_greeting(name = "stranger"):
    print(f"Hello {name}!")

print_greeting()
print_greeting("Brandon")

# Output: Hello stranger!
#         Hello Brandon!
```

Again, no real surprises. Now let's look into creating a basic file structure for our project, and building a simple class.

Let's start by creating two separate files in the path to our project, as follows.

```
main.py
person.py
```

Within person.py, let's build a simple class which will contain a property for both the first and last name of a person.

```python
class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
```

Now, within main.py, let's create a reference to our class, as well as an instance.

```python
from person import Person

person = Person("Brandon", "Weaver")
print(f"{person.first_name} {person.last_name}")

# Output: Brandon Weaver
```

Great, but let's assume I'm going to want the first and last name almost anywhere I reference an instance of `Person`. Do I really want to write `f"{person.first_name} {person.last_name}"` each time? We can set the default output of a class by overriding the `__str__` method of the class.

```python
class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __str__(self):
        return f"{self.first_name} {self.last_name}"
```

Now we make the necessary adjustments to main.py.

```python
from person import Person

person = Person("Brandon", "Weaver")
print(person)

# Output: Brandon Weaver
```

This way, we merely need to pass the object as an argument to `print()` to achieve the same result.

That about sums up what I was able to learn in my first few hours with the language. I hope anyone who is just now picking up Python, or programming in general will be able to gain some insight from my experience.

I look forward to spending more time with Python next week, and I'm interested to see how well my knowledge of Sinatra/Rails will translate to the Django framework.