python: function that will call itself - python

i was wondering if i can get your help with the stucture.logic of a function that will need to call itself
def populate_frequency5(d,data,total_compare):
freq=[]
prev = None
for row in d:
if prev is None or prev==row[11]:
freq.append(row[16])
doctor=row[10]
drug=row[11][:row[11].find(' ')].capitalize()
else:
make_image_url_doctor(freq,doctor,drug,data)
total_compare=True
del freq[:]
prev=row[11]
if total_compare:
(b1,bla,bla1)=medications_subset2(data,[drug.upper()])
data1=calculate_creat_conc4(b1)
populate_frequency5(data1,['a'],total_compare=True)
total_compare=False
the first time the function is called i need it to run this:
def populate_frequency5(d,data,total_compare):
freq=[]
prev = None
for row in d:
if prev is None or prev==row[11]:
freq.append(row[16])
doctor=row[10]
drug=row[11][:row[11].find(' ')].capitalize()
else:
make_image_url_doctor(freq,doctor,drug,data)
(b1,bla,bla1)=medications_subset2(data,[drug.upper()])
data1=calculate_creat_conc4(b1)
del freq[:]
prev=row[11]
then somehow the second time when i call it, i need it to run this way:
def populate_frequency5(d,data,total_compare):
freq=[]
prev = None
for row in d:
if prev is None or prev==row[11]:
freq.append(row[16])
doctor=row[10]
drug=row[11][:row[11].find(' ')].capitalize()
run_another_function()

