If you're trying Python for the first time, it's a good idea to learn how to write a loop. Luckily, I've got you covered.

The post How to Write a Loop in Python: While and For appeared first on The Renegade Coder.

]]>

As this series grows, I often find myself revisiting the fundamentals. For instance, today we’ll be learning how to write a loop in Python. Luckily for you, there’s some bonus material on recursion as well.

In short, there are two core ways of writing a loop, while and for. If you’re looking for a tradition loop, opt for the while loop. Meanwhile, if you have some sequence or iterable to traverse, opt for the for loop. If you find a scenario which gets messy with a loop (e.g. tree traversal), don’t be afraid to fall back on recursion.

## Problem Description

When you first get into programming, you often go through a progression of different pieces of syntax. For instance, you might learn about printing and variables. Then, you might expand your knowledge into arithmetic and boolean expressions. If all goes well, you might even learn about conditionals.

As time goes on, you might ask yourself “but, what if I want to do something repeatedly?” Luckily, most imperative programming languages have a syntax for this called looping. Essentially, we repeat a task until we satisfy some condition.

Of course, if you’ve come from another programming language, you already know all about looping (or at least recursion). The trouble is getting used to the new syntax. Fortunately, we have several different solutions which we’ll take a look at in the next section.

## Solutions

In this section, we’ll take a look at three different ways to write a loop in Python. First, we’ll look at recursion, a functional technique. Then, we’ll dive into the two iterative techniques, while and for.

### Recursion

Before we dig into the various loop syntax in Python, I feel like it’s important to mention recursion as a concept. After all, we don’t actually need loops at all. We can get away from writing functions which reference themselves:

def recurse():
recurse()

In this example, we’ve written a function called recurse() which calls itself. If we run it, however, we’ll get an error:

>>> recurse()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
recurse()
File "<pyshell#1>", line 2, in recurse
recurse()
File "<pyshell#1>", line 2, in recurse
recurse()
File "<pyshell#1>", line 2, in recurse
recurse()
[Previous line repeated 991 more times]
RecursionError: maximum recursion depth exceeded

Of course, this makes sense. After all, if a function calls itself, then it will call itself, then it will call itself, then it will call itself… alright, my head is spinning.

Luckily, this is pretty easy to fix. We just need to add a condition which only calls the function under certain conditions (e.g. while the input is greater than zero):

def recurse(i):
if i > 0:
recurse(i - 1)

Now, if we can this function with some number, we won’t crash:

>>> recurse(5)

But, what is this actually doing? Well, let’s try printing something:

def recurse(i):
print(f'Input is {i}')
if i > 0:
recurse(i - 1)

Here, we used an f-string (learn more about those here) to show the input every time this function is called:

>>> recurse(5)
Input is 5
Input is 4
Input is 3
Input is 2
Input is 1
Input is 0

Check that out! We managed to create a function which executes 6 times when we enter a 5. As you can probably imagine, this mechanism can be used to do a lot of interesting things. If you’re interested in learning more about recursion, I’ve written an article all about it.

### While Loop

With recursion out of the way, let’s talking about loops. In Python, there are two main looping mechanisms: while and for. Typically, courses cover while first because it’s simpler. If you’re familiar with if statements, a while loop looks almost exactly the same:

while condition:
do_thing()

If the condition is true, the loop body executes just like an if statement. However, after the body executes, the condition is rechecked. If the condition is still true, we drop back into the loop body once again.

Naturally, we can write a loop which behaviors similarly to our recursion example. All we have to do is create a counter variable and count down on each iteration:

i = 5
while i >= 0:
print(f'Input is {i}')
i -= 1

In this example, we create a variable called i and give it a value of 5. Then, we kick off the loop by checking if i is greater than or equal to 0. Since it is, we drop into the loop where we print “Input is 5” and decrement i. Then, the process repeats. Of course, now i is 4 instead of 5. Overall time, i will decrement until it is -1, and the loop condition will fail.

In Python, while can be used to implement any indefinite loop. In other words, use a while loop when you don’t know how many iterations you’ll have ahead of time. For example, while loops are perfect for reading from files or prompting for input from a user. In the next section, we’ll take a look at an example of a definite loop.

### For Loop

In many imperative languages like Java, C, and Python, there is more than one way to write a loop. For example, in Java, there are at least four different loop syntaxes that I’m aware of (e.g. while, for, for each, do while). Since Python tries to keep things simple, the number of loop syntaxes are limited. As far as I know, there are only two: for and while.

Now, for loops in Python aren’t like for loops in other languages. Instead of providing a space to track an index, they operate more like for each loops in other languages. In other words, we need something to iterate over like a list. Let’s try recreating our while loop from above:

indices = [5, 4, 3, 2, 1, 0]
for i in indices:
print(f'Input is {i}')

To make this loop work, we had to create a list to iterate over. Clearly, this isn’t as convenient as the previous solution. Luckily, Python has a way generating these sort of iterables:

for i in range(5, -1, -1):
print(f'Input is {i}')

Here, we’ve created a loop which will count down from 5 to 0 just like all our other loops. To do that, we used the range() function which generates a list-like structure from the inputs provided. In this case, 5 represents the inclusive starting value, the first -1 represents the exclusive ending value, and the second -1 represents the step (i.e. how many values to skip and in what direction).

In general, for loops are more useful for iterating over sequences like lists, strings, or generators. In other words, they don’t work exactly like for loops in other languages—not without using a special function like range().

## Performance

At this point, I’m not sure it makes sense to compare the performance of these three constructs, but I already wrote three solutions that do the same thing. In other words, we’re just begging for a comparison. To kick things off, let’s store all three of our solutions in strings:

setup = """
i = 5
def recurse(i):
# Removed print for sanity
if i > 0:
recurse(i - 1)
"""

recursion = """
recurse(5)
"""

while_loop = """
while i >= 0:
# Removed print for sanity
i -= 1
"""

for_loop = """
for i in range(5, -1, -1):
pass  # Removed print for sanity
"""

Then, we can run out test as follows:

>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=recursion))
0.7848201999999986
>>> min(timeit.repeat(setup=setup, stmt=while_loop))
0.040824499999999375
>>> min(timeit.repeat(setup=setup, stmt=for_loop))
0.34835850000000335

One thing I found really interesting was the performance of the while loop. Then, I realized that my test was slightly inaccurate. Specifically, I had placed the i in setup, so it became zero after the first iteration. In other words, the while loop became a glorified if statement. When I updated my setup string, here were the results:

>>> setup = """
def recurse(i):
# Removed print for sanity
if i > 0:
recurse(i - 1)
"""
>>> while_loop = """
i = 5
while i >= 0:
# Removed print for sanity
i -= 1
"""
>>> min(timeit.repeat(setup=setup, stmt=while_loop))
0.3415355000000204

Now, that’s almost identical to the for loop—which makes sense to me. That said, I was reading some performance discussions on StackOverflow, and the for loop should be faster overall. Naturally, I had to investigate, so I updated both solutions for large numbers:

>>> for_loop = """
for i in range(100, -1, -1):
pass  # Removed print for sanity
"""
>>> min(timeit.repeat(setup=setup, stmt=for_loop))
1.2956954000001133
>>> while_loop = """
i = 100
while i >= 0:
# Removed print for sanity
i -= 1
"""
>>> min(timeit.repeat(setup=setup, stmt=while_loop))
4.765163399999892

Turns out that 100 was all I was willing to wait. Otherwise, this test may have taken all day. That said, even at a number this small, there’s an obvious difference in performance. Feel free to check out that discussion above for a further explanation of why.

## Challenge

Now that we know how to write a loop, let’s try something interesting. Let’s imagine we have a list of lists (aka a matrix):

my_matrix = [
[3, 5, 2, 4],
[5, 9, 4, 2],
[1, 8, 4, 3]
]

And, we want to total each row (inner list) and determine the average of all rows. Using the example above, we’d get the following row totals:

my_matrix = [
[3, 5, 2, 4],  # 14
[5, 9, 4, 2],  # 20
[1, 8, 4, 3]   # 16
]

Then, we’d average the totals:

(14 + 20 + 16) / 3  # 16.666666666666668

When we’re done, we’d report the result to the user.

While this seems like a pretty straightforward task for us, how would we train the computer to do it? In other words, how would we use the various loop syntaxes to do this (hint: you’ll might want to nest two loops)?

If you come up with a solution, drop it down below in the comments. Naturally, I’ll throw my own solution down there to get us started.

## A Little Recap

With all that out of the way, let’s revisit our solutions once again:

# Recursion
def recurse(i):
print(f'Input is {i}')
if i > 0:
recurse(i - 1)
recurse(5)

# While loop
i = 5
while i >= 0:
print(f'Input is {i}')
i -= 1

# For loop
for i in range(5, -1, -1):
print(f'Input is {i}')

If you liked this article, you might like joining the weekly mailing list, becoming a Patron, or browsing the shop. Right now, I have a Python 3 Beginner Cheat Sheet which includes the loop syntax from this article among other things. Check it out!

Otherwise, stick around and check out some of these related articles:

In addition, you might get some value out of the following products on Amazon (ad):

If none of that sounds interesting, no sweat! Thanks for checking out my work today.

The post How to Write a Loop in Python: While and For appeared first on The Renegade Coder.

]]>

Someone in the community thought it would be helpful to share this list of programming languages for game development. I figured you might enjoy it.

The post Want to Design Your Own Indie Game? Check Out These Programming Languages! appeared first on The Renegade Coder.

]]>

Online games were once all the rage–and for many, they still are. Previously, ‘Why I No Longer Enjoy Online Gaming’ covered a personal decision to veer away from online games like the game Overwatch. Without speaking for everyone, online gaming can be an exhausting pursuit, especially when you’ve dedicated the majority of your time to it and feel like your world revolves around it. While you can make friends, the online community can be extremely toxic, exclusive, and arbitrary.

Perhaps it may be time to consider going back to basics with single-player games, or even indie games by smaller developers or individuals. Many of the problems of online games stem from their development by huge corporations. Researchers at the University of York found how big developers include problematic elements like microtransactions and income-generating loot boxes in their games in an effort to make more money. This is what makes supporting up-and-coming games so refreshing, as most of them have been created for the sole intent of user enjoyment, you rarely see things done just for the sake of making money. A clever analogy in an HP article about the ‘13 Best Indie Games for PC’ describes this genre as the “garage bands” of programming due to their more off-beat mechanics and somewhat more compelling gameplay. These titles are programmed with pure passion, talents, and ideas, which makes them unique tokens created for likeminded individuals to enjoy.

If you’re interested in designing your own indie game, here are some programming languages to check out.

## C++

While C++ may be difficult to learn, it is one of the most commonly used languages as it lets you have more control over the hardware and graphical processes that are essential in video game design. As it uses object-oriented language, internal structures are used to organize code into reusable blocks. Many consider this the language to learn since many others stem from it. The action-adventure game Starbound was developed with C++.

## Java

The dynamism of the Java language makes it a preference for a lot of game programmers as it supports multithreading which uses less memory and maximizes CPU. Since it runs on a virtual machine, your game can be distributed easily as it’s compatible with different devices. Minecraft–one of the best-selling video games of all time–was originally created using Java by developer Markus Persson before selling it to Microsoft.

## HTML5

HTML5 allows you to modify the appearance of webpages, structure, and present web content. Multimedia content can even be added without Flash or a third-party plug-in, and websites can be accessed without the Internet, making it a considerable option for game developers. It’s also meant to work across platforms. The classic game Bejeweled is written with HTML5.

## JavaScript

