Create a help line for each function in module - python

I've made a couple of python files with functions like:
def func(a,b,c):
return a+b+c
The functions are often more complicated, but the general idea of them all are the same, receive a couple of predetermined parameters, and return the desired value.
Now, I want to make a separate GUI file for easy use of all the functions. The GUI imports all the different python scripts and via text entry fields I want to be able to give the desired parameters for each function. The problem is that the functions vary greatly in what kinds of parameters they expect, so I wanted to make each function able to return a help string to the GUI with a short explanation of what the function needs to run. In the GUI file I'm using getattr to save the desired function:
methodtocall = getattr(Nuclear, func)
I can then call the function with parameters gained for textfields, like:
methodtocall(textfield1.get(),textfield2.get())
The problem, as I said above, is that for the GUI to be useful, I need a help sentence to be printed to the GUI the moment I select a function. I tried to make an adjustment in the functions themselves, example:
def func(a,b,c):
help = "give a as string, b as list, c as integer"
if no_parameters:
return help
else:
return desired_value
The problem is that the methodtocall function gives a TypeError, since I try to launch it without any parameters: methodtocall()
The solution would be something that called the desired function the moment I select it in the GUI, and retrieves the help line for the desired function and displays it in a help textfield in the GUI, does anyone have any ideas?

Place the help text in the first unassigned string in the function definition, like this:
def func(a,b,c):
"""
This function adds three numbers.
"""
return a+b+c
Now, this text is available through the variable __doc__:
print(func.__doc__)
#
# This function adds three numbers.
#
You do not even need to call the function.

Related

Using variables from a function in another python program

