How to execute only parts of a function? - python

I have defined a class which contains some basic matrix functions. My function for transposing a matrix looks like this:
def transpose(self):
'''
Transpose a matrix.
'''
C = Z ## creating a new zero matrix
for i in range(0, self.rows):
for j in range(0, self.cols):
C.matrix[i][j] = self.matrix[j][i]
## printing the resultant matrix
C.show()
return C
So when I call this function from the interpreter, it prints the result after execution (because of the show() function).
However, when I call this function from another function in the same class, I don't want the matrix to be printed, that is, I don't want the C.show() part to execute.
Is there any way to do this? I was thinking on the lines of __name__ == "__main__" but that doesn't really apply here it seems.

Just add another, default, parameter to the function and put the print in an if:
def transpose(self, print_matrix=True):
'''
Transpose a matrix.
'''
C = Z ## creating a new zero matrix
for i in range(0, self.rows):
for j in range(0, self.cols):
C.matrix[i][j] = self.matrix[j][i]
## printing the resultant matrix
if print_matrix:
C.show()
return C
As it has a default value you don't need to change any current method calls, but you can add another parameter to your new one. Call it as transpose(False), if you don't want to print.

The problem you have is that the calculation and display are both coupled into the same function. In general, tight coupling like this is considered undesirable. Why? Well, you are seeing the problem now, you can't do one part of the function without the other.
Now I could give you crazy answers about how to only print when called from the interpreter, but I would be encouraging bad code. Instead, we should decouple this function into two different function.
Decoupling is simple, take the two different things your code is doing -- printing and calculating -- and separate them into two different functions.
def transpose(self):
'''
Transpose a matrix.
'''
C = Z ## creating a new zero matrix
for i in range(0, self.rows):
for j in range(0, self.cols):
C.matrix[i][j] = self.matrix[j][i]
return C
def transposeAndPrint(self):
C = transpose(self)
C.show()
Now you can call transposeAndPrint when you need to print, and transpose when you don't need to.

Of course I could tell you to add an extra parameter but that won't change the fact that a transpose function should not do printing (except for debug).
def transpose(self):
'''
Transpose a matrix.
'''
C = Z ## creating a new zero matrix
for i in range(0, self.rows):
for j in range(0, self.cols):
C.matrix[i][j] = self.matrix[j][i]
return C
And somewhere else, where you need it:
o.transpose()
o.show()

Another option would be to use Python's logging module. You can set multiple logging levels, which are intended for just this type of situation. In this case, you could make the show function output at the DEBUG level, which you can then easily turn on or off as need be.
See:
http://docs.python.org/2/howto/logging.html

Related

python store function in array

