I'm practicing writing functions that do only one thing. I'm getting stuck with the below functions. play_games is what the user calls to run the whole program. Ideally, it should only have the call to the play_many_games method which is in one of the program's classes.
But if I don't also add the line that calls the prepare_reports function, then the reports will never get taken care of. How do I "do reports and games" if I insist on only having functions that do one thing?
Is the bottom line that we need a main function that can do more than one thing (e.g. a main function that can do both games and reports calls)?
def play_games(number_of_games):
games_engine = prepare_reports(number_of_games)
games_engine.play_many_games(number_of_games)
def prepare_reports(number_of_games):
report_requests = []
if number_of_games <= 100:
report_on_game = GameReport()
report_requests.append(report_on_game)
report_on_many_games = ManyGamesReport()
report_requests.append(report_on_many_games)
return GamesEngine(*report_requests)
Having a main function that does nothing but drive the process and call other functions, is a function that only does one thing. I suggest you create one.
You could try this, since there's not much of a point in declaring games_engine:
def play_games(number_of_games):
prepare_reports(number_of_games).play_many_games(number_of_games)
def prepare_reports(number_of_games):
report_requests = []
if number_of_games <= 100:
report_on_game = GameReport()
report_requests.append(report_on_game)
report_on_many_games = ManyGamesReport()
report_requests.append(report_on_many_games)
return GamesEngine(*report_requests)
However, what you showed us is technically a function doing only one thing. You see, by declaring games_engine = prepare_reports(number_of_games), you are just making your code easier to read.
Related
so basically I have encountered a problem where I have made my loop, but since one of the variables is defined before the actual assignment, the code stops working. the code.
Another thing is that I'm working in Spyder, and I don't know why, but if I try to code so that the program collect variables initially (which is essential for this purpose), the program encounters an internal issue. Any ideas on how to ask for user input in Spyder?
Thanks to everyone in advance
Basically, what I want this to do is to differentiate functions, and the with these derivatives create a maclaurin series. When the actual error ((r-j)/r) is smaller than the stopping variable s, I want the program to stop and display the result, but I don't know what is wrong.
The second thing I want to achieve is to get to know how to gain input from the user in the program.
So, here is, in text form, your code (sorry, plagiarism argument is not valid around here)
q = sympy.Function('q')
q = sympy.diff(f)
def main():
a = sympy.Function('a')
a = sympy.diff(q)
j = sympy.function
j = 1+(1/sympy.factorial(count))*q
r = sympy.Function('r')
r = j+(1/sympy.factorial(count+1))*a
if ((r-j)/r)>s:
count = count + 1
q = sympy.diff(a)
j = r+(1/sympy.factorial(count))*q
r = j+(1/sympy.factorial(count+1))*a
main()
else:
print(f"Answer{r}")
In the middle of an obviously very confused code, and even more confused situation with that "plagiarism" stuff (don't worry, if you have a working code at the end of your effort, there is no way it will look similar enough to your original to be detected as plagiarism because I've posted it here:D) there is actually a good question, and I remember that I while ago I had to scratch my head to understand what was happening in a similar situation.
The problem you have here, is that you can't compute sympy.diff(q) in main function, before assigning something to q in that same function later.
Because of the line q = sympy.diff(a) that you have later, q has to be a local variable (unless you say otherwise, see later). That's default behavior in python: a variable that you assign in a function is a local variable.
But because you are reading this variable before, in the previous line (the one that triggers the error) a = sympy.diff(q), then python has a problem: the local variable a doesn't exist yet.
Without the future q = sympy.diff(a), q would have been "read-only" inside main, and python would have done what you probably expect: read the global variable q.
So, your real problem is not really that line. Your real problem is the line q = sympy.diff(a).
Because even without the current error, that line would not do what you expect it to do. You probably expect it to alter q so that in the subsequent recursive call of main, q has this new value for now on. Not to create a local value q, and have the next call of main start over with the global value of q.
You have several options here.
One would be to declare q has global. Just add line global q at the beginning of your main, and q is now the global variable.
A cleaner way would be to pass q as an argument to main.
Note that you'll have probably the same problem with count. You should also either declare it as global, or, neater way, pass it to main.
Note also that this would solve only syntax errors (well, not even all. j=sympy.function is meaningless for example). But there are many other errors here. The least serious being your strange habit to create a Function and immediately delete it by overwriting it by another function or expression.
Say I have got some function fun, the actual code body of which is out of my control. I can create a new function which does some preprocessing before calling fun, i.e.
def process(x):
x += 1
return fun(x)
If I now want process to take the place of fun for all future calls to fun, I need to do something like
# Does not work
fun = process
This does not work however, as this creates a cyclic reference problem as now fun is called from within the body of fun. One solution I have found is to reference a copy of fun inside of process, like so:
# Works
import copy
fun_cp = copy.copy(fun)
def process(x):
x += 1
return fun_cp(x)
fun = process
but this solution bothers me as I don't really know how Python constructs a copy of a function. I guess my problem is identical to that of extending a class method using inheritance and the super function, but here I have no class.
How can I do this properly? I would think that this is a common enough task that some more or less idiomatic solution should exist, but I have had no luck finding it.
Python is not constructing a copy of your function. copy.copy(fun) just returns fun; the difference is that you saved that to the fun_cp variable, a different variable from the one you saved process to, so it's still in fun_cp when process tries to look for it.
I'd do something similar to what you did, saving the original function to a different variable, just without the "copy":
original_fun = fun
def fun(x):
x += 1
return original_fun(x)
If you want to apply the same wrapping to multiple functions, defining a decorator and doing fun = decorate(fun) is more reusable, but for a one-off, it's more work than necessary and an extra level of indentation.
This looks like a use case for python's closures. Have a function return your function.
def getprocess(f):
def process(x):
x += 1
return f(x) # f is referenced from the enclosing scope.
return process
myprocess = getprocess(fun)
myprocess = getprocess(myprocess)
Credit to coldspeed for the idea of using a closure. A fully working and polished solution is
import functools
def getprocess(f):
#functools.wraps(f)
def process(x):
x += 1
return f(x)
return process
fun = getprocess(fun)
Note that this is 100% equivalent to applying a decorator (getprocess) to fun. I couldn't come up with this solution as the dedicated decorator syntax #getprocess can only be used at the definition place of the function (here fun). To apply it on an existing function though, just do fun = getprocess(fun).
Hello there developers,
i am writing code that takes the user input and initializes a class depending on the input like in the example code below:
class X:
def __init__(self):
return
def run(self):
print("i am X")
def func1(cls):
exec("global " + cls.lower())
exec(cls.lower() + " = " + cls + "()")
def func2(mode_to_set):
exec(mode_to_set.lower() + ".run()")
but as I run the code like this:
func1('X')
func2('X')
i keep getting this error:
Traceback (most recent call last):
File "/Users/noahchalifour/Desktop/test.py", line 16, in <module>
func2('X')
File "/Users/noahchalifour/Desktop/test.py", line 13, in func2
exec(mode_to_set.lower() + ".run()")
File "<string>", line 1, in <module>
NameError: name 'x' is not defined
Can anyone help me?
A much better way to instantiate a class based on user input would be to use a "factory pattern":
http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Factory.html
Basically you create a class whose whole purpose is to create other classes based on a value. Some people might find that overkill, so you could also use a function that creates classes based on input.
Whatever you do though, the way you have it now, running raw, user-input strings using exec, is a bad idea. The best case scenario is that it introduces new bugs that are near-impossible to trace since they aren't actually recorded anywhere. Worst case scenario, a user somehow finds a way to send a string to the function, you've pretty much destroyed whatever security you've hoped for.
Basically "exec" should generally be a last resort. There are usually more elegant and secure ways to solve the problem.
It seems like you'd be better off having func2 instantiate and run the method:
def func2(mode_to_set):
globals()[mode_to_set]().run()
In this way, you don't have a whole bunch of undesireable cruft floating about in your global namespace and you don't end up doing an untrusted exec. Also, execing a global statement inside a function doesn't work (as you've seen)... exec is a way to execute a string as if it were code. It isn't a way to drop dynamically created statements into the current function.
Dictionaries, dictionaries, dictionaries. Your program should maintain control over what code gets executed, rather than letting the user construct new code dynamically.
classes = {'X': X}
instances = {}
def func1(cls):
var = cls.lower()
instances[var] = classes[cls]()
def func2(mode_to_set):
instances[mode_to_set.lower()].run()
func1('X')
func2('X')
The only difference is that you don't have a global variable named x; you have a global dictionary with a key x that refers to your instance.
I'm currently trying to code a Python (3.4.4) GUI with tkinter which should allow to fit an arbitrary function to some datapoints. To start easy, I'd like to create some input-function and evaluate it. Later, I would like to plot and fit it using curve_fit from scipy.
In order to do so, I would like to create a dynamic (fitting) function from a user-input-string. I found and read about exec, but people say that (1) it is not safe to use and (2) there is always a better alternative (e.g. here and in many other places). So, I was wondering what would be the alternative in this case?
Here is some example code with two nested functions which works but it's not dynamic:
def buttonfit_press():
def f(x):
return x+1
return f
print(buttonfit_press()(4))
And here is some code that gives rise to NameError: name 'f' is not defined before I can even start to use xval:
def buttonfit_press2(xval):
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
return f
print(buttonfit_press2(4))
An alternative approach with types.FunctionType discussed here (10303248) wasn't successful either...
So, my question is: Is there a good alternative I could use for this scenario? Or if not, how can I make the code with exec run?
I hope it's understandable and not too vague. Thanks in advance for your ideas and input.
#Gábor Erdős:
Either I don't understand or I disagree. If I code the same segment in the mainloop, it recognizes f and I can execute the code segment from execstr:
actfitfunc = "f(x)=x+1"
execstr = "def {}:\n return {}\n".format(actfitfunc.split("=")[0], actfitfunc.split("=")[1])
exec(execstr)
print(f(4))
>>> 5
#Łukasz Rogalski:
Printing execstr seems fine to me:
def f(x):
return x+1
Indentation error is unlikely due to my editor, but I double-checked - it's fine.
Introducing my_locals, calling it in exec and printing in afterwards shows:
{'f': <function f at 0x000000000348D8C8>}
However, I still get NameError: name 'f' is not defined.
#user3691475:
Your example is very similar to my first example. But this is not "dynamic" in my understanding, i.e. one can not change the output of the function while the code is running.
#Dunes:
I think this is going in the right direction, thanks. However, I don't understand yet how I can evaluate and use this function in the next step? What I mean is: in order to be able to fit it, I have to extract fitting variables (i.e. a in f(x)=a*x+b) or evaluate the function at various x-values (i.e. print(f(3.14))).
The problem with exec/eval, is that they can execute arbitrary code. So to use exec or eval you need to either carefully parse the code fragment to ensure it doesn't contain malicious code (an incredibly hard task), or be sure that the source of the code can be trusted. If you're making a small program for personal use then that's fine. A big program that's responsible for sensitive data or money, definitely not. It would seem your use case counts as having a trusted source.
If all you want is to create an arbitrary function at runtime, then just use a combination of the lambda expression and eval. eg.
func_str = "lambda x: x + 1" # equates to f(x)=x+1
func = eval(func_str)
assert func(4) == 5
The reason why your attempt isn't working is that locals(), in the context of a function, creates a copy of the local namespace. Mutations to the resulting dictionary do not effect the current local namespace. You would need to do something like:
def g():
src = """
def f(x):
return x + 1
"""
exec_namespace = {} # exec will place the function f in this dictionary
exec(src, exec_namespace)
return exec_namespace['f'] # retrieve f
I'm not sure what exactly are you trying to do, i.e. what functions are allowed, what operations are permitted, etc.
Here is an example of a function generator with one dynamic parameter:
>>> def generator(n):
def f(x):
return x+n
return f
>>> plus_one=generator(1)
>>> print(plus_one(4))
5
I'm learning python from a textbook. This code is for the game Tic-Tac-Toe.
The full source code for the problem:
http://pastebin.com/Tf4KQpnk
The following function confuses me:
def human_move(board, human):
""" Get human move."""
legal = legal_moves(board)
move = None
while move not in legal:
move = ask_number("Where will you move? (0 - 8): ", 0, NUM_SQUARES)
if move not in legal: print "\nThat square is already taken. Choose another.\n"
print "Fine..."
return move
I do not know why the function receives 'human' parameter. It appears to do nothing with it.
def human_move(board, human):
How would I know to send 'human' to this function if I were to write this game from scratch? Because I can't see why it is sent to this function if it isn't used or returned.
The answer: it depends. In your example it seems useless to me, but I haven't checked it in depth.
If you create a function to be used only from your code, it is in fact useless.
def calculate_money(bank_name, my_dog_name):
return Bank(bank_name).money
money = calculate_money('Deutsche bank', 'Ralph')
But if you are working with some kind of API/Contract, the callbacks you specify might accept arguments that are not needed for a certain implementation, but for some others, are necessary.
For instance, imagine that the following function is used in some kind of framework, and you want the framework to show a pop up when the operation is finished. It could look something like this:
def my_cool_callback(names, accounts, context):
# do something blablab
context.show_message('operation finished')
But what if you don't really need the context object in your callback? you have to speficy it anyway for the signature to match... You can't call it pointless because that parameter is used sometimes.
EDIT
Another situation in which it could be useful, would be to loop through a list of functions that have almost the same signature. In that case could be ok also to have extra arguments as "garbage placeholders". Let's say all your functions need 3 arguments in general, but one needs only 2.