JavaScript is one of the most popular scripting and programming languages in the world. It allows the creation of dynamically updated content, animation, and other multimedia properties. When used in tandem with Application Programming Interfaces, it lets developers implement difficult programs. The popular Angry Birds game runs on JavaScript.

The post Want to Design Your Own Indie Game? Check Out These Programming Languages! appeared first on The Renegade Coder.

]]>

Wanna see how things went for The Renegade Coder in 2019? Well, I put together another yearly review capping out at 2500 words. Woo!

The post 2019: Year in Review appeared first on The Renegade Coder.

]]>

As The Renegade Coder heads into its 3rd birthday, I figured I’d wrap up 2019 with a little review. In it, you’ll find everything from my favorite articles to my traffic metrics. Come along!

## Accomplishments in 2019

Unlike last year, nothing major happened for me this year. Sure, I complained a lot, but I didn’t have any major developments. That said, I’m happy to share a few major things that happened to me:

Beyond all that, I was just living life. If you’re interested in learning more about my year, check out my blog. I ranted quite a bit!

## Favorite Creations of 2019

In 2019, I started niching down to focus on my most popular content, Python articles. At the same time however, I also broadened to scope of the website to include teaching content. In addition, I started a YouTube channel. As a result, I figured this year I’d share my favorite creations—one for each month:

Also, I’d be happy to share my favorite YouTube videos, but I only made eight! If you’d like to see that collection grow, subscribe to my channel. Otherwise, feel free to share some of your favorites of the past year with me in the comments.

## Projects in 2019

This year, I worked on a lot of fun projects. Since I have plenty to write about, I’ll share all my updates in the subsections below.

### Sample Programs in Every Language

Unlike in previous years, the bulk of my contribution to this project came during Hacktoberfest. During that time, I merged A LOT of pull requests for code snippets, articles, and even some slick feature updates.

One of my favorite features that came out of this year is the addition of Glotter, a Docker-based blackbox testing library. Essentially, it allows us to pull up Docker images for each language and test all our code using a standard set of Python tests. Now, several of our languages and projects are fully tested. Read more about that here.

In addition, we hit several milestones with this project this year. For example, 100 of the code snippets/languages are now documented. In addition, we hit 25 projects. This ain’t no Hello World in Every Language anymore.

Overall, I’m excited to see this project grow, but I don’t plan to focus on it too much. As always, I’m sure Hacktoberfest will resurrect it again this year.

### CSE 5521: Artificial Intelligence I

Last semester, I took a course on artificial intelligence which had a handful of projects in JavaScript. For instance, one project asked us to right a handful of search algorithms for the 8 puzzle. By the end of that project, I had implemented depth first search, breadth first search, iterative deepening, and A*.

Later in the semester, we had to write the minimax and alpha-beta pruning algorithms for tic-tac-toe. If done correctly, it’s impossible to beat the computer!

Finally, we had to write a few linear and nonlinear regression algorithms. For example, we had to implement linear least squares and gradient descent.

Overall, I actually enjoyed the course. For once, I understood some AI. Unfortunately, my education classes were a lot more fun, so I had a hard time focusing on as the semester went on. Hopefully, I can carry this knowledge over into AI II.

### JuxtaMIDI

Recently, I published an article all about a tool I put together with a partner for a data visualization class. The goal of the tool was to generate a visualization of MIDI files, a type of music file.

While the tool is fairly nice looking, it doesn’t do a whole lot. Basically, it just plots the raw data from the MIDI files, so you can compare multiple files simultaneously. That said, I had a lot of fun making it, and I think it’s a fun tool for any tech folks also interested in music and data visualization.

### Side Projects

Outside of code, I also worked on a few side projects this year. For instance, I started a YouTube channel which now features 8 videos. In addition, I created a portfolio site. Not sure how it’ll help me going forward, but it at least makes me look more legitimate. Finally, I started a niche site called Trill Trombone which features 18 articles.

At the moment, I don’t have much to report from these projects, but I am excited to see them grow in 2020. Hopefully, I’ll have something exciting to share by this time next year.

## Metrics: 2017 – 2019

Now that I’m nearly three years into The Renegade Coder, I figured I’d start sharing some metrics in aggregate. In the following subsections, we’ll take a look at various statistics including page views, top posts, top traffic sources, and revenue. Without further ado, let’s dive in!

### Months and Years

Below is a table that shows my page views for each month since I started The Renegade Coder:

When I set out to create this website, I anticipated neverending growth. After all, even in the worst case, every post should get at least one view a year. In other words, more content means more viewership.

Unfortunately, that’s not really the case. As you can see, I had a very, very good year in terms of growth. In fact, my page views grew six-fold. However, that viewership peaked in May and has been on a major decline since then. As of December, I had less views than I did the previous December.

All-in-all, I’m not really concerned about this dip in views. As we’ll see later, I basically had a one-hit-wonder which finally stopped bringing in organic traffic. Meanwhile, several other posts were growing, so I feel like my views will be more diverse in the coming year. That said, it’s going to be tough to hit 300,000 with my current rate. We’ll see what we can do!

Also, it’s worth noting that I’ve been doing a bit of syndication. For instance, I often repost my coding related articles to dev.to with the canonical URL, so views there aren’t counted here. In addition, I’ve worked out a deal with Java Code Geeks where my reposted their regularly. Perhaps that’s hurting my view counts. Who knows!

### Averages Per Day

If you’re not a fan of raw data, here’s the same chart but with daily averages:

As you can see, we’re on a downward trend at the moment. My current plan for growth over the next few months is to get back to what got me views in the first place: Python content. Right now, I have four Python articles planned for January. Chances are I’ll have seven by the end of this month.

Then, I plan to start cranking out YouTube videos for all the Python content. If that becomes my brand, so be it! I really enjoy writing and speaking about the language.

### Top Posts and Pages

In 2019, one of my articles climbed to the top of Google where it saw outrageous success. In the span of a year, How to Check if a File Exists in Python amassed nearly 150,000 views. That said, it was nice to have a few other articles pulling their weight as well.

As mentioned already, Python seems to be working out for me. As a result, I’m going to become a fire hose for Python content over the next few months. If I see any sort of success like this, I’ll be content!

### Top Sources of Traffic

In 2019, I was driven almost entirely by traffic from Google. If anyone has any tips for me to diversify my traffic, let me know!

One thing I found interesting is how many developers use DuckDuckGo. Somehow, it managed to come in at second in terms of traffic sources with nearly 5,000 page views. That beats nearly everything but Google from the previous year. Also, I’m glad so many people want to save the planet with Ecosia.

### Top Countries

Once again, I took a look at where my traffic was coming from in terms of geography. According to the report, I get an overwhelming amount of traffic from my home country. That said, it’s only about a third of the total traffic for the year. In other words, two thirds of my traffic comes from other places! How cool is that?

Since 2018, it looks like I’ve lost my Israeli viewership but picked up some Spanish. That’s cool! I’ll be curious to see how this shakes out next year.

### Content Length

One metric that I thought would be fun to share is how long my content is on average.

As you can see, 2019 was the year for long form content. In other words, I was trying to shoot for 1000+ word articles, and I overshot that goal by 60% on average. Although, I’m not really surprise; this review alone is enormous.

Also, notice how this chart contains 2016. While The Renegade Coder didn’t exist until 2017, I actually transferred some content from a previous WordPress blog. You can find out the details in my first post.

### Total Revenue

As you may recall, last year my ad revenue was growing rapidly. However, in the summer, my page views started to drop. Without page views, you can’t really generate ad revenue, so I decided to investigate.

Obviously, I couldn’t be sure why I was losing Google ranking, so I decided to take an educated guess: perhaps my site was just too slow. As a result, I decided to perform an overhaul which resulted in a trashing of the ads. In other words, I no longer generate ad revenue. That’s why you’ll see a dip in revenue below:

Unfortunately, WordAds doesn’t pay out until you’ve made $100, and have$72 holding on. Perhaps if I get enough page views again, I’ll turn these on briefly to collect my check.

At any rate, I’ve found other ways to make an income. For instance, I started a Patreon again. In addition, I created yet another shop. Unfortunately, one has been quite a bit more successful than the other. Here are my earnings from Patreon since July:

If you recall, I also had a membership site which I converted to Patreon. Here’s the income from that:

Finally, I made another $4.55 from my store. If you add all this up, you’ll find that I made about$297.26 in 2019—at least according to QuickBooks. For someone operating a blog as a hobby, that’s not bad. For someone who puts as much time into this as I do, that’s terrible. After all, we’re just looking at revenue. I spent about \$545 in 2019 on website related costs like hosting and plugins, so I ended up a net negative.

You can learn more about my money making journey in my articles titled “Is the Work Finally Paying Off?” and “My First Ad Revenue Paycheck“. Here’s to better earnings in 2020!

## A Look Into 2020

At this point, I haven’t really made any plans for 2020. Right now, grad school is kicking my ass, and I’ve been on the verge of complete burnout for months now. As a result, I’m tempted to take a little break. That said, I’m afraid that a break could mean stalling out the growth of my project. Then, I’ll never be free!

As far as I know, I’m planning to focus on writing Python articles for the next few months. In addition, I thought it would be fun to start writing Git related content. After all, I think version control is extremely important, and I forget that people don’t know about it.

Finally, I want to hit 25 YouTube videos by the end of the year. Right now, I have 8, so that means I’ll need to make 17 more to hit my target. That’s a pace of just over 1 a month which I think is attainable. However, I have to remember that I publish two articles a week, so it might still be a lofty goal. It all depends on what my summer looks like.

At any rate, that’s all I’ve got! If you liked this review, check out last year’s review. It basically covers all the same information here, but it’s interesting to see where my head was at this time last year. Otherwise, thanks for stopping by! Here’s to another year of grinding.

The post 2019: Year in Review appeared first on The Renegade Coder.

]]>
How to Comment Code in Python: Inline, Multiline, and Docstring https://therenegadecoder.com/code/how-to-comment-code-in-python/ https://therenegadecoder.com/code/how-to-comment-code-in-python/#respond Fri, 17 Jan 2020 15:00:00 +0000 https://therenegadecoder.com/?p=20719

How do you comment code in Python? Turns out there are three different ways, each with their own advantages and disadvantages.

The post How to Comment Code in Python: Inline, Multiline, and Docstring appeared first on The Renegade Coder.

]]>

As we kick off 2020, I wanted to start getting back to some of my favorite content: Python “how to” content. Today, we’ll be looking at how to comment code in Python—a skill we should all have.

To summarize, there are three main ways to make comments in Python. To make inline comments, use the hash mark, #. To make multiline comments, use a hash mark on every line. Alternatively, use triple quotes, """. These kick off a multiline string which can be used to simulate comments. For more details, check out the options below.

## Problem Description

One thing I’ve done throughout this series is create content that targets a specific issue and address it with a few solutions. Of course, many of those solutions require some fundamental understanding of how Python works. In other words, at no point have I actually written any of those fundamental articles. Well, I suppose it’s better late than never.

Today, I want to look at a few ways of commenting code in Python. For those that don’t know, comments are ways of documenting code directly. Specifically, a comment is text that has no semantic affect on your programs. In other words, comments don’t do anything but provide context for the reader.

As an example, we might want to write some mathematical expression like the Pythagorean Theorem:

a_squared = 3**2
b_squared = 4**2
c_squared = a_squared + b_squared

Clearly, this expression resembles the Pythagorean Theorem based on variable name choices alone. However, not everyone will be able to tell at first glance. In other words, we might want to add a comment that tells the reader what the purpose of this expression is. For example, we might say “uses the Pythagorean Theorem to compute c^2.” How do we go about doing that? Luckily, this article will give us a few options.

