0
\$\begingroup\$

I have a database, with tens of thousands of records, which I wish to represent in python. The python 2.x version has tables in which each record is an instance of a class and the values in the record are held in attributes of the object. Some of the attributes are terms which are used to classify records. The classifications in my database relate to some technical metadata structures, so here, to concentrate on the essential coding question.

If I have a collection of objects which are classified by, for example, colour and year, does it make sense to represent the colour and year as python super-classes (perhaps as illustrated below) rather than as attribute values?

In the following example I've created a potential implementation:

import time
## Cars will be classified Colour and Year

class Colour(type): pass

class Year(type):
    description = 'Year of purchase'

## A class for cars classified by year and colour
class Car(Colour,Year): pass

## colours for classification
#
# Duplication in specification of colour could be removed by using a factory to
# generate these classes from tabulated information.
#
Red = Colour( 'red', (object,), dict(description='The primary colour red',colour='red') )
Blue = Colour( 'blue', (object,), dict(description='The primary colour blue',colour='blue') )
Green = Colour( 'green', (object,), dict(description='The primary colour green',colour='green') )

# years for classification.
Y2015 = Year( '2015', (object,), dict(description='2015 AD' ) )
Y2016 = Year( '2016', (object,), dict(description='2016 AD' ) )
Y2017 = Year( '2017', (object,), dict(description='2017 AD' ) )
Y2018 = Year( '2018', (object,), dict(description='2018 AD' ) )


# for each
class CarRecord(object):
    def __init__(self,comment):
        self.record_date=time.ctime()
        self.comment=comment

#
# records are classified by the colour and year classes.
#
MyCar = Car( 'MyCar', (CarRecord,Blue,Y2018), dict( comment='car number 1' ) )
HisCar = Car( 'HisCar', (CarRecord,Green,Y2016), dict( comment='car number 2' ) )

## instantiation creates a specific metadata record, with timestamp
my_car = MyCar('A very good car')
his_car = HisCar("Someone else's car")

This example appears to work smoothly, but I have arrived at this point by trial-and-error and have some concerns that I may not fully understand the implications of some of the coding structures used.

Advantages

  • The categories Blue, Red etc are python objects and can carry additional descriptive information and helper methods as needed;
  • There is a clear separation between properties such as Colour, which are part of a classification scheme, and description, which is a free-text attribute;
  • Ability to add attributes and methods to categories (Red, Blue etc) and category groups (Colour, Year) in a transparent way;

Disadvantages

  • Could there be hidden performance overheads when expanding the number of category groups to 10 and the number of categories to hundreds?
  • Is there a better way of handling the relationship between concepts being categorised (the cars hers) and concepts being used for categorisation?
\$\endgroup\$
5
  • 1
    \$\begingroup\$ How are you using your code? I can write a review without seeing how you're actually using the code. However my review may not factor in your usage and be sub-optimal. Can you show why you need custom types and abnormal metaclasses. \$\endgroup\$
    – Peilonrayz
    Apr 26, 2021 at 16:24
  • \$\begingroup\$ @Peilonrayz : I'm sorry if the question is too vague to answer. My code as it stands is, I think, too complex/untidy to post here. I was trying to ask a general question about use of meta-classes to classify concepts which are expressed as python classes. In UML terms, I can declare that MyCar is Red through either an association (e.g. by giving MyCar an attribute colour=Red or derivation/specialisation (MyCar is a sub-class of RedObjects). Can you clarify what you mean by "abnormal metaclasses"? \$\endgroup\$
    – M Juckes
    Apr 27, 2021 at 8:50
  • \$\begingroup\$ "too complex/untidy to post here." No, your actual real code is far better for you and me to discuss. To build metaclasses normally you just use class Red(metaclass=Colour): color = "red" however you're using the interface used only by six. If you change to normal metaclass usage then you should be able to see your custom types don't do anything. \$\endgroup\$
    – Peilonrayz
    Apr 27, 2021 at 9:40
  • \$\begingroup\$ If I understand correctly, there will be a class for every combination of categories across all groups: 3 colors x 4 years = 12 classes. You suggest there could be 10 groups, each with 100 categories = 100*100*100,,,*100 = 10^20 classes! That seems rather unwieldly. What happens when a red car gets painted blue? I think Enums as class attributes gets you all the advantages you listed above. \$\endgroup\$
    – RootTwo
    Apr 29, 2021 at 4:54
  • \$\begingroup\$ @RooTwo -- a fair point, but 10^20 Enums is also going to be a problem. It is true that a can use Enums .. and the justification for looking for an alternative is not clear in the example. The reason I'm looking at this is that I'm classifying concepts, and representing this in python code. In UML terms (based on a limited understanding of UML) I think of class attributes as expressing an association relationship. If I go down that route I have two sets of class relationships in my code: one set of functional python classes and a 2nd set of associations for classification of colour etc. \$\endgroup\$
    – M Juckes
    Apr 30, 2021 at 6:37

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.