input function inside a nested function in python - python

This is strange. I have searched this problem, but I didn't find any similar question. The following code in Python 3.X is the simplest model that I can explain.
def is_correct(function,wait_sec=0.5):
while True:
output = function
is_correct = input('Is the input correct(y(Enter)/n)?')
time.sleep(1)
if is_correct.lower() in ['','y','yes']:
clear_output()
time.sleep(wait_sec)
return output
clear_output()
time.sleep(wait_sec)
def whileloop(fun):
while True:
fun
def INPUT():
result=input('...')
def hello_world():
print('hello world')
def forloop(fun):
for i in range(3):
fun
Thus, when I run forloop(INPUT()), it only let me input two times. when I run whileloop(INPUT()), I got one input and then an infinite loop. Most strangely, when I run is_correct(hello_world), it only print 'hello world' once.
Any idea?

You are missing () when using argument fun or function inside functions,
And when you call the functions, you should pass the argument without () like forloop(INPUT) and whileloop(INPUT)
def is_correct(function,wait_sec=0.5):
while True:
output = function()
is_correct = input('Is the input correct(y(Enter)/n)?')
#time.sleep(1)
if is_correct.lower() in ['','y','yes']:
#clear_output()
#time.sleep(wait_sec)
return output
#clear_output()
#time.sleep(wait_sec)
def whileloop(fun):
while True:
fun()
def INPUT():
result=input('...')
def hello_world():
print('hello world')
def forloop(fun):
for i in range(3):
fun()
forloop(INPUT)

Related

Using straing/data from another function

I'm trying to use returned data from one function into multiple other functions. But I don't want the first function to run each time; which is happening in my case.
#Function lab
def func_a():
print('running function a')
data = 'test'
return data
def func_b():
print(func_a())
def func_c():
print(func_a())
def func_d():
print(func_a())
if __name__ == '__main__':
func_a()
func_b()
func_c()
func_d()
Each time that whole function_a runs. But I just want the returned data from "func_a" in other functions.
IIUC, you could alleviate this with a simple class.
I hold the state of the class which runs func_a in a variable called output. I can then reference this output variable once the class has finished running as much as I like in all other functions without having to re-run func_a.
Hope this helps!
class FunctionA:
def __init__(self):
self.output = None
def run_function(self):
print('running function a')
data = 'test'
self.output = data
def func_b():
print(func_a.output)
def func_c():
print(func_a.output)
def func_d():
print(func_a.output)
if __name__ == '__main__':
func_a = FunctionA()
func_a.run_function()
func_b()
func_c()
func_d()
>>> running function a
>>> test
>>> test
>>> test
Your func_a does two things. To make this clear, let's call it, print_and_return_data.
There are several ways to to break apart the two things print_and_return_data does. One way is to split up the two behaviors into smaller sub-methods:
def print_and_return_data():
print('running function a') # keeping the old print behavior
data = 'test'
return data
into:
def print_run():
print('running function a') # keeping the old print behavior
def return_data():
return 'test'
def print_and_return_data():
print_run()
return return_data()
So that other functions only use what they need:
def func_b():
print(return_data())
Another way is to change print_and_return_data to behave differently the first time it's called from the following times it's called (I don't recommend this because functions changing based on how many times it's been called can be confusing):
context = {'has_printed_before': False}
def print_and_return_data():
if not context['has_printed_before']:
print('running function a')
context['has_printed_before'] = True
data = 'test'
return data
def func_b():
print(print_and_return_data())
if __name__ == '__main__':
func_a() # prints
func_b() # won't print
One way to avoid "functions behaving differently when they're called" is to pass the variation (the "context") in as an argument:
def return_data(also_print=False):
if also_print:
print('running function a')
data = 'test'
return data
def func_b():
print(return_data())
if __name__ == '__main__':
func_a(also_print=True) # prints
func_b() # won't print

How to set a prefix for all print() output in python?

