Elements Blog

Python Tips & Tricks: 3 hacks for starting a Tesla factory

In this blog post I would like to show you 3 Python tricks that prove that Python is awesome. Imagine you are the boss of a cool car factory, like Tesla. To keep your reputation you want to produce cars of the maximum quality, but at the same time improve your efficiency as much as possible. This way you can all save time you can spend on other things, like baking an egg.

Of course this is just our imagination, and we don’t own a car factory, but hey nobody can stop us from dreaming. Just for now we will represent our cars as Python classes.

I’ll tell you how to do this the pro way in 3 hacks…

Hack #1: Don’t waste your time, use Dataclasses

Starting in Python 3.7 we have at our disposal the dataclass decorator. With dataclasses you can have a lot of boilerplate code automatically done for you, especially to instantiate and represent your objects as strings. Exactly what we need to mass produce our cars with minimum overhead!

Now imagine you have the Tesla factory and want to create a class Car which has 4 parameters which define yours cars. Some set by default and some others not:


class Car:
  brand: str
  model: str
  self_driving: bool
  wheels: int # I want this one with default value 4
  
  def __init__(self, brand: str, model: str, self_driving: bool, wheels: int = 4):
    self.brand = brand
    self.model = model
    self.self_driving = self_driving
    self.wheels = wheels

I know what you think…. That’s indeed boring, I don’t want to even start writing the repr method to represent this class objects as a string, what a pain!

Luckily, Python is the perfect tool for the lazy developer. It will create the __init__ and repr methods for me. Let’s see how to do that:

from dataclasses import dataclass

@dataclass
class Car:
  brand: str
  model: str
  self_driving: bool
  wheels: int = 4

We can now use it like this:

>>> my_car = Car("Tesla", "Model S", True)
>>> print(my_car)
Car(brand='Tesla', model='Model S', self_driving=True, wheels=4)

Wasn’t that easy? With the time you saved by not writing repetitive code you can go and have a coffee, you deserve it!

Hack #2: Give your class a custom type

Now you wonder how you can guarantee that all your produced cars follow the same strict quality requirements that are expected for an awesome company like Tesla. For example, I want all my cars to have a working battery!

This is how one of your lousy competitors would do it:


from dataclasses import dataclass

@dataclass
class Car:
  brand: str
  model: str
  self_driving: bool
  wheels: int = 4

  def charge_battery(self):
    raise NotImplementedError
  

class MyCar(Car):
  def charge_battery(self):
    print("battery charged!")
    

But this is not nice, first because you need to create another class MyCar that basically does the same as the original Car. And second because all cars should have a battery from factory, in this case we are delegating the quality assurance to the final user. Elon Musk would never do that!

This is why good guy Python brings us Metaclasses. A Metaclass is basically the type of a class, so you can make Car to be of type Electric which means it has to have a battery to work, just like an integer by definition is a number without a decimal part.


from dataclasses import dataclass


class Electric(type):
  def __init__(cls, name, bases, namespace):
    obj = super().__init__(name, bases, namespace)
    
    if "charge_battery" not in namespace:
      raise RuntimeError(f"{name} has to implement the charge_battery method")


@dataclass
class Car(metaclass=Electric):
    brand: str
    model: str
    self_driving: bool
    wheels: int = 4
    

Now, this piece of code is impossible, an electric car without a battery can’t exist, and Python will let you know it before you can even instantiate an object!

RuntimeError: Car has to implement the charge_battery method

Like this car, the code won’t drive away. The developer is now forced to implement the charge_battery method, even before he tries to instantiate the car! So don’t worry, your Tesla factory won’t have any cars without some sort of battery, and the customer will be happy!

Hack #3: Track your production numbers with WeakSets!

Now, as the factory boss, you would like to know how many cars you have produced. But you want everything automated and nice, because you know human beings tend to forget about stuff and you don’t want to loose one single penny!

The naive way, that will for sure give more work and headaches to developers, would be to keep a list somewhere and remember to count any car you produce:

>>> cars_list = []
>>> car_one = Car("Tesla", "Model S", True)
>>> cars_list.append(car_one)
>>> car_two = Car("Tesla", "Model 3", True)
>>> cars_list.append(car_two)
...

Nasty, huh? You need to have somebody always aware of any car that has been produced and add it to a list. Also you will have a hard time removing cars from that list if you delete their instances. And what if we lose count? Let’s do it better by leveraging what we learned in Hack 2 with our Electric Metaclass:


from dataclasses import dataclass
from weakref import Weakset


class Electric(type):
  instances = WeakSet()
  
  def __init__(cls, name, bases, namespace):
    obj = super().__init__(name, bases, namespace)
    
    if "charge_battery" not in namespace:
      raise RuntimeError(f"{name} has to implement the charge_battery method")

    def __call__(self, *args, **kwargs):
      obj = super().__call__(*args, **kwargs)
      self.instances.add(obj)
      return obj
    
    
@dataclass
class Car(metaclass=Electric):
    brand: str
    model: str
    self_driving: bool
    wheels: int = 4
    

Check the instances attribute we have added to the Metaclass. A WeakSet is basically a list which keeps track of references to objects, you can add such pointers to the list and their are “automagically” removed if the reference ends up pointing to nothing.

As you can see, we override the __call__ method to add to our instances list a reference to the object we have just created. This method is called whenever you instantiate a new class.

Let’s see it in action!

>>> car_one = Car("Tesla", "Model S", True)
>>> car_two = Car("Tesla", "Model 3", True)
>>> for car in Electric.instances:
       print(car)
Car(brand='Tesla', model='Model S', self_driving=True, wheels=4)
Car(brand='Tesla', model='Model 3', self_driving=True, wheels=4)>>> del car_one  # Destroy one of the cars
>>> print(len(Electric.instances))
1

As you can observe, now we can iterate over and keep count of all the cars we have created, without any developer having to do any extra hours. Awesome!

Will you start your own Tesla factory?

So, if you ever start a car factory remember these 3 hacks. Also, if you come back to reality and you need to produce many objects and you want to make sure they have a common interface. You can use these hacks in a lot of cases, and it will always save you time.

But what to do with the time? You could fulfill your dream and start a real car factory, but first I would recommend reading about how to bake a good quality code egg.

Stay tuned for more Python Tips & Tricks!

No items found.
No items found.

This blog was written by

Aitor

on

Mar 19, 2021

Developer
Software Development
Python
dataclasses