## Solutions

In this portion of the article, we’ll take a look at a few different ways to write comments in Python. Keep in mind that this isn’t really an article on commenting styles or even a commentary on how to write comments. Instead, we’ll just be sharing the syntax. It’s up to you to figure out how you want to use the tools provided.

In Python, you can create a comment using the hash mark, #. As soon as this mark appears, everything following it until the end of the line is considered a comment:

# Uses the Pythagorean Theorem to compute c^2
a_squared = 3**2
b_squared = 4**2
c_squared = a_squared + b_squared

Since comments don’t start until the hash mark appears, we can comment the ends of lines as well:

# Uses the Pythagorean Theorem to compute c^2
a_squared = 3**2  # Computes a^2
b_squared = 4**2  # Computes b^2
c_squared = a_squared + b_squared  # Computes c^2

Normally, I’m of the belief that your code should be primarily self-documenting. That said, an inline comment here and there can be helpful for future readers—including yourself.

Fun fact: Python doesn’t have block comments. In other words, there is no built-in syntax for handling multiline comments. As a result, PEP 8 recommends using repeated inline comments for block comments:

# Uses the Pythagorean Theorem to compute c^2.
# First, we compute a^2 and b^2. Then, the
# expression is constructed as a^2 + b^2 and
# assigned to c^2.
a_squared = 3**2  # Computes a^2
b_squared = 4**2  # Computes b^2
c_squared = a_squared + b_squared  # Computes c^2

Again, these comments are probably excessive; their role is to provide an example of a block comment.

### Block Comments Using Multiline Strings

With all that said, it’s possible to simulate block comments with multiline strings:

"""
Uses the Pythagorean Theorem to compute c^2.
First, we compute a^2 and b^2. Then, the
expression is constructed as a^2 + b^2 and
assigned to c^2.
"""
a_squared = 3**2  # Computes a^2
b_squared = 4**2  # Computes b^2
c_squared = a_squared + b_squared  # Computes c^2

Now, that looks a little cleaner to me. In addition, it’s a bit easier to manage in source code in my opinion.

That said, keep in mind that this isn’t a true comment. We’ve instead created a string constant which isn’t assigned to a variable. In practice, this isn’t really an issue as the strings will get optimized out in the bytecode.

Another word of caution: sometimes this style of comment can be interpreted as a docstring. For example, if we insert this comment just below a function header, we’ll have created a docstring for documentation purposes:

def pythagorean_theorem(a, b):
"""
Computes the length of the squared third leg of a right triangle.
"""
a_squared = a**2
b_squared = b**2
c_squared = a_squared + b_squared
return c_squared

In this example, our multiline comment is actually a docstring which we can use to document the method:

def pythagorean_theorem(a, b):
"""
Computes the length of the squared third leg of a right triangle.
:param a: the length of the first leg of the triangle
:param b: the length of the second leg of the triangle
:return: a^2 + b^2
"""
a_squared = a**2
b_squared = b**2
c_squared = a_squared + b_squared
return c_squared

Then, this docstring becomes a runtime attribute of the function. In other words, we can inspect that attribute as follows:

print(pythagorean_theorem.__doc__)

As you can see, docstrings aren’t like comments in the sense that docstrings still exist at runtime—regular comments do not. Many IDEs and other tools can then extract these docstrings for documentation purposes. How cool is that?

## Challenge

At this point, I’d usually measure performance, but I didn’t feel like that would be applicable. Instead, let’s jump straight to the challenge!

Now that we know three different ways to comment code in Python, let’s talk about good commenting practices. In the comments below, share at least one tip you recommend when it comes to commenting code. Feel free to share anything from commenting styles to commenting etiquette. Bonus points for anything that’s Python specific.

As always, I’ll share my own tip below as well! If possible, I’d love to get a little discussion going. Depending on how it goes, I might compile the results in another article.

## A Little Recap

And with that, we’re all done. As always, here’s a little recap of our three ways to comment Python code:

# Here is an inline comment in Python

# Here
# is
# a
# multiline
# comment
# in
# Python

"""
Here is another multiline comment in Python.
This is sometimes interpretted as a docstring,
so be careful where you put these.
"""

If you liked this article, and you want to see more like it, hop on my mailing list. Alternatively, you can contribute even more by becoming a patron and getting your name on the Wall of Fame. Finally, I’d love it if you ran over to YouTube and subscribed to my channel.

Since you’re here, you might benefit from my Python 3 Beginner Cheat Sheet. It’s basically a two-page document of Python syntax including if statements, loops, and expressions. If you’re looking to learn more about Python expressions, I also have a fun lab you can try out.

Beyond that, you can always check out some of these related articles:

Otherwise, thanks for stopping by! I appreciate it.

The post How to Comment Code in Python: Inline, Multiline, and Docstring appeared first on The Renegade Coder.

]]>

Lately, I've been having fun writing Python lists (pun intended). As a result, here are some the coolest Python programming language features.

The post 8 Coolest Python Programming Language Features appeared first on The Renegade Coder.

]]>

After writing nearly 20 articles just about Python, I’ve decided to take some time to reflect on what I’ve learned. For instance, I recently wrote a compilation article which includes 70+ Python code snippets. Now, I’ve put together a list of some of the coolest Python programming language features.

## Coolest Python Features List

And without further ado, let’s take a look at some of the coolest Python features. If you think I’ve missed any, feel free to drop them in the comments.

### List Comprehensions

By far, my favorite feature in Python is the list comprehension. Honestly, the feature isn’t all that interesting; it’s just a convenient way to generate lists. That said, it’s a feature that I haven’t seen in any other popular language (e.g. Java, C, C++, etc.). As a result, I make sure to take advantage of it as often as possible. Here are a few examples:

# Generates a list containing values from 0 to 9
[i for i in range(10)]

# Generates a list of all even values from 0 to 9
[i for i range(10) if i % 2 == 0]

# Generates a list containing values from 1 to 10
[i + 1 for i in range(10)]

# Generates a list containing values from  0 to -9
[-i for i in range(10)]

# Generates all possible pairs between 0 and 9
[(a, b) for a in range(10) for b in range(10)]

# Shallow copies another list
my_list = [1, 3, 5, 7, 9]
[item for item in my_list]

Since a list comprehension creates a list, we’re able to work with the output like any other list:

# Generates a list containing values from 0 to 9
nums = [i for i in range(10)]
nums[0]  # returns 0
nums[1]  # returns 1

If you’re interested in learning how to write these yourself, I have an article just for you. In it, you’ll learn more about the syntax as well as a few application areas. If you have any of your own examples, feel free to share them in the comments.

### Generator Expressions

One of the nice things about learning the list comprehension syntax is that it allows you to also write generator expressions. After all, they’re very similar—one just saves you space. That’s right! Generator expressions don’t actually create lists. Instead, they provide the means for generating one item at a time of a list without ever constructing that list. Take a look:

# Generates values from 0 to 9
(i for i in range(10)])

# Generates values from 0 to 9
(i for i range(10) if i % 2 == 0)

# Generates values from 1 to 10
(i + 1 for i in range(10)])

# Generates values from  0 to -9
(-i for i in range(10))

# Generates all possible pairs between 0 and 9
((a, b) for a in range(10) for b in range(10))

# Generates a shallow copy of another list
my_list = [1, 3, 5, 7, 9]
(item for item in my_list)

Notice how similar the syntax is to the list comprehension. However, the application is slightly different. Instead of indexing the elements, we have to use a special function:

# Generates values from 0 to 9
nums = (i for i in range(10)])
next(num)  # returns 0
next(num)  # returns 1

Since a generator is an iterable, we can also get away with using the for loop syntax:

# Generates values from 0 to 9
nums = (i for i in range(10)])
for num in nums:
print(num)  # prints each item in the generator

Once we’ve exhausted every element, the generator expression becomes useless. In other words, we can only generate every element once. After that, we have to write the expression again.

### Slice Assignment

Have you ever wanted to replace entire sections of a list? Well, Python has a feature that allows you to do just that in a single line: slice assignment. Like slicing, slice assignment allows you to specify a region of a list. Of course, the difference is that slice assignment then lets you replace that region with whatever you want:

my_list = [1, 2, 3]

# Appending a list with slice assignment
my_list[len(my_list):] = [4]

# Prepending a list with slice assignment
my_list[:0] = [0]

# Replacing middle element
midpoint = len(my_list) // 2
my_list[midpoint: midpoint + 1] = [-2]

# Replacing arbitrary subsection
my_list[:2] = [3, 4, 5]

As I’ve mentioned in a related article, slice assignment doesn’t stop there. We can use any iterable on the right side. For example, we could use strings, tuples, list comprehensions, or even generator expressions. In other words, our previous two features can make an appearance:

my_list = [1, 2, 3]
my_list[len(my_list):] = (item for item in range(5))

Since learning about slice assignment in late 2019, I’ve been obsessed with it. As a result, I think it’s my second favorite feature right behind list comprehensions. Right now, I don’t have an article covering this feature in more detail, so you’re welcome to share some of your favorite examples in the comments.

### Iterable Unpacking (aka Destructuring)

If you’ve checked out my article on getting the last item of a list, you might recall that iterable unpacking was one of the solutions. The idea being that we can split a list into two pieces: the last item and everything else:

my_list = [1, 2, 3]
*remainder, last_item = my_list

Well, iterable unpacking can do more than retrieve the end of a list. For example, it can be used to swap variables:

a = 1
b = 2
b, a = a, b

Normally, we’d need three lines of code to perform a swap: one to create a temporary variable, another to overwrite one of the variables, and the last to copy the temporary variable to the other variable. With iterable unpacking, it’s a single line of code.

If iterable unpacking looks familiar to you, you might know it from its other name: destructuring. Oddly enough, I featured destructuring in an article covering some of my favorite features of any programming language.

That said, I don’t use iterable unpacking very often. If you have any good examples that would supplement this list, feel free to share them.

### Negative Indexing

Of all the features on this list, negative indexing is perhaps the most subtle. After all, many modern programming languages have some form of list indexing. However, few have a way of getting the last element of a list so elegantly:

my_list = [1, 2, 3]
last_item = my_list[-1]

In addition to being able to access list elements in reverse, we can also use negative indexing with list methods like insert(), pop(), and index():

my_list = ['h', 'e', 'l', 'l', 'o']
my_list.insert(-1, 'l')  # ['h', 'e', 'l', 'l', 'l', 'o']
my_list.pop(-2)  # ['h', 'e', 'l', 'l', 'o']
my_list.index('l', -2)  # 3

If you like negative indexing, you’ll be happy to know this feature doesn’t stop with lists. Feel free to use it with strings, tuples, and other sequences.

### Dictionary Comprehensions

Previously in this list, I mentioned list comprehensions. Apparently, that feature is so good that the developers decided to expand its capabilities to encompass other data structures like dictionaries. After all, wouldn’t it be nice to be able to generate a dictionary in a single line of code? Well, as of PEP 274, you can:

# Generates a dictionary of numbers to letters
{num: chr(65 + num) for num in range(5)}

# Generates the same thing
nums = [1, 2, 3, 4, 5]
letters = ["A", "B", "C", "D", "E"]
{num: letter for num, letter in zip(nums, letters)}

Typically, I use a dictionary comprehension to merge two lists into a dictionary. That said, I’m sure there are other use cases. Feel free to share some of your favorite it in the comments.

### Chaining Comparisons

