I have been wondering for a while if there is easier way to assign class attributes to method local namespace. For example, in dosomething method, I explicitly make references to self.a and self.b:
class test:
def __init__(self):
self.a = 10
self.b = 20
def dosomething(self):
a = self.a
b = self.b
return(a + b)
But sometimes I have a lot of variables (more than 10) and it gets messy to type and look at - I would have bunch of var = self.var statements at the beginning of a method.
Is there any way to do this more compact way? (I know updating local() is not a good idea)
Edit: Ideally, what I want is:
def dosomething(self):
populate_local_namespace('a', 'b')
return(a + b)
Q. Is there any way to do this more compact way?
1. If the variables are read-only, it would be reasonably Pythonic to factor-out a multi-variable accessor method:
class Test:
def __init__(self):
self.a = 10
self.b = 20
self.c = 30
def _read_vars(self):
return self.a, self.b, self.c
def dosomething(self):
a, b, c = self._read_vars()
return a + b * c
def dosomethingelse(self):
a, b, c = self._read_vars()
return a - b * c
If the variables aren't read-only, it is best to stick with self.inst_var = value. That is the normal way to write Python code and is usually what most people expect.
2. Once in a while you will see people abbreviate self with a shorter variable name. It is used when the readability benefits of decluttering outweigh the readability cost of using a non-standard variable name:
def updatesomethings(s):
s.a, s.b, s.c = s.a + s.c, s.b - s.a, s.c * s.b
3. Another way to handle a very large number instance variable is to store them in a mutable container for ease of packing and unpacking:
class Test:
def __init__(self, a, b, c, d, e, f, g, h, i):
self._vars = [a, b, c, d, e, f, g, h, i]
def fancy_stuff(self):
a, b, c, d, e, f, g, h, i = self._vars
a += d * h - g
b -= e * f - c
g = a + b - i
self._vars[:] = a, b, c, d, e, f, g, h, i
4. There is also a dictionary manipulation approach that would work, but it has a code smell that most Pythonistas would avoid:
def updatesomethings(self):
a = 100
b = 200
c = 300
vars(self).update(locals())
del self.self
You can easily solve this problem with a tradeoff, by storing the variables in a dictionary.
data = {}
copy_to_local_variables = ["a", "b", "c", "d"]
for var_name in copy_to_local_variables:
data[var_name] = getattr(self, var_name)
(Though I am unable to understand why you need to copy class attributes to method local namespace)
I found another way:
def dosomething(self):
for key in ['a', 'b']:
exec('{} = self.{}'.format(key, key))
return(a + b)
I don't know if this is dangerous or not. Would be great if someone can comment on this.
Related
my code is probably very unconventional since I am self-taught, any help or tips are appreciated.
I tried to speed up my python code using cython and have had some very good results only using a little bit of static typing here and there. However, I think there is much room for improvement.
I'm using a few classes to do similar operations in slightly different fashion, depending on their type, like this:
class A:
def __init__(self, A, B, C):
self.A = A
self.B = B
self.C = C
self.combined = 0
def UpdateCombined(self):
self.combined = A + B + C
return
class B:
def __init__(self, A, B, C):
self.A = A
self.B = B
self.C = C
self.combined = 0
def UpdateCombined(self):
self.combined = A * B * C
return
I looked into interfaces, because they seemed like the conventional way of implementing classes with the same type of methods and attributes, but different behaviour, but I came to the conclusion, that using interfaces through inheritance in my case is just unnecessary boilerplate and not really useful in anyway (if I have a interface class with NotImplemented everywhere, it really isn't any help, is it?)
I have quite a bit operations, where I have a list of instances of these classes and want to perform the same operation on all of them:
a, b, c = A(1, 3, 2)
x, y, z = B(5, 4, 3)
object_list = [a, b, c, x, y, z]
for SomeObject in object_list:
SomeObject.UpdateCombined()
My question now is, how could I go about cleanly improving this with cython? I think, probably use cdef class to make A and B extensions types, staticly type their arguements, that would be my first move. But how to I improve the latter code part, can I use extension types for static typing?
Thanks for any help in advance, any comments are appreciated
Let's say I have a Python constructor
def foo(a, b, c):
__def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
and I have a list of inputs
bar = [a, b, c]
Is there a way I can call the constructor with just a list of inputs? Eg,
foobar = foo(bar)
Or would I need to make an entire wrapper function, such as:
def fooWrapper(inputList):
a = inputList[0]
b = inputList[1]
c = inputList[2]
return foo(a, b, c)
Assuming I cannot change neither the constructor nor the way I receive the inputs (as a list), is there a more simple way to do this than creating a wrapper?
Thank you.
This should do the work for the wrapper function:
def f(a, b, c):
return sum([a, b, c])
bar = [3, 2, 1]
total = f(*bar)
print(total)
Outputs 6.
Since a constructor can not return a value, yes you need a wrapper.
Let's say I have a calculate() method which have complicated calculation with many variables, while I want to log down what is the value of variables in different phase (EDIT: Not only for verification but for data study purpose). For example.
# These assignment are arbitrary,
# but my calculate() method is more complex
def calculate(a, b):
c = 2*a+b
d = a-b
if c > d+10:
g = another_calc(a, c):
else:
g = another_calc(a, d):
return c, d, g
def another_calc(a, c_d):
e = a+c_d
f = a*c_d
g = e+f
return g
You may assume the method will be modified a lot for experimental exploration.
There is no much logging here and I want to log down what happen, for example I can write aggressive code like this
# These assignment are arbitrary,
# but my calculate() method is more complex
def calculate(a, b):
info = {"a": a, "b": b}
c = 2*a+b
d = a-b
info["c"], info["d"] = c, d
if c > d+10:
info["switch"] = "entered c"
g, info = another_calc(a, c, info):
else:
info["switch"] = "entered d"
g, info = another_calc(a, d, info):
return c, d, g, info
def another_calc(a, c_d, info):
e = a+c_d
f = a*c_d
g = e+f
info["e"], info["f"], info["g"] = e, f, g
return g, info
This serve my purpose (I got the info object, then it will be exported as CSV for my further study)
But it is pretty ugly to add more (non-functional) lines to the original clean calculate() method, changing signature and return value.
But can I write a cleaner code?
I am thinking whether it is possible to use decorator to wrap this method. Hope you guys would have some great answers. Thanks.
One way to write cleaner code (my opinion) is to wrap the info -dictionary inside a class.
Here is my simple code example:
# These assignment are arbitrary,
# but my calculate() method is more complex
def calculate(a, b, logger):
logger.log("a", a)
logger.log("b", b)
c = 2*a+b
d = a-b
logger.log("c", c)
logger.log("d", d)
if c > d+10:
logger.log("switch", "entered c")
g = another_calc(a, c)
else:
logger.log("switch", "entered d")
g = another_calc(a, d)
return c, d, g
def another_calc(a, c_d, logger):
e = a+c_d
f = a*c_d
g = e+f
logger.log("e", e)
logger.log("f", f)
logger.log("g", g)
return g
class Logger(object):
data = []
def log(self, key, value):
self.data.append({key: value})
def getLog(self):
return self.data
logger = Logger()
print(calculate(4, 7, logger))
print(logger.getLog())
Pros and cons
I use separated logger class here because then I don't need to know how the logger is implemented. In the example, it is just a simple dictionary but if needed, you can just change the implementation of creating a new logger.
Also, you have a way to choose how to print the data or choose output. Maybe you can have an interface for Logger.
I used a dictionary because it looked like you was just needing key-value pairs.
Now, using the logger, we need to change method signature. Of course, you can define default value as None, for example. Then None value should be checked all the time but that is why I didn't define the default value. If you own the code and can change every reference for the calculate()method, then it should not be a problem.
There is also one interesting thing that could be important later. When you have debugged your output and not need to log anything anymore, then you can just implement Null object. Using Null object, you can just remove all logging without changing the code again.
I was trying to think how to use decorator but now find any good way. If only output should be logged, then decorator could work.
I want to translate some Haskell code into Python.
The Haskell classes/instances look like:
{-# LANGUAGE MultiParamTypeClasses #-}
module MyModule where
class Example a b where
doSomething :: a -> b -> Bool
doSomethingElse :: a -> b -> Int
instance Example Int Int where
doSomething a b = (a + b * 2) > 5
doSomethingElse a b = a - b * 4
Is there a way in Python to approximate the Haskell class/instance construct?
What is the least offensive way to translate this into Python?
This doesn't really have an analogue in Python, but you can fake it:
def int_int_doSomething(a, b):
return (a + b * 2) > 5
def int_int_doSomethingElse(a, b):
return a - b * 4
Example = {}
Example[(int, int)] = (int_int_doSomething, int_int_doSomethingElse)
def doSomething(a, b):
types = type(a), type(b)
return Example[types][0](a, b)
def doSomethingElse(a, b):
types = type(a), type(b)
return Example[types][1](a, b)
All you have to do is add new values to Example for each type combination you want to have. You could even throw in some extra error handling in doSomething and doSomethingElse, or some other methods to make it easier. Another way would be to make an object that keeps track of all of these and lets you add new types to the map in a more managed way, but it's just more bookkeeping on top of what I've already shown.
Keep in mind that this is essentially how Haskell does it, too, except the checks are performed at compile time. Typeclasses are really nothing more than a dictionary lookup on the type to pick the appropriate functions to insert into the computation. Haskell just does this automatically for you at compile time instead of you having to manage it yourself like you do in Python.
To add that bookkeeping, you could do something like the following, keeping it in its own module and then it'll only (by default) export the symbols in __all__. This keeps things looking more like the Haskell version:
class _Example(object):
def __init__(self, doSomething, doSomethingElse):
self.doSomething = doSomething
self.doSomethingElse = doSomethingElse
ExampleStore = {}
def register(type1, type2, instance):
ExampleStore[(type1, type2)] = instance
def doSomething(a, b):
types = type(a), type(b)
return ExampleStore[types].doSomething(a, b)
def doSomethingElse(a, b):
types = type(a), type(b)
return ExampleStore[types].doSomethingElse(a, b)
def Example(type1, type2, doSomething, doSomethingElse):
register(type1, type2, _Example(doSomething, doSomethingElse))
__all__ = [
'doSomethingElse',
'doSomethingElse',
'Example'
]
Then you can make instances like
Example(int, int,
doSomething=lambda a, b: (a + b * 2) > 5,
doSomethingElse=lambda a, b: a - b * 4
)
Which looks almost like Haskell.
You don't have parametric types in Python, as it's dynamically typed. Also the distinction between classes and instances is clear in Python, but as classes are themselves "live objects", the distinction of usage might be a little bit blurred sometimes...
For your case, a classical implementation might go as:
#you don't really need this base class, it's just for documenting purposes
class Example:
def doSomething(self, a, b):
raise "Not Implemented"
def doSomethingElse(self, a, b):
raise "Not Implemented"
class ConcreteClass(Example):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def doSomething(self, a, b):
return (a + b * self.x) > self.y
def doSomethingElse(self, a, b):
return a - b * self.z
instance = ConcreteClass((2, 5, 4)
but I personally dislike that convoluted style, so you might just go with something more lightweight, like:
from collections import namedtuple
Example = namedtuple('Example', 'doSomething doSomethingElse')
instance = Example((lambda a, b: (a + b * 2) > 5),
(lambda a, b: a - b *4 ))
And of course, rely on duck typing and usually "let it crash". The lack of type safety should be made up with extensive unit testing.
I'm trying to write a small Python module which contain some mathematical functions. For example, it might contain a function like:
def quad(x, a, b, c):
return a*x**2 + b*x + c
As you may notice it contains several parameters (viz. a, b, c) apart from the variable x. Now if I were to put this in a file and simply import it, the end user would have to always call the function with the parameters in addition to the variable. Because of this I was thinking of creating a class such as this:
class quad:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def eq(x):
return self.a*x**2 + self.b*x + self.c
Thus allowing the end user to use it as:
q = quad(p, q, r)
eq = q.eq
Is this the right way of doing things? I am terribly sorry about the title of the question, as I couldn't think of a better one!
That seems like a perfectly reasonable use of a class. Essentially you should consider using a class when your program involves things that can be modelled as objects with state. Here, the "state" of your polynomial is just the coefficients a, b, and c.
You can also use Python's __call__ special method to allow you to treat the class as though it were a function itself:
class quad:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __call__(x):
return self.a * x**2 + self.b * x + self.c
q = quad(p, q, r)
q(x)
Yet another way of doing it, which could be slightly cleaner, would be simply to return a function with those coefficients baked into it. This is essentially an example of currying, as Tichodrama mentions:
def quad(a, b, c):
def __quad(x):
return a * x**2 + b * x + c
return __quad
Or using lambda syntax:
def quad(a, b, c):
return lambda x: a * x**2 + b * x + c
These could then be used like so:
q = quad(p, q, r)
q(x)
It looks like you are searching for something like currying.
Perhaps this question can help you.