So I'm trying to write a python program to integrate into a greater in-house developed python application. This program I'm writing needs to generate an xml document and populate the fields with data stored in variables from another function in a different module.
After realizing I can't have both programs import each other (main program needs to call xmlgen.py to generate the xml doc, while xmlgen.py needs to utilize variables in the main program to generate that doc), I'm a little bit at a loss as to what to do here.
In the example shown below, xmlgen.py needs to use variables from the function sendFax in Faxer.py. Faxer.py needs to call xmlgen.py to generate the document.
snippet from xmlgen.py:
from lxml import etree
from Faxer import coverPage, ourOrg, ourPhonenum, ourFaxnum, emailAddr, sendReceipt, webAddr, comments
from Faxer import sendFax
def generateXml():
#xml file structure
root = etree.Element('schedule_fax')
...
~ A bunch of irrelevant xml stuff
...
grandchild_recipient_name = etree.Element('name')
grandchild_recipient_name.text = cliName
child_recipient.append(grandchild_recipient_name)
Now the piece of the main program I need to utilize the "cliName" variable from...
def sendFax(destOrg, destFax, cliName, casenum, attachments, errEAddr, comment, destName):
creds=requests.auth.HTTPBasicAuth(user,password)
allData=''
allData+='<schedule_fax>\n'
allData+='<cover_page>\n'
allData+='<url>'+prepXMLString(coverPage)+'</url>\n'
allData+='<enabled>true</enabled>\n'
allData+='<subject>'+prepXMLString(cliName)+' - case # '+str(casenum)+'</subject>\n'
Now when I try to import sendFax function from Faxer.py, I'm unable to call any of the variables from the function like,
grandchild_recipient_name.text = sendFax.cliName
does not work. What am i doing wrong here?? I'm not a python guru and am in fact quite new to all of this, so I'm hoping it's something simple. Should I just dump everything into a new function in the main program?
As pointed out above, you are trying to reference cliName as if it is an attribute of the function. This would be closer to being correct if sendFax was a class, but that's another subject. The snippet you have provided is simply a function definition. It doesn't guarantee that this function is ever actually used or give you any idea what cliName actually is, cliName is just the name used by the function internallt to describe the 3rd value supplied as input.
What you need to do is find where sendFax is actually used, rather than where it is defined. Then look at what the variables are called which are passed into it. There are two ways to pass variables into a function: by position and by name. If the variables are being passed by pposition you will find something like:
sendFax(some_name,some_other_name,yet_another_name,...
The third one of these will be the variable which becomes cliName inside the function.
If being passed by name you will see something like
sendFax(cliName=yet_another_name,...
Where once again yet_another_name is the thing which becomes cliName.
Depending on how the programme is structured you may be able to refer to yet_another_name from your program and get the value you need.
from Faxer import yet_another_name
But this will only work if Faxer runs and finishes with the one and only value of yet_another_name assigned. If Faxer iterates through lots of values of yet_another_name, or simply doesn't run sensibly when called as an import you'll need a more sophisticated approach.

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.

Why is there a syntax error in my Python function?

number=list(map(lambda x:int(x), input().split()))
first=".|."
second='-'
median=((number[0]-1)//2)+1
def Door(number[0],number[1]): # <<-- this one is resulting in a syntax error.
So I still fail to understand what is wrong with this code.
Can you please help me?
Thank you.
In this line:
def Door(...):
you are defining a function. You define a function with variables as parameters. When you call the function you pass it values.
What I think you are planning to do is first define Door() and then later call it with the values number[0] and number[1].
So begin your definition of the function like this:
def Door(a,b):
and when you want to call it, then you pass it the values number[0] and number[1], like this:
mydoor = Door(number[0],number[1])
Then, inside Door(), when your code refers to a and b, it is using the values of
number[0] and number[1]. This disconnect is so that the function can be called from different places with different parameters.
This applies even if you are defining the function just to modularize your code, and you only ever plan to call it from one place.

Alternative to exec

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

Parentheses in Python's functions and decorators(wrappers)

Thanks for reading my question. As I'm still new to Python, I would like to ask about the () in Python.
def addOne(myFunc):
def addOneInside():
return myFunc() + 1
return addOneInside # <-----here is the question
#addOne
def oldFunc():
return 3
print oldFunc()
Please note that on line four, although the programme returns a function, it does not need parentheses(). Why does it NOT turn out with an error for syntax error? Thank you very much for your answers in advance!
The parentheses are used to run a function, but without them the name still refers to the function just like a variable.
return myFunc() + 1
This will evaluate the myFunc function, add 1 to its value and then return that value. The brackets are needed in order to get the function to run and return a numeric value.
return addOneInside
This is not actually running addOneInside, it is merely returning the function as a variable. You could assign this to another name and store it for later use. You could theoretically do this:
plusOne = addOneInside
plusOne()
And it will actually call the addOneInside function.
The particular instance in your initial question is known as a Decorator, and it's a way for you to perform code on the parameters being passed to your function. Your example is not very practical, but I can modify it to show a simple use case.
Let's say that you want to only have positive numbers passed to your function. If myFunc is passed a negative number, you want it to be changed to 0. You can manage this with a decorator like this.
def addOne(myFunc):
def addOneInside(num):
if num < 0:
num = 0
return myFunc(num)
return addOneInside # <-----here is the question
#addOne
def oldFunc(number):
return number
To explain, the #addOne is the decorator syntax, and it's attaching the addOneInside function to be called on the argument/s of oldFunc whenever you call it. So now here's some sample output:
oldFunc(-12)
>>> 0
oldFunc(12)
>>> 12
So now you could add logic to oldFunc that operates independently of the parameter parsing logic. You could also relatively easily change what parameters are permitted. Maybe there's also a maximum cap to hit, or you want it to log or note that the value shouldn't be negative. You can also apply this decorator to multiple functions and it will perform the same on all of them.
This blogpost explained a lot for me, so if this information is too brief to be clear, try reading the long detailed explanation there.
Your indentation in function addOne() was incorrect (I have fixed it), but I don't think that this was your problem.
If you are using Python3, then print is a function and must be called like this:
print(oldFunc())

Categories