In many modern programming languages, comparing values is a simple process. For example, in Java, I can compare two numbers as follows:

17 > 5

In this example, the result is a boolean, true. As a result, the following expression is illegal in Java:

17 > 5 > 1

Here, 17 > 5 evaluates to true. Then, the expression true > 1 is evaluated. Since this is nonsensical, the compiler crashes.

In Python, however, we can chain comparisons without any risks. In other words, the same expression above is perfectly valid, and it returns True.

Under the hood, each comparison is computed just like Java. However, each intermediate result is ANDed with the result of the other comparison. For example, 17 > 5 returns True. Then, 5 > 1 returns True. Finally, the results are combined by and which returns True.

Personally, I haven’t used this feature much, but it’s gotten a lot of attention on the development end. For example, PEP 535 mentions a few updates to the chaining protocol. If you know of any cool use cases for this feature, let me know in the comments.

### f-Strings

Finally, we come to one of my favorite “new” (PEP 498) Python features, f-Strings. Normally, when we create strings for debugging, we lazily print them with concatenation. If we’re clever, we might use some of the string formatting techniques. Now, we can get the best of both worlds with f-Strings:

age = 25
name = 'Jeremy'
print(f'My name is {name}, and I am {age}')

In this example, we’ve created a string from two variables: name and age. All we had to do was prepend our string with an f. Then, we can place any expression we want in braces, and it will be interpreted. For example, age is a number which is automatically converted to its string representation.

I really love this f-String syntax because it solves a lot of common string formatting issues. For example, it makes string formatting very easy to read (unlike concatenation). Likewise, it makes it obvious what the output string will look like (again, unlike concatenation). Finally, there’s no issues with positioning of variables (unlike string interpolation). What you see is what you get.

While f-Strings are really helpful, I don’t find myself using them beyond debugging. Do you have any examples you’d like to share?

## Honorable Mentions

As someone who really loves working with Python, I had a hard time keeping this list short. As a result, here are a few additional features that didn’t make the cut:

• For/Else loops
• Imaginary numbers
• Any() and All()
• Returning multiple values (tuples)
• Arbitrarily large integers
• Keyword arguments
• Sets
• Joining strings
• Multiplying strings
• Walrus operator
• String interpolation
• Slicing

Of course, with how enormous the standard library is in Python, I’m sure there are even more clever bits of syntax. In addition, Python development is very active, so I wouldn’t be surprised to see even more features in the future. Perhaps I’ll update this list from time to time as new features appear.

## Recommendations

With all that said, thanks for sticking around to check out this list. Over the next couple months, I’ll be focusing more on Python and Git content, so expect to see more articles like this in the future. If there’s anything you’d like to see, drop a note in the comments or feel free to contact me directly.

In the meantime, support this website by hopping on the mailing list, becoming a patron, or exploring the shop. Otherwise, keep browsing the following related articles:

Finally, you might get some value out of the following Python resources from Amazon (ad):

Otherwise, thanks again for your time. I appreciate it!

The post 8 Coolest Python Programming Language Features appeared first on The Renegade Coder.

]]>

Whether or not you know how to add an item to a list in Python, you'll want to read this article just to learn about slice assignment. Trust me.

The post How to Add an Item to a List in Python: Append, Slice Assignment, and More appeared first on The Renegade Coder.

]]>

Lately, I’ve been thinking about new Python topics to write about, so I took to Google. When I searched “Python how to”, “Python how to add to a list” popped up first. Since this must be a popular search term, I decided it was worth an article. In other words, today we’ll learn how to add an item to a list in Python.

To save you some time, you can start adding items to a list right now with the append() method: my_list.append(item). If you have more complex needs, consider using extend(), insert(), or even slice assignment. See the rest of the article for more details.

## Problem Description

For people who come from other programming languages, tasks like creating and adding to a list can be daunting. After all, almost every language supports lists in one form or another (e.g. arrays, lists, etc.), but not all languages have the same syntax. For instance, here’s an example of an array in Java:

int[] myArray = new int[10];
myArray[0] = 5; // [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Here, we’ve created a fixed-size array of 10 elements, and we’ve set the first element to 5. In other words, we don’t really add elements to arrays in Java. Instead, we modify existing elements.

Meanwhile, in a language like Rust, arrays are declared a little differently:

let mut my_array: [i32; 10] = [0; 10];
my_array[0] = 5; // [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]

In Rust, we have to explicitly declare the array as mutable with mut. That way, we can modify the array just like in Java. In addition, the syntax is quite a bit different. For example, we set the type to i32, the size to 10, and all elements to 0.

Of course, there are languages with built-in lists much similar to what you might find in Python. For example, Ruby’s (dynamic) arrays can be created and modified as follows:

my_array = []
my_array << 5  # [5]

Unlike the previous solution, we didn’t have to setup our array with a certain size. Instead, we’re able to start with an empty array. Then, we pushed a 5 into the array, and called it a day.

Oddly enough, in Python, the syntax for creating a list is quite similar:

my_list = []

## Solutions

In this section, we’ll take a look at various ways to add an item to a list in Python. Since this task is pretty straightforward, there aren’t very many options. In fact, that’s sort of by design in Python (i.e. “There should be one– and preferably only one –obvious way to do it.”). That said, I’ve included a few silly solutions to keep this piece interesting.

### Add an Item to a List Statically

To be honest, this is sort of a nonanswer. That said, if you want to populate a list, you can declare the elements statically:

my_list = [2, 5, 6]

Rather than adding the items one at a time, we’ve decided to initialize the list exactly as we want it to appear. In this case, we’ve created a list with three items in it: 2, 5, and 6. In the next section, we’ll look at our first way to modify an existing list.

### Add an Item to a List by Slice Assignment

In Python, there is this very peculiar piece of syntax that I only just recently learned about called slice assignment. While slicing can be used to return a section of a list, slice assignment can be used to replace a section of a list. In other words, it’s possible to write an expression which adds a value to the end of a list:

my_list = []
my_list[len(my_list):] = [5]

Here, we have an expression which replaces the end of the list, which is an empty list, with a list containing a single value. In essence, we’ve added an item to the end of the list.

Interestingly enough, this syntax can be used to replace any part of a list with any other list. For example, we could add an item to the front of the list:

my_list = [1, 2, 3, 4]
my_list[:0] = [0] # [0, 1, 2, 3, 4]

Likewise, we can replace any sublist with any other list of any size:

my_list = [1, 2, 3, 4]
my_list[:2] = [6, 7, 8, 9] # [6, 7, 8, 9, 3, 4]

Fun fact: we aren’t restricted to lists with this syntax. We can assign any iterable to the slice:

my_list = []
my_list[:] = "Hello" # ['H', 'e', 'l', 'l', 'o']
my_list[:] = (1, 2, 3) # [1, 2, 3]
my_list[:] = (i for i in range(5)) # [0, 1, 2, 3, 4]

When I first added this solution to the list, I thought it was kind of silly, but now I’m seeing a lot of potential value in it. Let me know if you’ve ever used this syntax and in what context. I’d love to see some examples of it in the wild.

### Add an Item to a List with Append

On a more traditional note, folks who want to add an item to the end of a list in Python can rely on append:

my_list = []
my_list.append(5)

Each call to append will add one additional item to the end of the list. In most cases, this sort of call is made in a loop. For example, we might want to populate a list as follows:

my_list = []
for i in range(10):
my_list.append(i)

Of course, if you’re going to do something like this, and you’re not using an existing list, I recommend using a list comprehension:

my_list = [i for i in range(10)]

At any rate, append() is usually the go-to method for adding an item to the end of a list. Of course, if you want to add more than one item at a time, this isn’t the solution for you.

### Add an Item to a List with Extend

If you’re looking to combine two lists, extend() is the method for you:

my_list = []
my_list.extend([5])

In this example, we append a list of a single element to the end of an empty list. Naturally, we can append a list of any size:

my_list = [3, 2]
my_list.extend([5, 17, 8])  # [3, 2, 5, 17, 8]

Another great feature of extend() is that we’re not restricted to lists; we can use any iterable. That includes tuples, strings, and generator expressions:

my_list = []
my_list.extend("Hello") # ['H', 'e', 'l', 'l', 'o']
my_list.clear()
my_list.extend((1, 2, 3)) # [1, 2, 3]
my_list.clear()
my_list.extend(i for i in range(5)) # [0, 1, 2, 3, 4]

Of course, like append(), extend() doesn’t return anything. Instead, it modifies the existing list. Also like append(), extend() only adds the iterable to the end of the other list. There’s no way to specify where the input iterable goes. If you want more control, I suggest slice assignment or our next method, insert().

### Add an Item to a List with Insert

If append() and extend() aren’t doing it for you, I recommend insert(). It allows you to add an item to a list at any index:

my_list = []
my_list.insert(0, 5)

In this case, we inserted a 5 at index 0. Naturally, we can choose any valid index:

my_list = [2, 5, 7]
my_list.insert(1, 6) # [2, 6, 5, 7]

And just like with regular list syntax, we can use negative indices:

my_list = [2, 5, 7]
my_list.insert(-1, 9)  # [2, 5, 9, 7]

How cool is that?! Unfortunately, however, we can’t really insert an entire list. Since Python lists don’t restrict type, we can add any item we want. As a result, inserting a list will literally insert that list:

my_list = [4, 5, 6]
my_list.insert(1, [9, 10])  # [4, [9, 10], 5, 6]

Luckily, slice assignment can help us out here!

## Performance

With all the solutions ready to go, let’s take a look at how they compare in terms of performance. Since each solution doesn’t do exactly the same thing, I’ll try to be fair in how I construct my examples. For instance, all the following examples will append a value at the end of each of the sample lists (ignoring the static assignment solutions):

setup = """
empty_list = []
small_list = [1, 2, 3, 4]
large_list = [i for i in range(100000)]
"""

static_list_empty = "empty_list = []"
static_list_small = "small_list = [1, 2, 3, 4, 5]"

slice_assignment_empty = "empty_list[len(empty_list):] = [5]"
slice_assignment_small = "small_list[len(small_list):] = [5]"
slice_assignment_large = "large_list[len(large_list):] = [5]"

append_empty = "empty_list.append(5)"
append_small = "small_list.append(5)"
append_large = "large_list.append(5)"

extend_empty = "empty_list.extend([5])"
extend_small = "small_list.extend([5])"
extend_large = "large_list.extend([5])"

insert_empty = "empty_list.insert(len(empty_list), 5)"
insert_small = "small_list.insert(len(small_list), 5)"
insert_large = "large_list.insert(len(large_list), 5)"

Now, let’s take a look at all the empty list examples:

>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=static_list_empty))
0.06050460000005842
>>> min(timeit.repeat(setup=setup, stmt=slice_assignment_empty))
0.4962195999996766
>>> min(timeit.repeat(setup=setup, stmt=append_empty))
0.17979939999986527
>>> min(timeit.repeat(setup=setup, stmt=extend_empty))
0.27297509999971226
>>> min(timeit.repeat(setup=setup, stmt=insert_empty))
0.49701270000059594

As expected, the most straightforward solution performs the best. Let’s see how that plays out as we grow our list:

>>> min(timeit.repeat(setup=setup, stmt=static_list_small))
0.1380927000000156
>>> min(timeit.repeat(setup=setup, stmt=slice_assignment_small))
0.5136848000001919
>>> min(timeit.repeat(setup=setup, stmt=append_small))
0.1721136000005572
>>> min(timeit.repeat(setup=setup, stmt=extend_small))
0.28814950000014505
>>> min(timeit.repeat(setup=setup, stmt=insert_small))
0.5033762000002753

