I am wondering how to run functions from a list, and calling them using the random module, but I can't seem to get it to work can anyone help? Here is an example below.
import random
def word1():
print "Hello"
def word2():
print "Hello again"
wordFunctList = [word1, word2]
def run():
printWord = random.randint(1, len(wordFunctList))-1
wordFunctList[printWord]
run()
run()
So I wanted to do this in an infinite loop, but all I get for output is
Hello
Hello again
Then the program just doesn't do anything else? Can anyone help me? Btw, I am using the app pythonista. Also I am a programming NOOB. I just recently started with python.
The whole reason I am asking this question is because I am making a text based world generator, and I want to define functions for biomes, then randomly call them from a list while the world is generating.
I'd do it this way:
import random
def word1():
print "Hello"
def word2():
print "Hello again"
wordFunctList = [word1, word2]
def run():
# Infinite loop, instead of recursion
while True:
# Choose the function randomly from the list and call it
random.choice(wordFunctList)()
run()
Read this answer. It explains why you should avoid tail recursion and use infinite loop instead.
Explanation on random.choice(wordFunctList)():
wordFunctList is a list with function objects:
>>> print wordFunctList
[<function word1 at 0x7fcb1f453c08>, <function word2 at 0x7fcb1f453c80>]
random.choice(wordFunctList) chooses the function and returns it:
>>> random.choice(wordFunctList)
<function word2 at 0x7f9ce040dc80>
random.choice(wordFunctList)() calls the returned function:
>>> print random.choice(wordFunctList)()
Hello again # Outputs during the function call
None # Returned value
With extra parentheses (random.choice(wordFunctList)()()), you were calling the returned value of the function, that is None, but None is not callable and that's why you were getting the error.
Related
I decided I would create a simple text-based game as a learning project for Python as this is my first time using it. I have this function slow_print that simulates human typing which works in it's current form for strings, however is it possible to pass through a function instead. As I would like to break up the game text into sections for tidiness.
def slow_print(t):
for letter in t:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(random.random()*10.0/55)
print ('')
def intro():
print("Welcome, this is a text-based adventure game.")
print("This isn't designed for the light hearted so proceed at your own peril.")
...
...
Is this possible in Python? After playing around with the params and passing it through I got the error of "Python object is not iterableable". From my understanding strings would be iterateable. Would there be another easier way to accomplish this?
slow_print(intro())
ERROR:
Traceback (most recent call last):
File "C:\Users\CDN Admin\Python\game.py", line 20, in <module>
slow_print(intro())
File "C:\Users\CDN Admin\Python\game.py", line 9, in slow_print
for letter in t:
TypeError: 'NoneType' object is not iterable
It seems like you should rename the variable str inside the function slow_print.
str is a reserved keyword in python and it should be the cause of your error.
I have tried this solution without issues:
import sys
import time
import random
def slow_print(t):
for letter in t:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(random.random() * 10.0 / 55)
print('')
if __name__ == '__main__':
slow_print("Welcome, this is a text-based adventure game.")
slow_print takes text and slowly prints it. For it to work, you have to give it text.
intro does not return text. It prints text directly, then automatically returns None, the default return value for functions that don't explicitly return something else. slow_print then receives None and tries to slowly print it, but None is not text.
You need to restructure your code so the text that needs to be slowly printed is passed to slow_print instead of print. That might involve giving intro a parameter to select how to print things:
def intro(printer=print):
printer("Welcome, this is a text-based adventure game.")
printer("This isn't designed for the light hearted so proceed at your own peril.")
...
...
intro(slow_print)
In this modified code, intro has a printer parameter that it will use to print things. This parameter defaults to the built-in print function, but if you pass slow_print instead, intro will use slow_print to print its messages.
slow_print(intro()) prints what intro() returns, and this function does not return anything. You can rewrite this function.
def intro():
rerurn '''Welcome, this is a text-based adventure game.
This isn't designed for the light hearted so proceed at your own peril.'''
Then your slow_print will print intro message.
P. S. If you use intro() elsewhere, you should replace intro()to print(intro()).
So, Im coding a game, (just a simple text-based game, no fancy graphics or anything), but since im not good at coding professionally, I have everything done using functions, so that everything can call one another. this means that all functions and threads are always essentially 'loaded', I don't know the proper term.
essentially I want
def function():
print("Hello")
function()
to function as
def function():
print("Hello")
while True:
function()
but in my case, I can't do this, because I have many different functions being called from within each other in seemingly random patterns based on user input, and im worried at some point I'll hit a recursion wall, or stack overflow, or whatever it may be called.
AKA I can't use a loop because the order of the functions within the loop will vary from game to game
im pretty sure the only reason the stack overflow or whatever happens in the first scenario, is because the interpreter is yet to read any code after the function calls itself, as in if I had
def function():
print("Hello")
function()
print("goodbye")
the interpreter has yet to come back and print goodbye, therefore it gets stuck in memory
Call a function while ending the current function, and never return to read anything after
similar to I guess a "Break"
call a function and end the current function at the same time to save memory
As for me better to create some functions, and then create main function where that all will run:
def function1():
pass
def function2():
pass
def main():
print("function1")
function1()
print("function2")
function2()
if __name__ == "__main__":
main()
Is it possible to return from a function and continue executing code from just under the function. I know that may sound vague but here is an example:
def sayhi():
print("hi")
continue_function() #makes this function continue below in stead of return
#the code continues here with execution and will print hey
print("hey")
sayhi()
when executing this the code should do this:
it prints "hey"
it calls the sayhi() function
it prints "hi"
it calls a function to make it continue after the function (in theory similar behavour could be achieve by using decorators)
it prints "hey" again
it calls sayhi() again
etc
i am fully aware of the fact that similar behaviour can be achieved by just using for loops but for the project i am working on this functionality is required and not achievable by using looping.
some solutions i have thought of (but i have no clue how i could execute them) are:
somehow clearing the stack python uses to return from one function to another
changing return values
changing python itself (just to make clear: it would solve the problem but it is something i do not want to do beacuse the project must be usable on non-altered versions of python
using some c extension to change python's behaviour from within python itself
Repetition without loops can be done with recursion:
def sayhi():
print("hey")
print("hi")
sayhi()
sayhi()
I assume you have some terminating condition to insert. If not, this code will give a RecursionError.
I am trying to quit a python program by calling sys.exit() but it does not seem to be working.
The program structure is something like:
def func2():
*does some scraping operations using scrapy*
def func1():
Request(urls, callbakc=func2)
So, here, func1 is requesting a list of URLs and the callback method, func2 is being called. I want to quit the execution of the program if something goes wrong in func2
On checking the type of the object in func1 I found its and http.Request object.
Also, since I am using scrapy, whenever I call sys.exit() in func2, the next url in the list is called and the program execution continues.
I have also tried to use a global variable to stop the execution but to no avail.
Where am I going wrong?
According to the How can I instruct a spider to stop itself?, you need to raise CloseSpider exception:
raise CloseSpider('Done web-scraping for now')
Also see:
Running Scrapy tasks in Python
sys.exit() would not work here since Scrapy is based on twisted.
Even if we don't know how to completely stop, Python's mutable-object default binding "gotcha" can help us skip all callbacks from a certain point on.
Here is what you can do:
First, create a function generating wrapping other callback functions with condition. It's second argument cont is going to be bound to a mutable object (list) so we can affect all callbacks after creating them.
def callback_gen(f, cont=[True]):
def c(response):
if cont[0]:
f(response, cont=cont)
else:
print "skipping" # possibly replace with pass
return c
Now make some testing functions:
def func2(response, cont=None):
print response
print cont
# this should prevent any following callback from running
cont[0]=False
def func3(response, cont=None):
print response
print cont
And now create two callbacks the first one is func2 which prevents the following ones from running.
f2 = callback_gen(func2)
f3 = callback_gen(func3)
f2("func2")
f3("func3")
I like it :)
Hey so I am working on a program that requires a day/night cycle. Here is the function that I made to get it to start working:
def epoch():
for i in range(0,varb.run_number):
print("it is now day")
epoch_state = 1
yield epoch_state
time.sleep(varb.day_night_length)
print("it is now night")
epoch_state = 0
yield epoch_state
time.sleep(varb.day_night_length)
I can find nothing wrong with it, but when I call it I get this:
<generator object epoch at 0x01036670>
Any ideas on how to fix this?
P.S. The idea here is to run the cycle while printing out the state and returning the state
P.P.S. anything with varb. is a global with an unimportant numerical value
There is no error here. The function is working correctly.
You created a generator function by using yield expressions. You now need to iterate over your generator. Until you do, the generator is paused.
You could use list() for that:
result = list(epoch())
or a for loop:
for result in epoch():
print(result)