Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Tuesday, June 1, 2010

Bitemporality in Python

A few years ago I published a Java framework to deal with bitemporal issues in rich domain models. The code is freely available under a BSD style license.

As a first piece of non-trivial Python programming I coded up an equivalent framework in Python 2.5, available here. The framework allows you to set up a class with bitemporal properties that track the history and evolution of the value assigned to those properties. Here's a small example that should give you a feel for what you can do:
from bitemporal import *

class Person:

 def __init__(self, name):
  self.name = name
  self.address = BitemporalProperty()

p = Person("John Doe");
p.address.assign("Smallville", Interval(date(1975, 4, 3), date.max))
p.address.assign("Bigtown", Interval(date(1994, 8, 26), date.max))

print p.address.now() # Bigtown
print p.address.on(date(1980, 1, 1)) # Smallville

I'm looking for feedback on this code, which right now is only about 300 lines long. Is this code pythonic? Or is this Java-style Python code? If so, what areas need to be improved? Personally, I have doubts about at least a few things:
  • The type checks in the TimeFrame class (and a few other classes) feel iffy:
    @classmethod
    def set_reference(cls, value):
     if type(value) == date:
      cls.reference = datetime.combine(value, time())
     else:
      cls.reference = value
    
    But how else do I ensure that a timeframe always holds a datetime?
  • The BitemporalWrapper class feels Java-like. It decorates another object with bitemporal information and functionality. Is there a better way to do this in a dynamically typed language?
  • I considered using @property for the assign() method on the BitemporalProperty class, but the problem is that you often want to pass in a validity interval, which rules out use of "=".
Does anybody have any tips how this code can be improved?

Thursday, May 13, 2010

Python default argument madness

I've been learning python recently. I'm just getting started so I'm running into all the stupid beginner problems, for instance the insane behaviour of default argument values. Take this example:
from datetime import datetime
import time

class Weird:

 def __init__(self, dt = datetime.now()):
  self.dt = dt

w1 = Weird()
time.sleep(1)
w2 = Weird()
w3 = Weird(datetime.now())

print w1.dt == w2.dt # True
print w1.dt == w3.dt # False
The datetime in the w1 and w2 objects will actually be the same since the default argument value in the method definition is only evaluated once! What!?!? This essentially renders default arguments useless since you always end up writing the following:
class Weird:

 def __init__(self, dt = None):
  self.dt = dt or datetime.now()
I don't understand why you would design a default argument values features in your language like this. Doing it this way certainly violates the principle of least astonishment!