Again, append() gets the job done the quickest. Now, let’s take a look at an enormous list:

>>> min(timeit.repeat(setup=setup, stmt=slice_assignment_large))
0.5083946000004289
>>> min(timeit.repeat(setup=setup, stmt=append_large))
0.18050170000060461
>>> min(timeit.repeat(setup=setup, stmt=extend_large))
0.28858020000006945
>>> min(timeit.repeat(setup=setup, stmt=insert_large))
0.5108225000003586

Amazingly, all these solutions seem to scale really well. That said, append() takes the cake. After all, it is amortized O(1). In other words, appending to a list is a constant time operation as long as we don’t run out of space.

That said, take these performance metrics with a grain of salt. After all, not every solution is going to be perfect for your needs.

## Challenge

Now that we know how to add an item to a list, let’s try writing a simple sorting algorithm. After all, that’s the perfect task for someone who wants to get familiar with the various list manipulation methods.

Personally, I don’t care which sorting algorithm you implement (e.g. bubble, insertion, merge, etc.) or what type of data you choose to sort (e.g. numbers, strings, etc.). In fact, I don’t even care if you sort the data in place or create an entirely separate list. All I care about is that you use one or more of the methods described in this article to get it done.

When you think you have a good solution, feel free to share it in the comments. As always, I’ll share an example in the comments.

## A Little Recap

With all that out of the way, let’s take a look at all our solutions again:

# Statically defined list
my_list = [2, 5, 6]

# Appending using slice assignment
my_list[len(my_list):] = [5]  # [2, 5, 6, 5]

# Appending using append()
my_list.append(9)  # [2, 5, 6, 5, 9]

# Appending using extend()
my_list.extend([-4])  # [2, 5, 6, 5, 9, -4]

# Appending using insert()
my_list.insert(len(my_list), 3)  # [2, 5, 6, 5, 9, -4, 3]

By far, this has been one of my favorite articles to write in awhile. There’s nothing quite like learning something new while writing a short response to the question “How do I add an item to a list?”

If you liked this article, help me get it in front of more eyes by giving it a share. In addition, you can show your support by hopping on my mailing list, joining me on Patreon, or subscribing to my YouTube channel. Likewise, you might benefit from additional Python resources like my Python 3 Beginner Cheat Sheet. Otherwise, check out some of these related articles:

Other than that, that’s all I’ve got! Thanks again for your support. See you next time!

The post How to Add an Item to a List in Python: Append, Slice Assignment, and More appeared first on The Renegade Coder.

]]>
How to Check if a String Contains a Substring in Python: In, Index, and More https://therenegadecoder.com/code/how-to-check-if-a-string-contains-a-substring-in-python/ https://therenegadecoder.com/code/how-to-check-if-a-string-contains-a-substring-in-python/#respond Mon, 06 Jan 2020 06:40:00 +0000 https://therenegadecoder.com/?p=20607

One concept that threw me for a loop when I first picked up Python was checking if a string contains a substring. After all, in my first language, Java, the ...

The post How to Check if a String Contains a Substring in Python: In, Index, and More appeared first on The Renegade Coder.

]]>

One concept that threw me for a loop when I first picked up Python was checking if a string contains a substring. After all, in my first language, Java, the task involved calling a method like indexOf() or contains(). Luckily, Python has an even cleaner syntax, and we’ll cover that today.

To summarize, we can check if a string contains a substring using the in keyword. For example, "Hi" in "Hi, John" returns true. That said, there are several other ways to solve this problem including using methods like index() and find(). Check out the rest of the article for more details.

## Problem Description

A common problem in programming is detecting if a string is a substring of another string. For example, we might have a list of addresses stored as strings, and we want to find all addresses on a certain street (e.g. Elm Street):

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

In that case, we might check which addresses contain the street name (e.g. 123 Elm Street). How do we do something like this in Python?

In most programming languages, there’s usually some substring method. For instance, in Java, strings have an indexOf method which returns a positive number if the substring was found.

Even without a special method, most languages allow you to index strings like arrays. As a result, it’s possible to manually verify that a string contains a substring by looking for a match directly.

In the following section, we’ll take a look at several possible solutions in Python.

## Solutions

As always, I like to share a few possible solutions to this problem. That said, if you want the best solution, I suggest jumping to the last solution.

### Checking if String Contains Substring by Brute Force

Whenever I try to solve a problem like this, I like to think about the underlying structure of the problem. In this case, we have a string which is really a list of characters. As a result, what’s stopping us from iterating over those character to find our substring:

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

street_length = len(street)
for index in range(address_length - street_length + 1):
if substring == street:
print(address)

Here, I’ve written a sort of nasty set of loops which iterate over all addresses, compute lengths of some strings, iterate over all substrings of the appropriate size, and prints the results if a proper substring is found.

Luckily, we don’t have to write our own solution to this. In fact, the entire inner loop is already implemented as a part of strings. In the next section, we’ll look at one of those methods.

### Checking if String Contains Substring Using index()

If we want want to check if a string contains a substring in Python, we might try borrowing some code from a language like Java. As mentioned previously, we usually use the indexOf() method which returns an index of the substring. In Python, there’s a similar method called index():

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

try:
except ValueError:
pass

Here, we call the index function without storing the result. After all, we don’t actually care what the index is. If the method doesn’t find a matching substring, it’ll throw an exception. Naturally, we can catch that exception and move on. Otherwise, we print out the address.

While this solution gets the job done, there’s actually a slightly cleaner solution, and we’ll take a look at it in the next section.

### Checking if String Contains Substring Using find()

Interestingly enough, Python has another method similar to index() which functions almost identically to indexOf() from Java. It’s called find(), and it allows us to simplify our code a little bit:

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

print(address)

Now, that’s a solution I can get behind. After all, it’s quite reminscent of a similar Java solution.

Again, it works like index(). However, instead of throwing an exception if the substring doesn’t exist, it returns -1. As a result, we can reduce our try/except block to a single if statement.

That said, Python has an even better solution which we’ll check out in the next section.

### Checking if String Contains Substring Using in Keyword

One of the cool things about Python is how clean and readable the code can be. Naturally, this applies when checking if a string contains a substring. Instead of a fancy method, Python has the syntax built-in with the in keyword:

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

print(address)

Here, we use the in keyword twice: once to iterate over all the addresses in the address list and again to check if the address contains the street name. As you can see, the in keyword has two purposes:

• To check if a value is present in a sequence like lists and strings
• To iterate through a sequence

Of course, to someone coming from a language like Java, this can be a pretty annoying answer. After all, our intuition is to use a method here, so it takes some getting used to. That said, I really like how this reads. As we’ll see later, this is also the fastest solution.

## Performance

With all these solutions ready to go, let’s take a look at how they compare. To start, we’ll need to set the solutions up in strings:

setup = """
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"
"""

brute_force = """
street_length = len(street)
for index in range(address_length - street_length + 1):
if substring == street:
pass # I don't want to print during testing
"""

index_of = """
try:
# Again, I don't actually want to print during testing
except ValueError:
pass
"""

find = """
pass # Likewise, nothing to see here
"""

in_keyword = """
pass # Same issue as above
"""

With these strings ready to go, we can begin testing:

>>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=brute_force))
4.427290499999998
>>> min(timeit.repeat(setup=setup, stmt=index_of))
1.293616
>>> min(timeit.repeat(setup=setup, stmt=find))
0.693925500000006
>>> min(timeit.repeat(setup=setup, stmt=in_keyword))
0.2180926999999997

Now, those are some convincing results! As it turns out, brute force is quite slow. In addition, it looks like the error handling of the index() solution isn’t much better. Luckily, find() exists to eliminate some of that overhead. That said, in is the fastest solution by far.

As is often the case in Python, you’ll get the best performance out of common idioms. In this case, don’t try to write your own substring method. Instead, use the built-in in keyword.

## Challenge

Now that you know how to check if a string contains a substring, let’s talk about the challenge. We’re going to write a simple address search engine which filters on two keywords rather than one: street and number. However, we may not get both pieces of information at the time of search. As a result, we need to deal with finding addresses which exactly match whatever keywords are available.

For this challenge, you can write any solution you want as long as it prints out a list of addresses that exactly matches the search terms. For instance, take the following list of addresses:

addresses = [
"123 Elm Street",
"123 Oak Street",
"678 Elm Street"
]

If a user searches just “Elm Street”, then I would expect the solution to return “123 Elm Street” and “678 Elm Street”. Likewise, if a user searches “123”, then I would expect the solution to return “123 Elm Street” and “123 Oak Street”. However, if the user provides both “123” and “Elm Street”, I would expect the solution to only return “123 Elm Street”—not all three addresses.

Feel free to have fun with this. For example, you could choose to write an entire front end for collecting the street and number keywords, or you could assume both of those variables already exist.

In terms of input data, feel free to write your own list of addresses or use my simple example. Alternatively, you can use a website which generates random addresses.

Ultimately, the program needs to demonstrate filtering on two keywords. In other words, find a way to modify one of the solutions from this article to match the street, address, or both—depending on what is available at the time of execution.

In the comments below, I’ll share my solution. Feel free to do the same!

## A Little Recap

And with that, we’re finished. As a final recap, here are all the solutions you saw today:

addresses = [
"123 Elm Street",
"531 Oak Street",
"678 Maple Street"
]
street = "Elm Street"

# Brute force (don't do this)
street_length = len(street)
for index in range(address_length - street_length + 1):
if substring == street:

# The index method
try:
except ValueError:
pass

# The find method

# The in keyword (fastest/preferred)
print(address)

As always, if you liked this article, make sure to give it a share. If you’d like more articles like this to hit your inbox, hop on my mailing list. While you’re at it, consider joining me on Patreon. Also, you might get some value out of my Python 3 Beginner Cheat Sheet which features code snippets like these.

If you’re interested in learning more Python tricks, check out some of these related articles:

Finally, check out seem of these Python resources on Amazon (ad):

Otherwise, that’s all I have. Thanks again for your support!

The post How to Check if a String Contains a Substring in Python: In, Index, and More appeared first on The Renegade Coder.

]]>
How to Perform a Reverse Dictionary Lookup in Python: Generator Expressions and More https://therenegadecoder.com/code/how-to-perform-a-reverse-dictionary-lookup-in-python/ https://therenegadecoder.com/code/how-to-perform-a-reverse-dictionary-lookup-in-python/#respond Fri, 03 Jan 2020 15:00:00 +0000 https://therenegadecoder.com/?p=18371

When it comes to dictionaries, looking up a value by key is easy, but what about the reverse? Today, we'll perform a reverse dictionary lookup in Python.

The post How to Perform a Reverse Dictionary Lookup in Python: Generator Expressions and More appeared first on The Renegade Coder.

]]>

Welcome to yet another Python tutorial. Today, we’re taking a look at dictionaries and how we can perform a reverse dictionary lookup. In words, how do we get a key from a dictionary given a value?

As it turns out, there are three main solutions. First, we could try explicitly looping over the dictionary using something like my_dict.items(). Alternatively, we could create a generator expression: next(key for key, value in my_dict.items() if value == value_to_find). Finally, we could invert the dictionary completely to retrieve the key like normal.

## Problem Introduction

Awhile back, I wrote an article about how to invert a dictionary. In other words, how do we swap keys and values in a dictionary? Well, as it turns out, sometimes we don’t need to flip an entire dictionary. All we need is a key given a value.

Normally when we use a dictionary, we pass it a key to retrieve a value. But, what if we want to retrieve a key given a value? In other words, what if we want to perform a reverse dictionary lookup. For example, given the following dictionary, we might want to retrieve the first key that matches the value “red”:

