Learn to Code via Tutorials on Repl.it!

← Back to all posts
Easy ways to make your python code more Concise and efficient!
dumbCodr (7)

I just wanted to share some tricks to make code more concise and more efficient that are really simple to implement

F-Strings


F-Strings come in really handy when you need a clean way to use strings with variables, and to format them!
If you want to make your strings and prints look much cleaner, and perform better, F-strings are by far the easiest way, lets say we have some variables:

name='bob'
address='123 Park Place'
Hours=(9,17)

A lot of people would print it like this:

import random
print('Hello '+name+',\nwe have a package to deliver to you at '+address+', If it is alright with you, we will be dropping your package off at '+str(random.choice(list(set(range(24))-set(range(*Hours)))))+' oclock')

While that approach certainly works, It looks quite a bit cleaner to use F-Strings
An F string is declared by putting an f before quotations like f'' or f"", all you have to do to get your variables in your string, is to wrap them in brackets within those quotations, I.E f'Hello, {name}', If we were to do what we did above with F-strings this is how it would appear:

print(f'Hello {name},\nwe have a package to deliver to you at {address}, if it is alright with you, we will be dropping youre package off at {random.choice(list(set(range(24))-set(range(*Hours))))} oclock')

And lets say we are just making a program that says hi,

name=input()
print('hello, '+name+' how are you doing')
print(f'hello, {name} how are you doing')

The f-string looks quite a bit cleaner, and also allows you to use formatting to do things like this:

print(f'{"hello":->10} {name},\n how are you doing')

The :->10 just means,
(: means this is going to format)
(- Can be any character you want to be used as padding (or none at all))
(> implies which direction, you can also use ^ or <)
(10 is how much to pad it by, doing a higher number would move it further)

Lambdas, Maps, Listcomps, Zips, and Filter, and Enumerate (tools for iteration)

Listcomps and maps

One of the easiest ways to make your code more precise, and potentially faster is with the use of These handy functions and loop syntax,
Lets say that we are trying to remove all odd numbers from a list of numbers that have been converted to strings, The long way to accomplish this would probably be something along the lines of this

list1 = ['0', '7', '21', '3', '0', '8', '13', '10', '21', '8', '19', '17', '3', '5', '2', '18', '18', '2', '15', '13', '20', '1', '22']
#list for the converted strings
list2=[]
for num in list1:
  #check if even
  if int(num)%2==0:
    #add to final list
    list2.append(int(num))

That method is definitely Great, but it can be vastly improved upon with something called a list comprehension, a list comprehension is essentially the concise version of the code above. A list comprehension is always enclosed in brackets, always iterates over something and always returns a list, here are a few examples of the syntax in different scenarios:
If you want an if else, this is the syntax:

newlist = [<output> if <condition> else <output> for item in iterable]
#an example of this in use
evenodd=['even' if number%2==0 else 'odd' for number in range(30)]

What is happening here is that it checks the conditional every time it iterates over an item, and the output is what will appear in the position it was on in the old list.
The next syntax style is when you only want items if a certain condition is true, I.E We only want to keep the item if it has a 'b' in it

l=['bad','bass','oops','fish','salt','bin']
onlybs=[text for text in l if 'b' in text]
#^the code above basically goes through these steps
#for every text in the list
#if there is the letter b in text
#add that text to the new list
#That listcomp is equivelant to this:
newl=[]
for text in l:
  if 'b' in text:
    newl.append(text)

Now that we now how to use listcomps,our adjusted odd remover would like this:

list2=[x for x in list1 if int(x)%2==0]

In that specific case, converting to an int before checking if it was even was fine, but in some situations, youl end up needing to convert the whole list before you iterate, which is where maps come in. ap is a function that needs a function, and an iterable, and all it does is apply that function to every iterable. There is one caveat to maps though, the first one being that it doesnt actually store all the values until converted to a list, or iterated over, and the second one being that due to its unique implementation, it is quite a bit faster then listcomps when given a builtin method I.E

#map(function,iterable)
strin=map(str,range(50))
print(strin)
print(list(strin))

what we did there was apply str() to every item in range(50), which is a concise and easy way to convert large amounts of items types.

zip, enumerate and filter

enumerate

A lot of times when iterating, knowing which index you are on is useful, and thats exactly what enumerate is for. Simply all it does is simplify counting which index you are on.

c=0
for x in range(50):
  print(x)
  c+=1
#this can be done with enumerate like this
for index,item in enumerate(range(50)):
  print(f'{item} is at {index}th index')

What enumerate does is take an iterable, and create a new one that is a list of tuples where the first item is the index, and the second item is the actual part of the itarable. when iterating over an enumerate, it is best to unpack it into two variables. Her is a real world use case for enumerate:

def findall(iterable,target):
  res=[]
  for index,item in enumerate(iterable):
    if item==target:
      res.append(index)
  return res

in listcomp form:

def findall(iterable,target):
  return [count for count,item in enumerate(iterable) if item==target]