Your current logic is faulty and will lead to runaway recursion. If you ever make a recursive call, you'll pass it a total_compare of True; but then within that recursive call it will not be set to False again, so when checked it will be true and yet another recursive call (with the same defect) will inevitably result.
The setting of total_compare in the calling instance (were it ever to execute, which it won't because of the runaway recursion) is irrelevant: it's the last statement ever executed there and it's setting a local variable, so of course it can be removed without any observable effects. Maybe you don't realize that each instance of a function in recursive calls has its own set of local variables (including arguments -- they're also local variables, just ones that get initializer by the caller), which is why I'm pointing this out explicitly.
Your examples "desired code" 1 and 2 don't really help because they never show the function calling itself. Under what conditions, exactly, does the function need to call itself recursively (a) if it was called non-recursively, (b) if it was already called recursively? Remember that, to avoid runaway recursion, there must be eventually reached a "base case" where no further recursion occurs.
Given that in your first ("runaway recursion") example the recursive call appears to be the last action of the caller (net of the useless and therefore removable setting of the total_compare local variable), I should also point out that such "tail recursion" can easily be turned into iteration (and, in Python, that's usually advisable, since Python does not optimize tail recursion as other languages do).

Related

Running function code only when NOT assigning output to variable?

I am looking for a way in python to stop certain parts of the code inside a function but only when the output of the function is assigned to a variable. If the the function is run without any assignment then it should run all the inside of it.
Something like this:
def function():
print('a')
return ('a')
function()
A=function()
The first time that I call function() it should display a on the screen, while the second time nothing should print and only store value returned into A.
I have not tried anything since I am kind of new to Python, but I was imagining it would be something like the if __name__=='__main__': way of checking if a script is being used as a module or run directly.
I don't think such a behavior could be achieved in python, because within the scope of the function call, there is no indication what your will do with the returned value.
You will have to give an argument to the function that tells it to skip/stop with a default value to ease the call.
def call_and_skip(skip_instructions=False):
if not skip_instructions:
call_stuff_or_not()
call_everytime()
call_and_skip()
# will not skip inside instruction
a_variable = call_and_skip(skip_instructions=True)
# will skip inside instructions
As already mentionned in comments, what you're asking for is not technically possible - a function has (and cannot have) any knowledge of what the calling code will do with the return value.
For a simple case like your example snippet, the obvious solution is to just remove the print call from within the function and leave it out to the caller, ie:
def fun():
return 'a'
print(fun())
Now I assume your real code is a bit more complex than this so such a simple solution would not work. If that's the case, the solution is to split the original function into many distinct one and let the caller choose which part it wants to call. If you have a complex state (local variables) that need to be shared between the different parts, you can wrap the whole thing into a class, turning the sub functions into methods and storing those variables as instance attributes.

returning values of function in python

Why do I have to return function in the else case? Can't I just apply the defined function because I have to only return the value of b and store it?
def gcd_a(a,b):
if a==0:
return b
else:
gcd_a(b%a,a)
I think the main concept you are missing is that in order to get the result of a recursive function (or any function for that matter), the function that you access the result of must return the value*
Right now, when you call gcd_a, a recursive call to gcd_a will eventually return a value, however it will be lost, since the function that you are accessing the result of does not return a value.
To show you this is true, let's add in a log statement that prints when the function is returning:
def gcd_a(a,b):
if a==0:
print('finally returning!', b)
return b
else:
gcd_a(b%a,a)
Now if we call:
print(gcd_a(10, 99))
We get the following output:
finally returning! 1
None
Somewhere, a recursive call to gcd_a found your condition to be True, and returned 1, however, this result is not printed, because it is not returned by your call to gcd_a
* Unless you do something strange like updating a global variable, etc...
If your function finishes without returning anything, it will implicitly return None.
def double(val):
val * 2
value = double(10)
print(value)
Which is fine, except it doesn't have a return statement, and so all you get is None
The same applies to recursive functions: you can do all the recursive function calls you want, but if you don't actually return the result of the function, then it'll return None.
IMHO, the problem is in the way you are thinking about function which has to be cleared. The fact that you are having this doubt in a recursive function call is incidental because you are calling the same function again and again with different arguments causing different branches to be executed.
How will a function that doesn't return anything in any of its branches be helpful to its caller? In your case, what would happen if your function's caller calls it with an argument that hits your else block? It will return nothing and this won't help the caller!
Now in your recursive case, if your caller calls the function with an argument that hits the if block, then it would work as expected. However, if it hits the else block, then it would become a caller and call the same function again. For simplicity, let us assume that this time it hits the if condition and returns something to its caller. However, will that reach the original caller that initiated everything? The answer is no because you are not returning it to him!
Most of the times you would need a return for every branch in a function
unless you are doing it on purpose for a side effect.
In the else block, if you don't return the function call, the outer function returns None because python interpreter just runs whatever is returned by the gcd function.
Let's assume the following code:
def func():
10
In that function, it just runs 10, but it doesn't mean that there is some return from the function.

Local Function Call on itself

Learning python, searched for this problem, and having a hard time figuring out why I'm getting the behavior that I am. I'm getting the correct output, but I'm not sure why, I'd just like to know going forward just to better understand this concept. Let me explain:
if create a function such as
def function(list):
and I then call this function on a list x
print function(x)
if I were then to recall this function with the function itself like so:
def function(list):
function(list)
why does that recursive call still hold the values for x which was called globablly?
The "list" in the parameter list is then passed to the next call. Each one is a direct copy of x. It's not the global x; it's the local copy in the variable list that gets passed down.
Note that this is a direct example of infinite recursion: there's no way to stop the chain of the function calling itself. Instead, you might want something like
def function(list):
if len(list) == 0:
return "end"
else
return function(list[1:]) + list[0]
A recursive function needs a terminating condition and something to return.

Bad form to return None in __init__ in python

I was tinkering around with some classes and I came upon a situation where I wanted to cut off __init__ before it got a chance to do anything more. To do so, I simply put a null return statement at the end of the block I wanted to cut off at. For example:
class Example(object):
def __init__(self):
#lots and lots of code
if so_and_so:
return
Is it bad form to return inside __init__, even if it's just under this circumstance?
For any function, not only __init__, using plain return is equivalent to returning None, and if you don't use return in a function, None is implicitly returned anyway.
Therefor, it is perfectly fine to use return inside __init__.
(The exception to the rule above is generator functions, inside which you may only use return and not return None, so these are not equivalent inside generator functions).
Returning in the middle of __init__ will simply cut off object's initialization. It will not prevent the object from being created, nor interrupt program's flow in any way.
How long is a piece of string? If you don't need to initialize any further, then there's no point in continuing. Since None is returned implicitly at the end anyway (and in fact should be the only thing ever returned by __init__()), returning it early if initialization has been completed is fine.
OTOH, if you need to abort initialization then you should raise an exception instead.

Python default values for class member function parameters set to member variables

I am running into a problem writing recursive member functions in Python. I can't initialize the default value of a function parameter to be the same value as a member variable. I am guessing that Python doesn't support that capability as it says self isn't defined at the time I'm trying to assign the parameter. While I can code around it, the lack of function overloading in Python knocks out one obvious solution I would try.
For example, trying to recursively print a linked list I get the following code for my display function;
def display(self,head = -1):
if head == -1:
head = self.head
if not head:
return
print head,
self.display(head.link)
While this code works, it is ugly.
The main function looks like this:
def main():
l = List();
l.insert(3);
l.insert(40);
l.insert(43);
l.insert(45);
l.insert(65);
l.insert(76);
l.display()
if __name__ == "__main__":
main()
If I could set the display function parameter to default to self.head if it is called without parameters then it would look much nicer. I initially tried to create two versions of the function, one that takes two parameters and one that takes one but as I said, Python doesn't support overloading. I could pass in an argument list and check for the number of arguments but that would be pretty ugly as well (it would make it look like Perl!). The trouble is, if I put the line
head = self.head
inside the function body, it will be called during every recursive call, that's definitely not the behavior I need. None is also a valid value for the head variable so I can't pass that in as a default value. I am using -1 to basically know that I'm in the initial function call and not a recursive call. I realize I could write two functions, one driving the other but I'd rather have it all self contained in one recursive function. I'm pretty sure I'm missing some basic pythonic principle here, could someone help me out with the pythonic approach to the problem?
Thanks!
I don't really see what's wrong with your code. If you chose a falsy default value for head, you could do: head = head or self.head which is more concise.
Otherwise, this is pretty much what you have to do to handle default arguments. Alternatively, use kwargs:
def display(self,**kwargs):
head = kwargs.get("head", self.head)
if not head:
return
print head,
self.display(head=head.link) # you should always name an optional argument,
# and you must name it if **kwargs is used.

Categories