my_dict = {
"color": "red",
"width": 17,
"height": 19
}

In this case, we would expect our solution to return “color”. Of course, there might be multiple keys that match. How do we decide which one to grab?

Luckily, we won’t be digging into the nuance in this article. Instead, we’ll be looking at a handful of solutions that return the first key or every key that matches the value.

## Solutions

In this article, we’ll take a look at a few ways to perform a reverse ditionary lookup. As always, we’ll kick things off with a brute force solution. Then, we’ll look at some more sophisticated solutions.

### Reverse Dictionary Lookup by Brute Force

Perhaps a straightforward way of solving this problem is to iterate over the dictionary until we find the value we’re looking for:

my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"
for key, value in my_dict.items():
if value == value_to_find:
print(f'{key}: {value}')

In this case, we’re searching the dictionary for the value “red”. During each iteration, we’ll check if the value we’re looking for matches the current value. If it does, we print the results.

If we copy this solution verbatim, it will actually spit out all the matching keys. In this case, we’ll only see “color: red”. That said, a larger dictionary could yield duplicates.

At any rate, there are plenty of more interesting solutions ahead!

### Reverse Dictionary Lookup Using a Generator Expression

Instead of looping over our dictionary explicitly, we could leverage a generator expression (PEP 289) which looks a lot like a list comprehension:

my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"
key = next(key for key, value in my_dict.items() if value == value_to_find)
print(f'{key}: {value_to_find}')

Naturally, the difference between a list comprehension and a generator expression is that there’s no list created. In other words, we save memory and possibly time.

In the example above, instead of generating a list of all of the key-value pairs and iterating over them, we repeatedly generate a new key-value pair until we find one that matches. This clever bit of code is basically a condensed version of our loop from our brute forced solution. Of course, the iteration stops when we find what we need.

Again, be aware that this solution will only return the first key that matches our lookup value. If we wanted more than one key, we’d have to store the generator expression:

exp = (key for key, value in my_dict.items() if value == value_to_find)
next(exp) # First matching key
next(exp) # Second matching key

If we call next more times than there are matches, we get a StopIteration error. As a workaround, we can use a for-each loop directly:

exp = (key for key, value in my_dict.items() if value == value_to_find)
for key in exp:
print(key)

Now, isn’t that nice?

### Reverse Dictionary Lookup Using an Inverse Dictionary

As I mentioned in the problem description, we can always completely flip the dictionary:

my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"
my_inverted_dict = {value: key for key, value in my_dict.items()}
key = my_inverted_dict[value_to_find]

If you haven’t had a chance to read the other article, basically this solution takes advantage of a dictionary comprehension. In other words, it constructs a new dictionary from the original dictionary. Naturally, the part that does the magic is value: key which reverses the mapping.

Unfortunately, this solution won’t work for every circumstance because not all values are hashable (e.g. lists), but it gets the job done. Likewise, it only saves the last key for any duplicate values. As a result, other possible keys are lost.

If we want a solution that generates a list of keys, we can do something like the following:

my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"
my_inverted_dict = dict()
for key, value in my_dict.items():
my_inverted_dict.setdefault(value, list()).append(key)
keys = my_inverted_dict[value_to_find]

In this example, we end up with a list of keys rather than a single key.

## Performance

As always, let’s take a look at the performance of each of these solutions. First, we’ll need to set them up in strings:

setup = """
my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"
"""

brute_force_single = """
for key, value in my_dict.items():
if value == value_to_find:
break
"""

brute_force_multi = """
for key, value in my_dict.items():
if value == value_to_find:
pass
"""

generator_single = """
next(key for key, value in my_dict.items() if value == value_to_find)
"""

generator_multi = """
exp = (key for key, value in my_dict.items() if value == value_to_find)
for key in exp:
pass
"""

inverse_single = """
my_inverted_dict = {value: key for key, value in my_dict.items()}
my_inverted_dict[value_to_find]
"""

inverse_multi = """
my_inverted_dict = dict()
for key, value in my_dict.items():
my_inverted_dict.setdefault(value, list()).append(key)
my_inverted_dict[value_to_find]
"""

For the sake of completeness, I adapted each solution to each possible scenario. Either we want a single key, or we want many keys. As a result, each test is labeled single or multi, respectively.

In terms of testing, here are the results:

>>> import timeit
>>> min(timeit.repeat(setup=setup, stmt=brute_force_single))
0.19409550000000309
>>> min(timeit.repeat(setup=setup, stmt=brute_force_multi))
0.3046430999997938
>>> min(timeit.repeat(setup=setup, stmt=generator_single))
0.6223289999998087
>>> min(timeit.repeat(setup=setup, stmt=generator_multi))
0.6531434000003173
>>> min(timeit.repeat(setup=setup, stmt=inverse_single))
0.5350638999998409
>>> min(timeit.repeat(setup=setup, stmt=inverse_multi))
1.2309030999999777

Weirdly enough, the generator expression solution is actually quite slow. Perhaps, there’s a bit of overhead with creating a generator expression. I was interested to see how this solution scales with larger dictionaries, so I updated the setup string and reran my tests:

>>> setup = """
my_dict = {"color": "red", "width": 17, "height": 19, "health": 15, "depth": 100, "direction": "north", "material": "metal", "power": 17, "strength": 17, "weight": 111, "x": 0, "y": 0, "z": 0, "song": "Madeline", "band": "The Wonder Years", "friend": "rupert"}
value_to_find = "red"
"""
>>> min(timeit.repeat(setup=setup, stmt=brute_force_single))
0.18737550000059855
>>> min(timeit.repeat(setup=setup, stmt=brute_force_multi))
0.9153716000000713
>>> min(timeit.repeat(setup=setup, stmt=generator_single))
0.5850626999999804
>>> min(timeit.repeat(setup=setup, stmt=generator_multi))
1.2661715000003824
>>> min(timeit.repeat(setup=setup, stmt=inverse_single))
1.4036990000004153
>>> min(timeit.repeat(setup=setup, stmt=inverse_multi))
5.085829500000727

Again, I was a bit bothered by the results, so I tried changing the value we were searching for:

>>> setup = """
my_dict = {"color": "red", "width": 17, "height": 19, "health": 15, "depth": 100, "direction": "north", "material": "metal", "power": 17, "strength": 17, "weight": 111, "x": 0, "y": 0, "z": 0, "song": "Madeline", "band": "The Wonder Years", "friend": "rupert"}
value_to_find = "The Wonder Years"
"""
>>> min(timeit.repeat(setup=setup, stmt=brute_force_single))
0.8808984999996028
>>> min(timeit.repeat(setup=setup, stmt=brute_force_multi))
0.9333926999997857
>>> min(timeit.repeat(setup=setup, stmt=generator_single))
1.303262800000084
>>> min(timeit.repeat(setup=setup, stmt=generator_multi))
1.295239500000207
>>> min(timeit.repeat(setup=setup, stmt=inverse_single))
1.3928389000002426
>>> min(timeit.repeat(setup=setup, stmt=inverse_multi))
5.030787800000326

Again, brute force has the best performance. When I looked into why, I found that there’s a bit of overhead as I suspected. If I had the time, I’d probably run each of this solutions through cProfiler as outlined in my performance article. That said, I’ll defer to the responses in this Stack Overflow thread.

Overall, it looks like each solution performs in the order they were presented. In other words, brute force is slightly faster than a generator expression. Meanwhile, flipping the dictionary can be extremely costly.

## Challenge

With all the fun stuff out of the way, let’s take a look at your challenge. Since covering the reverse dictionary lookup, I thought it would be fun to challenge you with the following:

Look at all three solutions above (or 6 if you include the various requirements). Can you break down exactly why each solution performs the way it does? In other words, can you explain the differences in performance between each solution? Why would looping over a dictionary be faster than using a generator expression? Why wouldn’t flipping the dictionary be fastest?

As I alluded to previously, you can use any tools at your disposal to support your reasoning. For instance, you might try using cProfiler to exam the inner workings of each solution. Likewise, you might try running various tests like I did with timeit. Perhaps a plot of each solution under different workloads would help you figure out asymptotic runtimes.

Maybe, you don’t want to run any empirical testing tools at all. Instead, you want to look directly at the source code and trace what work it has to do to accomplish our task. Whatever you choose to do, make sure you share your results in the comments!

## A Little Recap

And with that, we’re done! Here’s all the solutions from this article in one place:

my_dict = {"color": "red", "width": 17, "height": 19}
value_to_find = "red"

# Brute force solution (fastest) -- single key
for key, value in my_dict.items():
if value == value_to_find:
print(f'{key}: {value}')
break

# Brute force solution -- multiple keys
for key, value in my_dict.items():
if value == value_to_find:
print(f'{key}: {value}')

# Generator expression -- single key
key = next(key for key, value in my_dict.items() if value == value_to_find)
print(f'{key}: {value_to_find}')

# Generator expression -- multiple keys
exp = (key for key, value in my_dict.items() if value == value_to_find)
for key in exp:
print(f'{key}: {value}')

# Inverse dictionary solution -- single key
my_inverted_dict = {value: key for key, value in my_dict.items()}
print(f'{my_inverted_dict[value_to_find]}: {value_to_find}')

# Inverse dictionary solution (slowest) -- multiple keys
my_inverted_dict = dict()
for key, value in my_dict.items():
my_inverted_dict.setdefault(value, list()).append(key)
print(f'{my_inverted_dict[value_to_find]}: {value_to_find}')

With all that out of the way, it’s time for me to ask you for a little help! Specifically, I’d love it if you hopped on my mailing list or even became a patron. In addition, I’m trying to grow my YouTube channel, so head on over and subscribe.

Alternatively, you can show your support by browsing The Renegade Coder shop. For instance, you might get some value out of the Python 3 Beginner Cheat Sheet which features tips for writing comprehensions, conditionals, and loops.

Otherwise, check out some of these Python resources on Amazon (ad):

If you have the time, I’d appreciate it if you stuck around to check out some of these related articles:

Otherwise, thanks for stopping by! I appreciate it.

The post How to Perform a Reverse Dictionary Lookup in Python: Generator Expressions and More appeared first on The Renegade Coder.

]]>
Democratic Synthesis: Taking Think-Pair-Share to the Next Level https://therenegadecoder.com/teach/democratic-synthesis-taking-think-pair-share-to-the-next-level/ https://therenegadecoder.com/teach/democratic-synthesis-taking-think-pair-share-to-the-next-level/#respond Mon, 30 Dec 2019 15:00:00 +0000 https://therenegadecoder.com/?p=20067

While exploring active learning this semester, I accidentally created my own extended activity which I've been jokingly calling Democratic Synthesis.

The post Democratic Synthesis: Taking Think-Pair-Share to the Next Level appeared first on The Renegade Coder.

]]>

During this past semester, I learned about active learning and how I could use it in the classroom. Oddly enough, I was already incorporating a lot of active learning in my classroom without even realizing it. In this article, I want to share one of my favorite active learning techniques which I jokingly named Democratic Synthesis.

## What Is Active Learning?

Before we dive into my technique, I should probably explain active learning. As the name suggest, active learning is any learning technique where students are engaged (i.e. any time the instructor isn’t lecturing).

Active learning techniques vary wildly. For example, asking students to briefly reflect on an activity or lesson would be enough to constitute active learning. Meanwhile, asking students to do something more involved like a gallery walk would also constitute active learning. The point of any active learning technique is to make sure students are engaged in the learning process.

Other common active learning strategies include:

