How can I update different arguments to the same function? - python

I have a function R(t) defined as:
def R(t) :
if t > 0 :
return "R"
else :
return 0
Now, I want to have several instances of this function working at once. For example, whenever a given condition is met, I would like to generate an R(2) and then, for every iteration of a for loop, I would like to subtract 1 from the argument. My problem comes when the condition is met several times in distinct iterations of the loop, so while there might be an R(2) just appearing, there will be an R(1) turning into an R(0).
I am barely learning how to use python, but I don't think that the code enabling me from accomplishing what I want is very hard. I believe that maybe if I define R(t,j) and use jas an indexing parameter it might be easier to code.

A recursive function that does what you want is:
def R(t):
if t > 0:
print "R"
return R(t-1)
else:
print t

Related

I can't put "continue" command in a definition?

Let's say,
def sample():
if a==1:
print(a)
else:
continue
for i in language:
a=i
sample()
I want to use this function in a loop, but the continue command gives me an error because there is no loop. What can I do?
Return a boolean from the function and based on the return value make continue or not because continue must be within a loop
continue keyword in python is only available in for or while loops. Also block defined variables like a are not available on the global scope.
I don't know what you want to achieve but assuming your code, you want to extract a condition into a function, something like this:
def condition(a):
return a == 1
def sample(a):
print(a)
for i in language:
a=i
if condition(a):
sample(a)
else:
continue
There are several best-practice patterns of exactly how to do this, depending on your needs.
0. Factor your code better
Before doing any of the below, stop and ask yourself if you can just do this instead:
def sample(a):
print(a)
for i in language:
if i != 1:
continue
sample(i)
This is so much better:
it's clearer to the reader (everything you need to understand the loop's control flow is entirely local to the loop - it's right there in the loop, we don't have to look anywhere else farther away like a function definition to know when or why or how the loop will do the next thing),
it's cleaner (less boilerplate code than any of the solutions below),
it's more efficient, technically (not that this should matter until you measure a performance problem, but this might appeal to you; going into a function and coming back out of it, plus somehow telling the loop outside the function to continue - that's more work to achieve the same thing), and
it's simpler (objectively: there is less code complected together - the loop behavior is no longer tied to the body of the sample function, for example).
But, if you must:
1. Add boolean return
The simplest change that works with your example is to return a boolean:
def sample(a):
if a==1:
print(a)
else:
return True
return False
for i in language:
if sample(i):
continue
However, don't just mindlessly always use True for continue - for each function, use the one that fits with the function. In fact, in well-factored code, the boolean return value will make sense without even knowing that you are using it in some loop to continue or not.
For example, if you have a function called check_if_valid, then the boolean return value just makes sense without any loops - it tells you if the input is valid - and at the same time, either of these loops is sensible depending on context:
for thing in thing_list:
if check_if_valid(thing):
continue
... # do something to fix the invalid things
for thing in thing_list:
if not check_if_valid(thing):
continue
... # do something only with valid things
2. Reuse existing return
If your function already returns something, or you can rethink your code so that returns make sense, then you can ask yourself: is there a good way to decide to continue based on that return value?
For example, let's say inside your sample function you were actually trying to do something like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
else:
continue
Well then you can rewrite it like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
return record
for i in language:
record = sample(a)
if record.status != 1:
continue
Of course in this simple example, it's cleaner to just not have the sample function, but I am trusting that your sample function is justifiably more complex.
3. Special "continue" return
If no existing return value makes sense, or you don't want to couple the loop to the return value of your function, the next simplest pattern is to create and return a special unique "sentinel" object instance:
_continue = object()
def sample(a):
if a==1:
print(a)
else:
return _continue
for i in language:
result = sample(i):
if result = _continue:
continue
(If this is part of a module's API, which is something that you are saying if you name it like sample instead of like _sample, then I would name the sentinel value continue_ rather than _continue... But I also would not make something like this part of an API unless I absolutely had to.)
(If you're using a type checker and it complains about returning an object instance conflicting with your normal return value, you can make a Continue class and return an instance of that instead of an instance of object(). Then the type hinting for the function return value can be a type union between your normal return type and the Continue type. If you have multiple control flow constructs in your code that you want to smuggle across function call lines like this.)
4. Wrap return value (and "monads")
Sometimes, if the type union thing isn't good enough for some reason, you may want to create a wrapper object, and have it store either your original return value, or indicate control flow. I only mention this option for completeness, without examples, because I think the previous options are better most of the time in Python. But if you take the time to learn about "Option types" and "maybe monads", it's kinda like that.
(Also, notice that in all of my examples, I fixed your backdoor argument passing through a global variable to be an explicit clearly passed argument. This makes the code easier to understand, predict, and verify for correctness - you might not see that yet but keep an eye out for implicit state passing making code harder to follow and keep correct as you grow as a developer, read more code by others, and deal with bugs.)
It is because the scope of the function doesn't know we are in a loop. You have to put the continue keyword inside the loop
continue keyword cannot be used inside a function. It must be inside the loop. There is a similar question here. Maybe you can do something like the following.
language = [1,1,1,2,3]
a = 1
def sample():
if a == 1:
print(a)
return False
else:
return True
for i in language:
if sample():
continue
else:
a = i
OR something like this:
language = [1,1,1,2,3]
a = 1
def gen(base):
for item in base:
if a == 1:
yield a
else:
continue
for i in gen(language):
a = i
print(a)

why one line python loop and traditional loop return different results?

I have array, where I for sure know, there are two objects, which meet conditions, that I want to loop
if I do
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
result = []
for check in checks:
if check.lcode == lcode and check.admin == admin_uid:
result.append(check)
return result
returns correct array with 2 objects
but this code
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
return [check for check in checks if check.admin == admin_uid and check.lcode == lcode]
return 0
what im I doing wrong ?
Until we have a sample input, we can only speculate. In principle both versions of your code should be equivalent, but just to be sure write the conditions in the same order in both:
def filter_checks_by_lcode_and_admin(admin_uid, lcode, checks):
return [check for check in checks if check.lcode == lcode and check.admin == admin_uid]
If that changes the result, then it's because your code has some kind of side effect that makes the result be different between invocations depending on the order of execution. Certainly something to avoid, as you can see, it'll lead to hard to find bugs.
Also you can try executing your code with the same input, but trying the second snippet first and the first snippet later. If this works, then again it'll be a sign that something is changing the state of the inputs between executions, definitely a problem that should be fixed.

Recursive function that saves a number provided certain conditions

I'm trying to create a function in Python that, using recursion, saves a certain number if it is greater than or equal to another previously provided in input (and saved on another variable).
a = 6
def attempts(k):
n = int(input("How many attempts do you want to make? "))
if n>=k:
return n
else:
print("You must make at least {} attempts to play!".format(k))
attempts(k)
b = attempts(a)
The problem is that, if I don't immediately insert the "correct" number, the variable "b" becomes a NoneType. How can I solve this problem?
Sorry for any typos, I'm not a native speaker.
Change your last line of the function to:
return attempts(k)
Currently, results starting from the first recursive call (if it occurs) are thrown away, which results in None being returned by the outermost call.
In the else statement, you are not returning anything, setting b equal to nothing. Add a return statement in the else statement and return whatever you want b to equal to if the else statement comes up.
The way your code works right now, you should add return attempts(k) in your else statement and remove the current last line, attempts(k) This will work the same, except b will have a value.
In the else case you evaluate attempts(k) but don't return it. So it's evaluated as a None. Change
attempts(k)
To
return attempts(k)

How to stop Function reassigning Boolean value within loop

Im trying to learn Python via creating a basic language-learning app to test myself. In order to get it to test me with a different word each time I have tried to write a function that generates an intial key ONLY IF it is the first time it is run (after this i have another function which should generate a different key).
In order to do this I have tried to us a Boolean (isfirsttime) which I initially set to False within the main loop of the particular Tkinter window in which this part of the code runs (sorry if I'm not explaining this particulary well am admittedly a total begginer!).
Within my function I then check if this value is False and then - it is - i generate a key and pass out this plus the value TRUE.
Back in the main loop I then assign the value True to the variable isfirsttime.
I think that the problem is that in the main loop the isfirsttime is FIRST assigned to False (to get the function checkfirst to work the first time) but this means that every time it is run it resets the Boolean to False.
Could anybody explain to me how I can reassign the value of isfirst time to TRUE after the first time the code has run, in a way that will cause the checkfirst function to PASS everytime after that? (I know that my problem has something to do with scope but i cannot figure it out - and have tried functions within functions and endlessly reassigning variables so I'm obviously not getting something here!)
Many thanks!
isfirsttime == False
def checkfirst():
if isfirsttime==False:
for item in categories:
newkey=random.choice(list(tempdict))
print("key is" + newkey)
isfirsttime=not isfirsttime
print(str(isfirsttime) + "isfirsttime")
return newkey, True
else:
pass
genkey=checkfirst()[0]
isfirsttime=checkfirst()[1]
You can make the call like this:
genkey, isfirsttime = checkfirst()
However, you still need to do something about the second time that checkfirst() is called.
Also, reading the comments under your question you need to sort out the assignment to isfirsttime:
isfirsttime = False # assign isfirsttime to False
def checkfirst():
# stuff omitted

Count iterations of pandas dataframe apply function

I'm looking for a way to count how many times my database function runs.
My code looks like this
df = pd.read_csv("nodos_results3.csv")
df['URL_dashboard'] = df.apply(create_url, axis = 1)
df.to_csv('nodos_results4.csv', index = False)
I want to count how many times the function "create_url" runs. If I was in C++, for example, I would simply have the function take in another input
create_url(database i_DB, int i_count)
{
//stuff I want done to database
i_count++;
}
but I'm not sure how to do something equivalent using pandas dataframe apply.
Update: For anyone who might find this while googling in the future - I personally didn't solve this issue. I was moved to another project and didn't continue working on this. Sorry I can't be more help.
apply executes the function exactly once for each row. So, the function is executed df.shape[0] times. Correction: As per #juanpa.arrivillaga, apply executes the function twice on the first row, the correct answer is df.shape[0]+1.
Alternatively, create a global variable (say, create_url_counter=0) and increment it in the function body:
def create_url(...):
global create_url_counter
...
create_url_counter += 1
Be aware, though, that having global variables is in general a bad idea.

Categories

Resources