5 tips you don't know about Python classes

Keywords: Python

Python has many powerful features that provide great flexibility when dealing with classes. Here, I'll show you five advanced techniques that can help you write better code.

1. Create a constant value

Suppose we are creating a class Circle. We may need a method to calculate the area and a method to calculate the perimeter:

class Circle():  
  def __init__(self, radius):  
    self.radius = radius 
	
  def area(self):  
    return 3.14 * self.radius * self.radius   
    
  def perimeter(self):  
    return 2 * 3.14 * self.radius

This implementation seems feasible, but what if we want to change the value of pi to be more precise? We need to change it in two places. A better idea is to save the value of PI in a variable:

class Circle():  
  def __init__(self, radius):  
    self.radius = radius  
    self.pi = 3.14 
  
  def area(self):  
    return self.pi * self.radius * self.radius   
    
  def perimeter(self):  
    return 2 * self.pi * self.radius

However, now anyone can change the value of pi. This is not a good idea. What if the user writes the following:

  c = Circle(4)  
  c.pi = 5

This will destroy all our functions! Obviously, we must do something about it. Unfortunately, Python does not allow the creation of constant variables. What we can do is use a function that returns a pi with the tag @ property. In this way, functions can be called like variables without parentheses.

class Circle():  
  def __init__(self, radius):  
    self.radius = radius  
     
  @property  
  def pi(self):  
    return 3.14 
  
  def area(self):  
    return self.pi * self.radius * self.radius   
    
  def perimeter(self):  
    return 2 * self.pi * self.radius

Now the value of pi cannot be changed by the user, it can only be stored in the attribute pi.

2. Multiple class constructors

In Python, the constructor of a class is__ init__ Method defined. Unfortunately, function overloading is not allowed, so we can only define a function with the same function. However, there is a way to use a method similar to a class constructor. This can be done using the tag @ classmethod.

For example, suppose we are creating a class Date. The first constructor is:

class Date():  
  def __init__(self, day, month, year):  
    self.day = day  
    self.month = month  
    self.year = year

Now we may want to add another constructor to get the Date from the string in the format dd/mm/yyyy. We can create a class method in the Date class:

@classmethod  
def fromString(cls, s):  
   day = int(s[:2])  
   month = int(s[3:5])  
   year = int(s[6:])  
   return cls(day, month, year) # Returns a new object

Now we can create a new Date object by calling the fromString method:

d = Date.fromString("21/07/2020")  
print(d.day, d.month, d.year)

Output:   
21 7 2020

3. Create enumeration

Suppose you have a variable in your program that represents the day of the week. You might express it as an integer, for example, Monday is 1, Tuesday is 2, and so on. However, this is not the best, because you must remember whether to start from zero or 1. In addition, when you print the value, it will only be an integer, so you need a function to convert it to the correct name.

Fortunately, we can use the enum class in the enum library. When you create a subclass of enum, it contains a set of variables, each with its own value, which you can use in your program. For example:

from enum import Enum

class WeekDay(Enum):  
  Monday = 1  
  Tuesday = 2  
  Wednesday = 3  
  Thursday = 4  
  Friday = 5  
  Saturday = 6  
  Sunday = 7

Now set the variable to the value "Friday", you can write:

day = WeekDay.Friday

You can also get the integer value represented by "Friday":

intDay = day.value # This value is 5

4. Iterator

Iterators are classes that allow you to iterate over all elements in a data structure. An example of an iterator is the range function: you can iterate over all integer values in a range (for example, using a for loop).

If you want to create your own iterator, you just need to implement it__ next__ And__ iter__ method.

  • __ iter__ The iterator object should be returned (so it returns self in most cases)
  • __ next__ The next element of the data structure should be returned

Suppose we are creating an iterator to loop through a list from back to front. The correct approach is:

class Backward():  
  def __init__(self, data):  
    self.data = data # We're going to iterate over a list type of data   
    self.index = len(self.data) 
  
  def __iter__(self):  
    return self 
	
  def __next__(self):  
    if(self.index == 0):  
      raise StopIteration  
    else:  
      self.index -= 1  
      return self.data[self.index]

As you can see, if there are no more elements to iterate__ next__ The function will raise a StopIteration error. Otherwise, it returns the next element to view. Now we can use the Backward object in the for loop:

bw = Backward([1,2,3,4,5])  
for elem in bw:  
  print(elem)

The output is as follows:

5  
4  
3  
2  
1

5. Access a class as a list

When we use lists, we can use square brackets to access specific values. We can also use__ getitem__ And__ setitem__ To implement similar functions for our own classes. These are the methods when we use square brackets for list calls:

  • x = l[idx] and x = L__ getitem__ (IDX) has the same function.
  • l[idx] = x and L__ setitem__ (IDX, x) has the same function.

So if we implement these two methods in a custom class, we can use square brackets like a list.

This is a very simple example (it is a list whose size cannot be changed and whose index starts from 1):

class MyList():  
  def __init__(self, dimension):  
    self.l = [0 for i in range(dimension)]  
    
  def __getitem__(self, idx):  
    return self.l[idx-1]  
    
  def __setitem__(self, idx, data):  
    self.l[idx-1] = data  
	
	
ml = MyList(5)  
ml[1] = 50 # Set the first element to 50   
ml[2] = 100 # Set the first element to 100 
x = ml[1] # The value of x is now 50

Translated from: https://python.plainenglish.io/five-unknown-tricks-for-python-classes-ba5edd29a108

Posted by weezil on Thu, 11 Nov 2021 19:30:21 -0800