• Quick Write: ask students to respond to a brief writing prompt
• Peer Instruction: ask students to respond to a multiple choice question, discuss their response with a friend, and choose a response again
• Jigsaw: ask students to break up into groups to learn about a topic, assign each student a subtopic to study, and ask students to regroup to share their new knowledge

In the following section, we’ll take a look at a common active learning technique known as Think-Pair-Share. Naturally, it forms the basis for my wild idea, Democratic Synthesis.

## What Is Think-Pair-Share?

Think-Pair-Share (TPS) is an active learning technique which leverages student collaboration. As the name suggests, there are three parts to TPS:

1. Think about the topic or question currently posed
2. Pair up with a student
3. Share thoughts

For example, you might ask a class to think about the merits of Medicare for All, a current hot topic in the United States. This allows students to bring in their own knowledge of the subject before introducing any new information. After thinking time passes, you can ask students to discuss their thoughts with a peer.

In many cases, the “share” portion of the activity can be opened up to the class. Perhaps pairs could report out on what they discussed, or maybe this discussion sets up a more rigorous activity. All that really matters is that students get a chance to thank about their response before they discuss it with anyone in the class.

In my experience, TPS works well in a Computer Science class, but I prefer to follow other active learning techniques like Peer Instruction (and Democratic Synthesis). That way, you can introduce a problem that students can solve together—rather than speculate. That said, it might be fun to use TPS in a more design oriented course like game development.

## What Is Democratic Synthesis?

Democratic Synthesis, as the fictional name implies, is a teaching technique where students come up with an answer to a problem as a class. In particular, it takes Think-Pair-Share to the next level.

First, we introduce a problem to the students. For a few minutes, students will try to solve the problem on their own. When they come up with a solution, we’ll ask them to submit it to an online discussion tool like TopHat. Then, they’ll pair up and discuss their thoughts.

Once all the solutions are posted and the students have had a chance to discuss them, we ask the students to vote for their favorite solution. In other words, which solution do they think best solves the problem.

Once a solution rises to the top, we have a couple options. We can either tackle the “best” solution as a class and determine if it’s valid, or we can leave that task to another round of Think-Pair-Share.

In either case, we’ll want to arrive at a correct solution. Usually, that means finding errors in the “best” solution and modifying them until the solution works. This iterative process allows students to make mistakes and learn from them in a safe environment.

## Democratic Synthesis in Action

At this point, I figured I’d share the exact activity I did with my class using Democratic Synthesis. Then, I’ll talk about how that activity could be modified depending on your needs.

### Step 1: State the Problem

For this lecture, I was covering recursion. At this point in the semester, the students were already quite comfortable with recursion conceptually, but they didn’t know exactly how to write their own recursive functions. As a result, I figured I’d ask them to tackle a challenging example as a class.

To kick off this activity, I asked the students to write me a recursive power function. Of course, there were some challenges weaved in. For example, the function didn’t have a return type. Instead, they had to propagate the results onto a reference type parameter (i.e. NaturalNumber).

### Step 2: Accept Individual Solutions

As students were working out their solutions, I asked them to submit their results to a discussion board on TopHat which I kept open at the front of the class. In other words, students could see solutions begin to roll in.

For this portion of the activity, I didn’t set a time limit. Honestly, I wasn’t sure how long it would take them to come up with a solution, so I patiently monitored them throughout the process. As students began veering off-topic, I moved onto the next step.

### Step 3: Discuss Solutions in Pairs

Once enough solutions had been submitted, I asked the students to discuss their solutions with each other. Here, the goal was to get students to compare two solutions to see what they could learn:

• Was their solution correct? Could they prove it?
• How did their partner’s solution compare? Was it faster/slower?
• Did their partner try to solve the problem the same way? Is there more than one way to solve it?

Again, the discussions weren’t prompted in any way. I just asked students to get with a partner and share what they came up with. I’m not sure if prompting them with the questions above would be helpful.

Likewise, I didn’t time limit this portion of the activity either. However, it may be a good idea if time is a concern.

### Step 4: Democratically Elect the “Best” Solution

After some discussion, I gave students the opportunity to elect the best solution in the class. In TopHat, this was as easy as telling students to “like” their favorite response. Then, I was able to sort the responses by “likes,” so we could crown a victor.

In my experience, students often pick an incorrect answer. For whatever reason, an incorrect solution will begin to get votes, and other students will see that. As a result, they will vote it up as well. Before too long, we’ll have a unanimous incorrect answer.

### Step 5: Debrief

Now, this is my favorite part of the activity. In all this buildup, students will feel like they’ve really created something. As a result, we get to have fruitful discussions about the results.

When I first did this activity, my students selected an incorrect answer. At that point, I took the opportunity to go through the process of “proving” its correctness. For example, I tested a base case—it failed. Then, I asked students to share a fix. After some deliberation, we were able to adjust our code to handle the base case.

Again, I began the testing process. First, I tested the base case. Then, I tested the next smallest subproblem. After a few iterations, the students were confident that the improved solution worked.

To finish off the activity, I asked the students if there was anything they would change or do differently. Since everyone was satisfied, we stopped the activity.

Oddly enough, I did this activity again later. However, instead of testing the code myself, I asked my students to follow the same process I did in a round of TPS/Jigsaw. In other words, I picked the top five answers and broke the class up into five small groups. Then, I asked the students to test their group’s solution before discussing their findings. Ultimately, I asked each group to report out whether or not their solution worked and how they would fix it if it didn’t.

## Observations and Caveats

After performing this activity twice, I felt like it was a huge hit. For one, students really enjoyed working through a problem like this with some structure. At no point were students overwhelmed, and failure was normalized. In other words, mistakes felt like an opportunity to learn rather than a punishment.

That said, there were definitely some concerns with this activity. For instance, the democratic vote might select a correct answer. In that case, what do you do? On one hand, you could go through the proving process anyway. Alternatively, you could select the top five answers, so you have a better chance of finding a solution that needs some work.

In addition, it’s important that students get a chance to solve the problem alone. Much like TPS, the thinking part is critical to ensuring that every student has something to bring to the table.

Finally, coming up with a good question is critical. Personally, I like to pick a question that is just out of reach for the students at their current ability level. In other words, think about what your students know and what you’d like them to learn by the end of the class. Then, work toward that goal organically with Democratic Synthesis.

Overall, I’m quite pleased with this activity, and I think other teachers might find value in it. I’m not sure how it would work outside of a Computer Science setting, but I’m sure it could be adapted just fine.

## Happy Teaching!

And with that, there’s nothing left to chat about. If you liked this activity, and you think you might try it in your classroom, let me know! I’d like to hear how it goes. Otherwise, how might you change or adapt this activity to your own needs?

In the meantime, stick around and check out some of my other teaching related articles:

In addition, if you want to see more articles like these, hop on my mailing list or support me on Patreon. Likewise, I occasionally generate teaching resources which you can find in my shop. Finally, help me grow my YouTube channel by becoming a subscriber. Otherwise, thanks for stopping by!

The post Democratic Synthesis: Taking Think-Pair-Share to the Next Level appeared first on The Renegade Coder.

]]>

Everything you regularly Google just found its place in this list. Say hello to a growing list of Python code snippets for everyday problems.

The post 71 Python Code Snippets for Everyday Problems appeared first on The Renegade Coder.

]]>

If you’ve been following me for any amount of time, you know that I regularly publish Python code snippets for everyday problems. Well, I figured I’d finally aggregate all those responses in one massive article with links to all those resources.

## Everyday Problems

In this section, we’ll take a look at various common scenarios that arise and how to solve them with Python code. Specifically, I’ll share a brief explanation of the problem with a list of Python code solutions. Then, I’ll link all the resources I have.

### Inverting a Dictionary

Sometimes when we have a dictionary, we want to be able to flip its keys and values. Of course, there are concerns like “how do we deal with duplicate values?” and “what if the values aren’t hashable?” That said, in the simple case, there are a few solutions:

# Use to invert dictionaries that have unique values
my_inverted_dict = dict(map(reversed, my_dict.items()))

# Use to invert dictionaries that have unique values
my_inverted_dict = {value: key for key, value in my_dict.items()}

# Use to invert dictionaries that have non-unique values
from collections import defaultdict
my_inverted_dict = defaultdict(list)
{my_inverted_dict[v].append(k) for k, v in my_dict.items()}

# Use to invert dictionaries that have non-unique values
my_inverted_dict = dict()
for key, value in my_dict.items():
my_inverted_dict.setdefault(value, list()).append(key)

# Use to invert dictionaries that have lists of values
my_dict = {value: key for key in my_inverted_dict for value in my_map[key]}

For more explanation, check out my article titled “How to Invert a Dictionary in Python.” It includes a breakdown of each solution, their performance metrics, and when they’re applicable. Likewise, I have a YouTube video which covers the same topic.

### Summing Elements of Two Lists

Let’s say you have two lists, and you want to merge them together into a single list by element. In other words, you want to add the first element of the first list to the first element of the second list and store the result in a new list. Well, there are several ways to do that:

ethernet_devices = [1, [7], [2], [8374163], [84302738]]
usb_devices = [1, [7], [1], [2314567], [0]]

# The long way
all_devices = [
ethernet_devices[0] + usb_devices[0],
ethernet_devices[1] + usb_devices[1],
ethernet_devices[2] + usb_devices[2],
ethernet_devices[3] + usb_devices[3],
ethernet_devices[4] + usb_devices[4]
]

# Some comprehension magic
all_devices = [x + y for x, y in zip(ethernet_devices, usb_devices)]

# Let's use maps
import operator

# We can't forget our favorite computation library
import numpy as np
all_devices = np.add(ethernet_devices, usb_devices)

If you’d like a deeper explanation, check out my article titled “How to Sum Elements of Two Lists in Python” which even includes a fun challenge. Likewise, you might get some value out of my YouTube video on the same topic.

### Checking if a File Exists

One of the amazing perks of Python is how easy it is to manage files. Unlike Java, Python has a built-in syntax for file reading and writing. As a result, checking if a file exists is a rather brief task:

# Brute force with a try-except block (Python 3+)
try:
with open('/path/to/file', 'r') as fh:
pass
except FileNotFoundError:
pass

# Leverage the OS package (possible race condition)
import os
exists = os.path.isfile('/path/to/file')

# Wrap the path in an object for enhanced functionality
from pathlib import Path
config = Path('/path/to/file')
if config.is_file():
pass

As always, you can learn more about these solutions in my article titled “How to Check if a File Exists in Python” which features three solutions and performances metrics.

### Converting Two Lists Into a Dictionary

Previously, we talked about summing two lists in Python. As it turns out, there’s a lot we can do with two lists. For example, we could try mapping one onto the other to create a dictionary.

As with many of these problems, there are a few concerns. For instance, what if the two lists aren’t the same size? Likewise, what if the keys aren’t unique or hashable? That said, in the simple case, there are some straightforward solutions:

column_names = ['id', 'color', 'style']
column_values = [1, 'red', 'bold']

# Convert two lists into a dictionary with zip and the dict constructor
name_to_value_dict = dict(zip(column_names, column_values))

# Convert two lists into a dictionary with a dictionary comprehension
name_to_value_dict = {key:value for key, value in zip(column_names, column_values)}

# Convert two lists into a dictionary with a loop
name_value_tuples = zip(column_names, column_values)
name_to_value_dict = {}
for key, value in name_value_tuples:
if key in name_to_value_dict:
pass # Insert logic for handling duplicate keys
else:
name_to_value_dict[key] = value