N00b question, maybe.
I am new-ish to python, but I was wondering if it is possible to store a function in an array? I want to do an array multiplication, where the value of one array is multiplied by a function on a location of another array of functions. Or actually, the value of the first array is inserted in the function of the designated location. This should create a new array where the values are an outcome of the "multiplication".
>>> import numpy as np
>>> a = [[1, 0], [0, 1]]
>>> b = [[f(x), g(x)], [(h(x), f(x)]]
>>> np.dot(a, b)
array([[0, 1],
[2, 0]])
Assuming that f(x), g(x) and h(x) are defined functions. In this case python will say that x is not defined. So far I know. However, I do not want to say, for example, f(a[0][1]), because I want to reuse array b and also be able to put the functions on random locations in the array.
In short I detect three questions:
- Is there a known way to have an array where the values are functions?
- If not, should I redefine an array function or write a new class for this? (how do I attack this problem?)
- If it is possible to create an array of functions, can I fill the 'function values' dynamically in the array (populate the array dynamically with functions) or can it only be static values?
like for example
b[0]=f(x)
And yes, I really want to do this with python.
f(x) is not a function (even in mathematics). The function is f. In python there is no problem to store functions in array:
def my_func():
print("Foo")
my_other_func = lambda: print("Bar")
my_arr = [my_func, my_other_func]
Your example puts the result of calling a function into your array.
b[0] = f
actually puts the function itself into the array, so that
b[0](x)
would have the same effect as
f(x)
Is there a known way to have an array where the values are functions?
There is, as stated by others already.
def my func(x):
return x
my_other_func = lambda x: x
l = [my_func, my_other_func]
If not, should I redefine an array function or write a new class for this? (how do I attack this problem?)
Not relevant
If it is possible to create an array of functions, can I fill the 'function values' dynamically in the array (populate the array dynamically with functions) or can it only be static values?
The 'function values' are called parameters and can be assigned after having the function in the array:
a[0](5) # == my_func(5)
a[1]('Hello') # == my_other_func('Hello')
The problem is that you are trying to use matrix multiplication as parameter passing and that will not work, you could create a helper fucntion that does it.
def callByElements(parameterMatrix, functionMatrix):
rows = len(parameterMatrix)
cols = len(parameterMatrix[0])
result = np.zeros( (rows, cols) )
for i in range(rows):
for j in range(cols):
result[i,j] = functionMatrix[i,j](parameterMatrix[i,j])
return result

Checking input values to methods to reduce the number of computations

I have a number of methods that are independent of each other but are needed collectively to compute an output. Thus, when a variable in any of the methods changes all the methods are called in the computation which is slow and expensive. Here is a quick pesudo-code of what I have:
# o represents an origin variable
# valueA represents a variable which can change
def a (o, valueA):
# calculations
return resultA
def b (o, valueB):
# calculations
return resultA
def c (o, valueC1, valueC2):
# calculations
return resultA
def compute (A, B, C1, C2):
one = self.a(o, A)
two = self.b(one,B)
three = self.c(two, C1, C2)
return img
For example when the value of C1 changes, when calling compute all the methods are calculated despite a & b having no change. What I would like is some way of checking which of the values of A,B,C1,C2 have changed between each call to compute.
I have considered defining a list of the values then on the next call comparing it to the new values being pass to compute. Eg; 1st call: list=[1,2,3,4] on 2nd call list=[1,3,4,5] so b & c need calculating but a is the same. However, I am unsure as to how to go from the comparison to defining which method to call?
Some background on my particular application in case it is of use. I have a wxPython window with sliders that determine values for image processing and an image is drawn on each change of these sliders.
What is the best way to compare each call to compute and remove these wasted repeated computations?
If i have to solve this, I would use a Dictionary, where the key is the valueX (or a list of it if have more than one, in your example C) and the value should be the result of the function.
So, you should have something like that:
{ valueA: resultA, valueB: resultB, [valueC1, valueC2]: resultC }
To do that, in the functions you will have to add it:
def a(o, valueA):
[calcs]
dic[valueA] = resultA
return resultA
[...]
def c(o, valueC1, valueC2)
[calcs]
dic[[valueC1, valueC2]] = resultC
return resultC
And, in the function that computes, you can try to get the value for the parameters and if not get the value, calculate it
def compute (A, B, C1, C2):
one = dic.get(A) if dic.get(A) else self.a(o, A)
two = dic.get(B) if dic.get(B) else self.b(one,B)
three = dic.get([C1,C2]) if dic.get([C1,C1]) else self.c(two, C1, C2)
return img
P.D: this is the "crude" implementation of memoize functions that #holdenweb pointed in his comment.
You could consider making the methods memoizing functions that use a dict to look up the results of previously stored computations (probably best in the class namespace to allow memoizing to optimize across all instances).
The memory requirements could be quite severe, however, if the methods are called with many arguments, in which case you might want to adopt a "publish and subscribe" pattern to try and make your computation more "systolic" (driven by changes in the data, loosely).
That' a couple of approaches. I'm sure SO will think of more.

Initialize Multiple Numpy Arrays (Multiple Assignment) - Like MATLAB deal()

I was unable to find anything describing how to do this, which leads to be believe I'm not doing this in the proper idiomatic Python way. Advice on the 'proper' Python way to do this would also be appreciated.
I have a bunch of variables for a datalogger I'm writing (arbitrary logging length, with a known maximum length). In MATLAB, I would initialize them all as 1-D arrays of zeros of length n, n bigger than the number of entries I would ever see, assign each individual element variable(measurement_no) = data_point in the logging loop, and trim off the extraneous zeros when the measurement was over. The initialization would look like this:
[dData gData cTotalEnergy cResFinal etc] = deal(zeros(n,1));
Is there a way to do this in Python/NumPy so I don't either have to put each variable on its own line:
dData = np.zeros(n)
gData = np.zeros(n)
etc.
I would also prefer not just make one big matrix, because keeping track of which column is which variable is unpleasant. Perhaps the solution is to make the (length x numvars) matrix, and assign the column slices out to individual variables?
EDIT: Assume I'm going to have a lot of vectors of the same length by the time this is over; e.g., my post-processing takes each log file, calculates a bunch of separate metrics (>50), stores them, and repeats until the logs are all processed. Then I generate histograms, means/maxes/sigmas/etc. for all the various metrics I computed. Since initializing 50+ vectors is clearly not easy in Python, what's the best (cleanest code and decent performance) way of doing this?
If you're really motivated to do this in a one-liner you could create an (n_vars, ...) array of zeros, then unpack it along the first dimension:
a, b, c = np.zeros((3, 5))
print(a is b)
# False
Another option is to use a list comprehension or a generator expression:
a, b, c = [np.zeros(5) for _ in range(3)] # list comprehension
d, e, f = (np.zeros(5) for _ in range(3)) # generator expression
print(a is b, d is e)
# False False
Be careful, though! You might think that using the * operator on a list or tuple containing your call to np.zeros() would achieve the same thing, but it doesn't:
h, i, j = (np.zeros(5),) * 3
print(h is i)
# True
This is because the expression inside the tuple gets evaluated first. np.zeros(5) therefore only gets called once, and each element in the repeated tuple ends up being a reference to the same array. This is the same reason why you can't just use a = b = c = np.zeros(5).
Unless you really need to assign a large number of empty array variables and you really care deeply about making your code compact (!), I would recommend initialising them on separate lines for readability.
Nothing wrong or un-Pythonic with
dData = np.zeros(n)
gData = np.zeros(n)
etc.
You could put them on one line, but there's no particular reason to do so.
dData, gData = np.zeros(n), np.zeros(n)
Don't try dData = gData = np.zeros(n), because a change to dData changes gData (they point to the same object). For the same reason you usually don't want to use x = y = [].
The deal in MATLAB is a convenience, but isn't magical. Here's how Octave implements it
function [varargout] = deal (varargin)
if (nargin == 0)
print_usage ();
elseif (nargin == 1 || nargin == nargout)
varargout(1:nargout) = varargin;
else
error ("deal: nargin > 1 and nargin != nargout");
endif
endfunction
In contrast to Python, in Octave (and presumably MATLAB)
one=two=three=zeros(1,3)
assigns different objects to the 3 variables.
Notice also how MATLAB talks about deal as a way of assigning contents of cells and structure arrays. http://www.mathworks.com/company/newsletters/articles/whats-the-big-deal.html
If you put your data in a collections.defaultdict you won't need to do any explicit initialization. Everything will be initialized the first time it is used.
import numpy as np
import collections
n = 100
data = collections.defaultdict(lambda: np.zeros(n))
for i in range(1, n):
data['g'][i] = data['d'][i - 1]
# ...
How about using map:
import numpy as np
n = 10 # Number of data points per array
m = 3 # Number of arrays being initialised
gData, pData, qData = map(np.zeros, [n] * m)

list() function of Python modifies its argument?

(I am quite a newbie in Python, so lots of things puzzle me even after reading the tutorial...)
Initially, I had the code like the following:
strings = ['>abc', 'qwertyu', '>def', 'zxcvbnm']
matrix = zip(*strings)
for member in matrix:
print("".join(member)) # characters are printed as expected
-- which did what I expected. But then for some reason I wanted to determine the number of members in matrix; as len(matrix) gave an error, I decided to copy it with converting to the list: mtxlist = list(matrix). Surprisingly, after this line the content of matrix seems to be changed - or at least I cannot use it the same way as above:
strings = ['>abc', 'qwertyu', '>def', 'zxcvbnm']
matrix = zip(*strings)
mtxlist = list(matrix) # this assignment empties (?) the matrix
for member in matrix:
print("".join(member)) # nothing printed
Can anybody explain what is going on there?
You're using Python 3, correct?
zip returns a generator that can only be iterated once. If you want to use it more than once, then your options are:
Write zip(*strings) each time you need it.
matrix = tuple(zip(*strings))
(iterate matrix as many times as you like. This is the easy option. The downside is that if zip(*strings) is big then it uses a lot of memory that the generator doesn't.)
matrix1, matrix2 = itertools.tee(zip(*strings))
(iterate each of matrix1 and matrix2 once. This is worse than the tuple in your usage, but it's useful if you want to partially consume matrix1, then use some of matrix2, more of matrix1, etc)
def matrix():
return zip(*strings)
# or
matrix = lambda: zip(*strings)
(iterate but using matrix(), not matrix, as many times as you like. Doesn't use extra memory for a copy of the result like the tuple solution, but the syntax for using it is a bit annoying)
class ReusableIterable:
def __init__(self, func):
self.func = func
def __iter__(self):
return iter(self.func())
matrix = ReusableIterable(lambda: zip(*strings))
(iterate using matrix as many times as you like. Deals with the syntax annoyance, although you still have to beware that if you modify strings between iterations over matrix then you'll get different results.)

Zip function in python 3.2.3 not working as hoped

I am trying to define a function that transposes a matrix. This is my code:
def Transpose (A):
B = list(zip(*A))
return B
Now when I call the function somewhere in the program like such:
Matrix = [[1,2,3],[4,5,6],[7,8,9]]
Transpose(Matrix)
print(Matrix)
The matrix comes out unchanged. What am I doing wrong?
Your function returns a new value that does not affect your matrix (zip does not change it's parameters). You are not doing anything wrong, that is the correct way of doing things.
Just change it to:
print(Transpose(Matrix))
or
Matrix = Transpose(Matrix)
Note: You really should be using lower-case names for your functions and variables.

Categories

Resources