Johan - 1 year ago 51

Python Question

I have a Python class that performs a bunch of calculations. Here is an example:

`class MyCalc(object):`

def calc_x(self):

return some_calc

def calc_y(self): # There's about 15 of these calculations

return some_calc

What I want is to calculate the difference between two instances of the class. I've come up with the following approach, but not sure if this method has any drawbacks or maybe there's a better way?

`class Diff(object):`

def __init__(self, a, b):

self.a = a

self.b = b

def __getattr__(self, attr):

getter = operator.attrgetter(attr)

closing = getter(self.a)()

opening = getter(self.b)()

return closing - opening

a = MyCalc()

b = MyCalc()

diff = Diff(a, b)

print(diff.calc_x) # calculate a.calc_x() - b.calc_x()

Alternatively I can add a decorator and don't use the Diff class:

`def differance(func):`

def func_wrapper(self):

return func(self) - func(self.b)

return func_wrapper

class MyCalc(object):

@difference

def calc_x(self):

return some_calc

@difference

def calc_y(self):

return some_calc

Any feedback will be appreciated.

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

Your `Diff`

class looks fine to me, but I'm still undecided whether this is Pythonic or not. ;) I don't see any major drawbacks, but it can be made more efficient.

Here's an alternative implementation of the `Diff`

class. It's a little more efficient since it doesn't have to do a lookup and two calls of `operator.attrgetter`

on each `__getattr__`

call. Instead, it caches the attribute accessing functions using `functools.partial`

and the built-in `getattr`

function.

I've also implemented a simple `MyCalc`

clas for testing purposes.

```
from functools import partial
class MyCalc(object):
def __init__(self, u, v):
self.u = u
self.v = v
def calc_x(self):
return self.u + self.v
def calc_y(self):
return self.u * self.v
class Diff(object):
def __init__(self, a, b):
self.geta = partial(getattr, a)
self.getb = partial(getattr, b)
def __getattr__(self, attr):
closing = self.geta(attr)()
opening = self.getb(attr)()
return closing - opening
a = MyCalc(10, 20)
b = MyCalc(2, 3)
diff = Diff(a, b)
print(diff.calc_x)
print(diff.calc_y)
a.u, a.v = 30, 40
b.u, b.v = 4, 7
print(diff.calc_x)
print(diff.calc_y)
```

**output**

```
25
194
59
1172
```

Recommended from our users: **Dynamic Network Monitoring from WhatsUp Gold from IPSwitch**. ** Free Download**