Once again, you can find an explanation for each of these solutions and more in my article titled “How to Convert Two Lists Into a Dictionary in Python.” If you are a visual person, you might prefer my YouTube video which covers mapping lists to dictionaries as well.

### Checking if a List Is Empty

If you come from a statically typed language like Java or C, you might be bothered by the lack of static types in Python. Sure, not knowing the type of a variable can sometimes be frustrating, but there are perks as well. For instance, we can check if a list is empty by its type flexibility—among other methods:

my_list = list()

# Check if a list is empty by its length
if len(my_list) == 0:
pass  # the list is empty

# Check if a list is empty by direct comparison (only works for lists)
if my_list == []:
pass  # the list is empty

# Check if a list is empty by its type flexibility **preferred method**
if not my_list:
pass  # the list is empty

If you’d like to learn more about these three solutions, check out my article titled “How to Check if a List in Empty in Python.” If you’re in a pinch, check out my YouTube video which covers the same topic.

### Cloning a List

One of my favorite subjects in programming is copying data types. After all, it’s never easy in this reference-based world we live, and that’s true for Python as well. Luckily, if we want to copy a list, there are a few ways to do it:

my_list = [27, 13, -11, 60, 39, 15]

# Clone a list by brute force
my_duplicate_list = [item for item in my_list]

# Clone a list with a slice
my_duplicate_list = my_list[:]

# Clone a list with the list constructor
my_duplicate_list = list(my_list)

# Clone a list with the copy function (Python 3.3+)
my_duplicate_list = my_list.copy()  # preferred method

# Clone a list with the copy package
import copy
my_duplicate_list = copy.copy(my_list)
my_deep_duplicate_list = copy.deepcopy(my_list)

# Clone a list with multiplication?
my_duplicate_list = my_list * 1  # do not do this

When it comes to cloning, it’s important to be aware of the difference between shallow and deep copies. Luckily, I have an article covering that topic.

Finally, you can find out more about the solutions listed above in my article titled “How to Clone a List in Python.” In addition, you might find value in my related YouTube video titled “7 Ways to Copy a List in Python Featuring The Pittsburgh Penguins.”

### Retrieving the Last Item of a List

Since we’re on the topic of lists, lets talk about getting the last item of a list. In most languages, this involves some convoluted mathematical expression involving the length of the list. What if I told you there is are several more interesting solutions in Python?

my_list = ['red', 'blue', 'green']

# Get the last item with brute force using len
last_item = my_list[len(my_list) - 1]

# Remove the last item from the list using pop
last_item = my_list.pop()

# Get the last item using negative indices *preferred & quickest method*
last_item = my_list[-1]

# Get the last item using iterable unpacking
*_, last_item = my_list

As always, you can learn more about these solutions from my article titled “How to Get the Last Item of a List in Python” which features a challenge, performance metrics, and a YouTube video.

### Making a Python Script Shortcut

Sometimes when you create a script, you want to be able to run it conveniently at the click of a button. Fortunately, there are several ways to do that.

First, we can create a Windows shortcut with the following settings:

\path\to\trc-image-titler.py -o \path\to\output

Likewise, we can also create a batch file with the following code:

@echo off
\path\to\trc-image-titler.py -o \path\to\output

Finally, we can create a bash script with the following code:

#!/bin/sh
python /path/to/trc-image-titler.py -o /path/to/output

If you’re looking for more explanation, check out the article titled “How to Make a Python Script Shortcut with Arguments.”

### Sorting a List of Strings

Sorting is a common task that you’re expected to know how to implement in Computer Science. Despite the intense focus on sorting algorithms in most curriculum, no one really tells you how complicated sorting can actually get. For instance, sorting numbers is straightforward, but what about sorting strings? How do we decide a proper ordering? Fortunately, there are a lot of options in Python:

my_list = ["leaf", "cherry", "fish"]

# Brute force method using bubble sort
my_list = ["leaf", "cherry", "fish"]
size = len(my_list)
for i in range(size):
for j in range(size):
if my_list[i] < my_list[j]:
temp = my_list[i]
my_list[i] = my_list[j]
my_list[j] = temp

# Generic list sort *fastest*
my_list.sort()

# Casefold list sort
my_list.sort(key=str.casefold)

# Generic list sorted
my_list = sorted(my_list)

# Custom list sort using casefold (>= Python 3.3)
my_list = sorted(my_list, key=str.casefold)

# Custom list sort using current locale
import locale
from functools import cmp_to_key
my_list = sorted(my_list, key=cmp_to_key(locale.strcoll))

# Custom reverse list sort using casefold (>= Python 3.3)
my_list = sorted(my_list, key=str.casefold, reverse=True)

If you’re curious about how some of these solutions work, or you just want to know what some of the potential risks are, check out my article titled “How to Sort a List of Strings in Python.”

One of the more interesting use cases for Python is data science. Unfortunately, however, that means handling a lot of raw data in various formats like text files and spreadsheets. Luckily, Python has plenty of built-in utilities for reading different file formats. For example, we can parse a spreadsheet with ease:

# Brute force solution
csv_mapping_list = []
with open("/path/to/data.csv") as my_data:
line_count = 0
for line in my_data:
row_list = [val.strip() for val in line.split(",")]
if line_count == 0:
else:
row_dict = {key: value for key, value in zip(header, row_list)}
csv_mapping_list.append(row_dict)
line_count += 1

import csv
csv_mapping_list = []
with open("/path/to/data.csv") as my_data:
line_count = 0
if line_count == 0:
else:
row_dict = {key: value for key, value in zip(header, line)}
csv_mapping_list.append(row_dict)
line_count += 1

import csv
with open("/path/to/dict.csv") as my_data:
csv_mapping_list = list(csv.DictReader(my_data))

In this case, we try to get our output in a list of dictionaries. If you want to know more about how this works, check out the complete article titled “How to Parse a Spreadsheet in Python.”

### Sorting a List of Dictionaries

Once you have a list of dictionaries, you might want to organize them in some specific order. For example, if the dictionaries have a key for date, we can try sorting them in chronological order. Luckily, sorting is another relatively painless task:

csv_mapping_list = [
{
"Name": "Jeremy",
"Age": 25,
"Favorite Color": "Blue"
},
{
"Name": "Ally",
"Age": 41,
"Favorite Color": "Magenta"
},
{
"Name": "Jasmine",
"Age": 29,
"Favorite Color": "Aqua"
}
]

# Custom sorting
size = len(csv_mapping_list)
for i in range(size):
min_index = i
for j in range(i + 1, size):
if csv_mapping_list[min_index]["Age"] > csv_mapping_list[j]["Age"]:
min_index = j
csv_mapping_list[i], csv_mapping_list[min_index] = csv_mapping_list[min_index], csv_mapping_list[i]

# List sorting function
csv_mapping_list.sort(key=lambda item: item.get("Age"))

# List sorting using itemgetter
from operator import itemgetter
f = itemgetter('Name')
csv_mapping_list.sort(key=f)

# Iterable sorted function
csv_mapping_list = sorted(csv_mapping_list, key=lambda item: item("Age"))

All these solutions and more outlined in my article titled “How to Sort a List of Dictionaries in Python.”

### Writing a List Comprehension

One of my favorite Python topics to chat about is list comprehensions. As someone who grew up on languages like Java, C/C++, and C#, I had never seen anything quite like a list comprehension until I played with Python. Now, I’m positively obsessed with them. As a result, I put together an entire list of examples:

# Define a generic 1D list of constants
my_list = [2, 5, -4, 6]

# Duplicate a 1D list of constants
[item for item in my_list]

# Duplicate and scale a 1D list of constants
[2 * item for item in my_list]

# Duplicate and filter out non-negatives from 1D list of constants
[item for item in my_list if item < 0]

# Duplicate, filter, and scale a 1D list of constants
[2 * item for item in my_list if item < 0]

# Generate all possible pairs from two lists
[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]

# Redefine list of contents to be 2D
my_list = [[1, 2], [3, 4]]

# Duplicate a 2D list
[[item for item in sub_list] for sub_list in my_list]

# Duplicate an n-dimensional list
def deep_copy(to_copy):
if type(to_copy) is list:
return [deep_copy(item) for item in to_copy]
else:
return to_copy

As always, you can find a more formal explanation of all this code in my article titled “How to Write a List Comprehension in Python.” As an added bonus, I have a YouTube video which shares several examples of list comprehensions.

### Merging Two Dictionaries

In this collection, we talk a lot about handling data structures like lists and dictionaries. Well, this one is no different. In particular, we’re looking at merging two dictionaries. Of course, combining two dictionaries comes with risks. For example, what if there are duplicate keys? Luckily, we have solutions for that:

yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = dict()

# Brute force
for dictionary in (yusuke_power, hiei_power):
for key, value in dictionary.items():
powers[key] = value

# Dictionary Comprehension
powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}

# Copy and update
powers = yusuke_power.copy()
powers.update(hiei_power)

# Dictionary unpacking (Python 3.5+)
powers = {**yusuke_power, **hiei_power}

# Backwards compatible function for any number of dicts
def merge_dicts(*dicts: dict):
merged_dict = dict()
for dictionary in dicts:
merge_dict.update(dictionary)
return merged_dict

If you’re interested, I have an article which covers this exact topic called “How to Merge Two Dictionaries in Python” which features four solutions as well performance metrics.

### Formatting a String

Whether we like to admit it or not, we often find ourselves burying print statements throughout our code for quick debugging purposes. After all, a well placed print statement can save you a lot of time. Unfortunately, it’s not always easy or convenient to actually display what we want. Luckily, Python has a lot of formatting options:

name = Jeremy
age = 25

# String formatting using concatenation
print("My name is " + name + ", and I am " + str(age) + " years old.")

# String formatting using multiple prints
print("My name is ", end="")
print(name, end="")
print(", and I am ", end="")
print(age, end="")
print(" years old.")

# String formatting using join
print(''.join(["My name is ", name, ", and I am ", str(age), " years old"]))

# String formatting using modulus operator
print("My name is %s, and I am %d years old." % (name, age))

# String formatting using format function with ordered parameters
print("My name is {}, and I am {} years old".format(name, age))

# String formatting using format function with named parameters
print("My name is {n}, and I am {a} years old".format(a=age, n=name))

# String formatting using f-Strings (Python 3.6+)
print(f"My name is {name}, and I am {age} years old")

Keep in mind that these solutions don’t have to be used with print statements. In other words, feel free to use solutions like f-strings wherever you need them.

As always, you can find an explanation of all these solutions and more in my article titled “How to Format a String in Python.” If you’d rather see these snippets in action, check out my YouTube video titled “6 Ways to Format a String in Python Featuring My Cat.”

### Printing on the Same Line

Along a similar line as formatting strings, sometimes you just need to print on the same line in Python. As the print command is currently designed, it automatically applies a newline to the end of your string. Luckily, there are a few ways around that:

# Python 2 only
print "Live PD",

# Backwards compatible (also fastest)
import sys

# Python 3 only
print("Mob Psycho 100", end="")

As always, if you plan to use any of these solutions, check out the article titled “How to Print on the Same Line in Python” for additional use cases and caveats.

### Testing Performance

Finally, sometimes you just want to compare a couple chunks of code. Luckily, Python has a few straightforward options:

# Brute force solution
import datetime
start_time = datetime.datetime.now()
[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)] # example snippet
end_time = datetime.datetime.now()
print end_time - start_time

# timeit solution
import timeit
min(timeit.repeat("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]"))

# cProfile solution
import cProfile
cProfile.run("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]")

Again, if you want more details, check the article titled “How to Performance Test Python Code.”