Low-Level of Class Creation

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

Objectives:

  • Learn about the low-level steps involved in creating a class

Files Modified: validate.py, structure.py

In this exercise, we look at the mechanics of how classes are actually created.

Class creation

Recall, from earlier exercises, we defined a simple class Stock that looked like this:

class Stock:
    def __init__(self,name,shares,price):
        self.name = name
        self.shares = shares
        self.price = price
    def cost(self):
        return self.shares*self.price
    def sell(self,nshares):
        self.shares -= nshares

What we're going to do here is create the class manually. Start out by just defining the methods as normal Python functions.

>>> def __init__(self,name,shares,price):
        self.name = name
        self.shares = shares
        self.price = price

>>> def cost(self):
        return self.shares*self.price

>>> def sell(self,nshares):
        self.shares -= nshares

>>>

Next, make a methods dictionary:

>>> methods = {
         '__init__' : __init__,
         'cost' : cost,
         'sell' : sell }

>>>

Finally, create the Stock class object:

>>> Stock = type('Stock',(object,),methods)
>>> s = Stock('GOOG',100,490.10)
>>> s.name
'GOOG'
>>> s.cost()
49010.0
>>> s.sell(25)
>>> s.shares
75
>>>

Congratulations, you just created a class. A class is really nothing more than a name, a tuple of base classes, and a dictionary holding all of the class contents. type() is a constructor that creates a class for you if you supply these three parts.

Typed structures

In the structure.py file, define the following function:

## structure.py

...
def typed_structure(clsname, **validators):
    cls = type(clsname, (Structure,), validators)
    return cls

This function is somewhat similar to the namedtuple() function in that it creates a class. Try it out:

>>> from validate import String, PositiveInteger, PositiveFloat
>>> from structure import typed_structure
>>> Stock = typed_structure('Stock', name=String(), shares=PositiveInteger(), price=PositiveFloat())
>>> s = Stock('GOOG', 100, 490.1)
>>> s.name
'GOOG'
>>> s
Stock('GOOG', 100, 490.1)
>>>

You might find the seams of your head starting to pull apart about now.

âœĻ Check Solution and Practice

Making a lot of classes

There are other situations where direct usage of the type() constructor might be advantageous. Consider this bit of code:

## validate.py
...

class Typed(Validator):
    expected_type = object
    @classmethod
    def check(cls, value):
        if not isinstance(value, cls.expected_type):
            raise TypeError(f'expected {cls.expected_type}')
        super().check(value)

class Integer(Typed):
    expected_type = int

class Float(Typed):
    expected_type = float

class String(Typed):
    expected_type = str
...

Wow is the last part of that annoying and repetitive. Change it to use a table of desired type classes like this:

## validate.py
...

_typed_classes = [
    ('Integer', int),
    ('Float', float),
    ('String', str) ]

globals().update((name, type(name, (Typed,), {'expected_type':ty}))
                 for name, ty in _typed_classes)

Now, if you want to have more type classes, you just add them to the table:

_typed_classes = [
    ('Integer', int),
    ('Float', float),
    ('Complex', complex),
    ('Decimal', decimal.Decimal),
    ('List', list),
    ('Bool', bool),
    ('String', str) ]

Admit it, that's kind of cool and saves a lot of typing (at the keyboard).

âœĻ Check Solution and Practice

Summary

Congratulations! You have completed the Low-Level of Class Creation lab. You can practice more labs in LabEx to improve your skills.

Other Python Tutorials you may like