filter

lets say we want to remove all digits from a string, this could be done with a listcomp or a normal loop, But filter can do it much more concisely

lol='eufu803fnhanus830j'
rmdigit=''.join([x for x in lol if x.isdigit()==False])
rd=''.join(filter(str.isalpha,lol))

Just like maps, filter is only better than a listcomp performance-wise if it is using a builtin function

Zips

lets say we have a list of cars, a list of their colors,a list of their model numbers, and a list of their years, and we want to have all of them together, the best way to do this is with the zip function, instad of iterating over all the lists.

name=['corola','tokoma','aventador','focus']
numb=[334,556,7778,3321]
colors=['green','beige','grey','pink']
years=[2020,2019,2021,2013]
cars=zip(name,numb,colors,years)
#as apposed to
cars2=[]
for x in range(len(name)-1):
    cars2.append(name[x],numb[x],colors[x],years[x])

Although the zip doesn't seem much shorter, than the naive method, it does a lot more in cases where lists could be uneven. It automatically accounts for the lengths of the iterates which means it wont error if one is longer than the other. Another great use of zips is in portioning out an iterable
i.e:

foo=[1,4,5,7,83,3,13,56,6]
#we want to divid it into sections of 3
bar=zip(foo[::3],foo[1::3],foo[2::3])

Lambdas

Though lambdas dont really have anything to do with iterables, they are quite often used within maps filters and other things. Basically a lambda is a mini one line function Here is how you define one:
<name>=lambda <parameters>:<what to spit out>
I.E

printdown=lambda s:print('ew') if 'q' in s else print('\n'.join(list(s)))

Using sets for better SPEED, and more concise functions

sets are a unique type of data structure, they cant have duplicates, dont have an order, are slow to iterate over but are huge speed boosts in certain scenarios.

Detecting duplicates

One of the most useful things that sets can help you with is detecting/removing duplicates, because a set conversion removes duplicates, it will be shorter than what it was converting from which allows you to use stuff like

isdupe=lambda i:len(set(i))==len(i)

instead of

def isdupe2(i):
  for item in i:
    if i.count(item)!=1:
      return False
  return True

That second example actually brings us to another efficiency trick with set

Making count more effecient

This one is pretty simple, you dont to need more counts of items than there are items so reducing a list to just unique items makes getting the count of a given item much faster

def isdupe2(i):
  for item in set(i):
    if i.count(item)!=1:
      return False
  return True

or the very barebones count dictionary (using a dictcomp :D)

frequency = lambda t:{l:t.count(l) for l in set(t)}

Super set,Subset,difference

Finding wheather all items in one thing are countained in another can best be done by converting iterables to sets,and then using the built issubset and issuperset methods

subset =lambda x,y:set(x).issubset(y)

In speed

One of the most important thing about sets is that checking if an item is contained is significantly faster with a set than with a list or a tuple
i.e

l=[7,33,3282801,83]
g=set(l)
s=7 in l
u=7 in g

Removing duplicates, set and dict.fromkeys

If you want to remove all duplicates from a list and dont care about order, its as simple as this:

nodupes=lambda t:list(set(t))

If you care about order:

nodupes2=lambda r:list(dict.fromkeys(r))

more info

https://www.w3schools.com/python/python_ref_set.asp

shorthand if-else

One of the easiest ways to make code look cleaner is to use shorthand if else
<thing> if <condition> else <thing>
i.e:

def iseven(i):
  return True if i%2==0 else False
#^shorthand
def iseven2(i):
  if i%2==0:
    return True
  else:
    return False

Dataclasses

This one is pretty simple, The example on their docs pretty much explains why its so great

from dataclasses import dataclass
@dataclass
class InventoryItem:
    name: str
    unit_price: float
    quantity_on_hand: int = 0
#looks a lot cleaner than
class item2:
  def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):
    self.name = name
    self.unit_price = unit_price
    self.quantity_on_hand = quantity_on_hand

it makes classes meant for storing data a lot a easier

Conclusion

I hope this was helpful and that you had fun reading, and learned a lot! :)
p.s if youre wondering about the performcance differences between map and listcomp, here ya go
https://replit.com/@dumbCodr/map-v-lcomp

Comments
hotnewtop
DynamicSquid (4937)

Nice tutorial! Just a tip, add the py extention at the end of the three ticks to get syntax highlighting, like this:

```py
print("This will be  syntax highlighted!")
Bookie0 (6299)

@DynamicSquid yess! another person trying to spread syntax highlighting lmao

nathangamer1 (0)

I'm a copywriter, too, and it's a little difficult for me. You can find my work on this site

elijahmikael (0)

As a writer, I'm working on an article that can describe this easily, currently I'm working in vector art company near me, with highly professional designer nad writers of the USA.

ch1ck3n (2082)

Nice!! this must have took a lot of time.

RoBlockHead (521)

These are some super tips! Thanks for sharing!