I am printing to a console in python. I am looking for a one off piece of code so that all print statments after a line of code have 4 spaces at the start. Eg.
print('Computer: Hello world')
print.setStart(' ')
print('receiving...')
print('received!')
print.setStart('')
print('World: Hi!')
Output:
Computer: Hello world
receiving...
received!
World: Hi!
This would be helpful for tabbing all of the output that is contained in a function, and setting when functions output are tabbed. Is this possible?
You can define a print function which first prints your prefix, and then internally calls the built-in print function. You can even make your custom print() function to look at the call-stack and accordingly determine how many spaces to use as a prefix:
import builtins
import traceback
def print(*objs, **kwargs):
my_prefix = len(traceback.format_stack())*" "
builtins.print(my_prefix, *objs, **kwargs)
Test it out:
def func_f():
print("Printing from func_f")
func_g()
def func_g():
print ("Printing from func_g")
func_f()
Output:
Printing from func_f
Printing from func_g
Reverting back to the built-in print() function:
When you are done with your custom printing, and want to start using the built-in print() function, just use del to "delete" your own definition of print:
del print
Why not define your own custom function and use that when needed:
def tprint(*args):
print(' ', *args)
It would be used like so:
print('Computer: Hello world')
tprint('receiving...')
tprint('received!')
print('World: Hi!')
Output:
Computer: Hello world
receiving...
received!
World: Hi!
You might want to use specific prefixes only at specific places
import sys
from contextlib import contextmanager
#contextmanager
def add_prefix(prefix):
global is_new_line
orig_write = sys.stdout.write
is_new_line = True
def new_write(*args, **kwargs):
global is_new_line
if args[0] == "\n":
is_new_line = True
elif is_new_line:
orig_write("[" + str(prefix) + "]: ")
is_new_line = False
orig_write(*args, **kwargs)
sys.stdout.write = new_write
yield
sys.stdout.write = orig_write
with add_prefix("Computer 1"):
print("Do something", "cool")
print("Do more stuffs")
with add_prefix("Computer 2"):
print("Do further stuffs")
print("Done")
#[Computer 1]: Do something cool
#[Computer 1]: Do more stuffs
#[Computer 2]: Do further stuffs
#Done
The advantage is that it's a utility function, i.e. you just have to import to use it, without having to redefine every time you write a new script.

How do I call two functions on the same line in third function?

def star():
print("***")
def slash():
print("///")
def main():
print(star(), slash())
main()
I would like this to print "***///" but I am unable to print them on the same line without getting an error.
Your functions star() and slash() call print() and they don't return any value. But your function main() is trying to print the values they return. You need to make up your mind where control of the printing is going to be. And it probably shouldn't be in star() and slash() because you want control over whether the output is on one line or not, and those functions can't tell what is also on the line. You could do it this way:
def star():
return "***"
def slash():
return "///"
def main():
print(star(), slash())
main()
What you really want is:
def star():
return "***"
def slash():
return "///"
def main():
print(star(), slash(), sep='')
main()
You need to return the string you want to print. Otherwise, you are will get:
***
///
None None
You wouldn't run print(print('value')) but that is what you are doing here. Rather you should say that you want the function you are calling to the first value and the second with another value. Then you can simply add them together.
You could use the return statement and create a variable.
For example:
def star():
return "***"
def slash():
return "///"
def main():
a = star() + slash()
print(a)
main()
You can read about them here
Try this
def star():
print("***", end = "")
def slash():
print("///")
def main():
print(star(), slash())
main()

Why can't multiprocess.Process call getattr method?

Trying to call two methods say_hello and say_world by getattr() in multiprocessing.Process, but method say_world hasn't been executed. How can I make it possible? Thanks.
# -*- coding: utf-8 -*-
from multiprocessing import Process
import time
class Hello:
def say_hello(self):
print('Hello')
def say_world(self):
print('World')
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
while True:
if hasattr(h, say_type):
result = getattr(h, say_type)()
print(result)
time.sleep(1)
def report(self):
Process(target=self.say_process('say_hello')).start()
Process(target=self.say_process('say_world')).start() # This line hasn't been executed.
if __name__ == '__main__':
t = MultiprocessingTest()
t.report()
The parameter target expects a reference to a function as value but your code passes None to it. These are the necessary parts to change:
class Hello:
def say_hello(self):
while True:
print('Hello')
time.sleep(1)
def say_world(self):
while True:
print('World')
time.sleep(1)
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
if hasattr(h, say_type):
return getattr(h, say_type) # Return function reference instead of execute function
else:
return None

Testing for functions called from a list in python

I want to know, how can I test for a function randomly pulled from a list in a conditional statement? Here is some example code. Just ignore what the code is supposed to be printing.
import random, time
def biomeLand():
print "Biome: Land"
def biomeOcean():
print "Biome: Ocean"
def biomeDesert():
print "Biome: Desert"
def biomeForest():
print "Biome: Forest"
def biomeRiver():
print "Biome: River"
biomes = [biomeLand, biomeOcean, biomeDesert, biomeForest,
biomeRiver]
def run():
while True:
selected_biome = random.choice(biomes)()
time.sleep(0.5)
run()
Once again how can I make it so the program tests in a conditional statement when a certain function is called from the list?
maybe:
def run():
while True:
selected_biome = random.choice(biomes)
selected_biome()
if selected_biome == biomeLand:
print "biomeLand Selected"
time.sleep(0.5)
run()
You can just match them like any other variable:
def foo():
print "foo"
def bar():
print "bar"
first = foo
print (first == bar) # prints "False"
print (first == foo) # prints "True"
So in your example you can just have something like:
if selected_biome == biomeLand:
# do something

Categories