1

I am trying to extend the calendar module to color days according to a passed pd.Series, whose index is the dates and whose value is a color code (0 to 10).

I'm not deep enough into OOP to do this. The TextCalendar class has a method formatyear, which in turn calls a method formatweek.

My current solution is to define a class ColoredTextCalendar(TextCalendar) whose __init__() sets a class property date_to_color (a pandas Series of color codes, with the date as index). I then basically copy-and-pasted the original formatyear and formatweek methods, and changed only two or three lines in them: formatyear now calls formatweek with additional parameters year and month, so that this method knows what actual date it is formatting (previously it just printed a 7-day calendar week like 12 13 14 15 16 17 18). And formatweek now looks up the corresponding color code in its class property date_to_color and colors each day's string accordingly.

What I'm doing kind of works, but it feels wrong, like there should be a simpler, more straightforward solution. Copy-and-pasting a long method and changing only a few lines feels wrong - that's not how you usually do OOP, right?

Alexander Engelhardt
  • 1,632
  • 3
  • 16
  • 31
  • You can use super() to call the parent class method, so if you need to add code before or after execution you dont need copy pasting, but if you are modifying the middle of the function you need to rewrite it. an other solution would be to split your method into multiple method so you have less line of code to rewrite in your child method. show us your code if you want a more precise advice. – bboumend Aug 31 '18 at 07:59
  • Yes, the before/after would be ideal. I've experimented with super() but in this case didn't find a way to use it to solve my problem. Unfortunately the method call I want to extend is right in the middle of the original method. – Alexander Engelhardt Aug 31 '18 at 08:01
  • you can put the code in the middle that you need to change into a new method and just override this method – bboumend Aug 31 '18 at 08:02
  • True, but that would require copy-pasting the large method where the changed method gets called, because I have to edit this one line in it, right? (Let me emphasize that the original class is not written by me, but is a builtin Python module) – Alexander Engelhardt Aug 31 '18 at 08:06
  • If you cant modify the original class, the easiest solution is to rewrite the function or fork the original project so you can modify the original class, other solutions will be realy advanced programming trick and im not sure this is a good practice it will make your code complicated and simpler is better than complicated – bboumend Aug 31 '18 at 08:29

1 Answers1

0

Example of how to override:

class Base:
    def foo(self, x):
        x += 1
        x += 2
        x += 3

Given this simple base class i want to override the x += 2 line ine the middle

rewrite your parent method like this

class Base:
    def foo(self, x):
        x += 1
        self.bar(x)
        x += 3

    def bar(self, x):
        x += 2

class Child(Base):
    def bar(self, x):
        # my new code

you need to have non defined number of params in your methods you can use *args and **kwargs see this *args and **kwargs?

bboumend
  • 490
  • 3
  • 13
  • But now imagine the Base class is not written by me, but instead is a builtin Python module. (It's the `calendar` module, to be specific). So that means I can't change the Base.foo method without copy-pasting it into my Child class, right? – Alexander Engelhardt Aug 31 '18 at 08:28
  • In this case the base class is owned by other people so refactoring it is not an option. – Stop harming Monica Aug 31 '18 at 08:36
  • At this points if you rewrite a method from a class not owned by you, you dont have duplication in your own code so it looks fine to me – bboumend Aug 31 '18 at 08:43
  • Okay. I'm fine with copy-pasting the necessary functions, I just wanted to make sure I'm not angering the OOP gods – Alexander Engelhardt Aug 31 '18 at 08:56