patternpythonMinor
Scala inspired classes in Python
Viewed 0 times
pythonscalainspiredclasses
Problem
I have to define a lot of values for a Python library, each of which will represent a statistical distribution (like the Normal distribution or Uniform distribution). They will contain describing features of the distribution (like the mean, variance, etc). After a distribution is created it doesn't really make sense to change it.
I also expect other users to make their own distributions, simplicity is an extra virtue here.
Scala has really nice syntax for classes in cases like this. Python seems less elegant, and I'd like to do better.
Scala:
Python:
It's not terrible, but it's not great. There are a lot of extra
One possibility is the following nonstandard idiom, a function which returns a dictionary of locals:
I like this quite a bit, but does it have serious drawbacks that aren't obvious?
It returns a dict instead of an object, but that's good enough for my purposes and would be easy to fix with a that made it return an object.
Is there anything better than this? Are there serious problems with this?
I also expect other users to make their own distributions, simplicity is an extra virtue here.
Scala has really nice syntax for classes in cases like this. Python seems less elegant, and I'd like to do better.
Scala:
class Uniform(min : Double, max : Double) {
def logp(x : Double) : Double =
1/(max - min) * between(x, min, max)
def mean = (max + min)/2
}Python:
class Uniform(object):
def __init__(self, min, max):
self.min = min
self.max = max
self.expectation = (max + min)/2
def logp(self, x):
return 1/(self.max - self.min) * between(x, self.min, self.max)It's not terrible, but it's not great. There are a lot of extra
selfs in there and the constructor part seems pretty boilerplate.One possibility is the following nonstandard idiom, a function which returns a dictionary of locals:
def Uniform(min, max):
def logp(x):
return 1/(max - min) * between(x, min, max)
mean = (max + min)/2
return locals()I like this quite a bit, but does it have serious drawbacks that aren't obvious?
It returns a dict instead of an object, but that's good enough for my purposes and would be easy to fix with a that made it return an object.
Is there anything better than this? Are there serious problems with this?
Solution
You might prefer to use
namedtuple for the attributes, and the property decorator for mean. Note that mean is now computed every time it's accessed - maybe you don't want this, or maybe it makes sense since max and min are mutable.from collections import namedtuple
class Uniform(namedtuple('Uniform', ('min', 'max'))):
def logp(self, x):
return 1/(self.max - self.min) * between(x, self.min, self.max)
@property
def mean(self):
return 0.5*(self.min + self.max)Code Snippets
from collections import namedtuple
class Uniform(namedtuple('Uniform', ('min', 'max'))):
def logp(self, x):
return 1/(self.max - self.min) * between(x, self.min, self.max)
@property
def mean(self):
return 0.5*(self.min + self.max)Context
StackExchange Code Review Q#21666, answer score: 9
Revisions (0)
No revisions yet.