How to run a function in a single line if statement - python

I have this if statement i am trying to convert into a single line to be used in a terminal shell, but cannot seem to get it to work.
Essentially the code sort of looks like this:
import module
if condition:
module.runCustomMethod()
else:
pass
so i tried to write this like so:
import module;module.runCustomeMethod() if condition == True else pass
but no matter how i arrange it, it always gives me a syntax error. how would i go about running a method in this way?

What you're trying to do is pretty ugly, and there are better ways to do it, but…
import module;module.runCustomeMethod() if condition == True else pass
The problem here is that pass is a statement, and Python expressions can never contain statements.
Since you're not using the value of the expression, you can replace that pass with any expression that's harmless to evaluate:
import module;module.runCustomeMethod() if condition == True else None
Now there's no SyntaxError in your code. Although it's still not going to work, because that condition isn't defined anywhere, so it's just going to raise a NameError instead. But if that isn't a problem in your real code, this will work.
As a side note, you almost always just want if condition, not if condition == True. Only use that if you specifically only want to accept True and reject other truthy values like 1.
If you're doing this in a sh script, the cleanest solution is probably this:
python <<EOF
import module
if condition:
module.runCustomeMethod()
EOF

Related

"if" statements not working - outputting certain code always user-input

No matter what it always outputs Spammer().
option = int(input("Enter the what you want to do: "))
<insert code not relevant>
if option == 1 or 'spam'.upper():
Spammer()
elif option == 1:
pcInfo()
Python 3.9.7
I've looked through several posts and nothing has worked.
edit: The typo was made while typing the code into StackOverflow. To fix the if statement I wrote it again but without ctrl-c and ctrl-v and it somehow worked.
'spam'.upper()
will always return
SPAM
which is a non-empty string and therefore is regarded as a truthy statement by Python.
Since an if statement checks for truthy expressions, the if block will always be triggered.
If you need more help, please specify what you actually intend to with that statement.
Also: The else if block contains the same condition as the if block which I suppose is a typo? Otherwise if would always catch that case first and then skip over else if in all cases. So you should definitely use another value of the else if statement.
As 'spam'.upper() will return 'SPAM',
which will always give True.
also, the pcInfo() will never execute,
as it has the same condition (option == 1) as the one above.

Is there a way to get the function parameters in the callee as the caller put it?

I want to achieve that calling foo(2*3) prints 2*3.
The reason is that I try to create a test framework for querying data files and I want to print the query statement with the assertion result.
I tried to get it work via the inspect module but I could not make it work.
In general, the answer is "no", since the value received by the function is the result of the expression 2*3, not the expression itself. However, in Python almost anything is possible if you really want it ;-)
For simple cases you could achieve this using the inspect module like this:
#!/usr/bin/env python3
import inspect
def foo(x):
context = inspect.stack()[1].code_context[0]
print(context)
def main():
foo(2 * 3)
if __name__ == '__main__':
main()
This will print:
foo(2 * 3)
It would be trivial to get the part 2 * 3 from this string using a regular expression. However, if the function call is not on a single line, or if the line contains multiple statements, this simple trick will not work properly. It might be possible with more advanced coding, but I guess your use case is to simply print the expression in a test report or something like that? If so, this solution might be just good enough.
Because the expression is evaluated before it is passed to the function, it is not possible to print out the un-evaluated expression.
However, there is a possible workaround. You can instead pass the expression as a string and evaluate it inside the function using eval(). As a simple example:
def foo(expr):
print(expr)
return(eval(expr))
Please note however that using eval is considered bad practice.
A better solution is to simply pass a string as well as the expression, such as foo(2*3, "2*3").

Analyze 'return' statement inside function

Sometimes inside one function we need to use the return statement several times.
When developer changes a function with multiple returns inside, it's easy to oversee some parts of code where yet another return was "hidden".
If unit tests do not cover all possible paths, disaster is guaranteed - it's only a question of time.
def my_function():
'''Multiple "return" inside'''
if condition 1:
return 1, 2, 3
if condition 2:
return 2, 3, 4
return 5 # this is wrong: only 1 value returned, while 3-tuple expected
Let's assume here: last return is wrong, because other callers expect tuple of 3 items.
I wonder if you know an easy way how to catch such parts of code automatically? I thought I could use AST, but I could not find any useful example of this.
This question is about automatic code analysis and listing such cases found - could be with running a separate script.
Of course I could write a try-to-guess parser (with e.g. regex) and then 'manually' check all unclear cases, but maybe there is a simpler way...
Depending on what version of Python you're using and what you really want to achieve, there are several ways to refactor the code.
One way, as has been already suggested, is to use Type Hints in Python 3.
Another way is refactor your code such that instead of using multiple return statements, you call other more atomic methods that handle those conditions and return the appropriate values. You use exception handling in those atomic methods to make sure the output is as desired, or raise an exception if final return type is unexpected.
def my_function():
'''Multiple "return" inside'''
if condition 1:
output = func_handle_condition_one()
if condition 2:
output = func_handle_condition_two()
output = some_other_value
if type(output) is not tuple:
raise TypeError("Invalid type for output")
return output
Additionally, ensure that you're using the right constructs for your conditions (such as whether you want to use multiple if or the if-elif-else construct). You could even re-factor your calling code to call the right function instead of calling one that has so many conditional statements.
Why not set a variable that gets returned at the end and check for its length
def my_function():
'''Multiple "return" inside'''
return_value=(0,0,0)
if condition 1:
return_value=(1, 2, 3)
elif condition 2:
return_value=(2, 3, 4)
else:
return_value=5 # this is wrong: only 1 value returned, while 3-tuple expected
try:
if len(return_value)==3:
return return_value
else:
print("Error: must return tuple of length 3")
except:
print("Error: must return tuple")
My proposal for the final type check of the result would be:
assert isinstance(return_value, tuple) and len(return_value) == 3
Advantage: as assert is easily switched off after debugging phase; still succinct statement for formulating the expectation.

Ternary using pass keyword python

I have a working conditional statement:
if True:
pass
else:
continue
that I would like to turn it into a ternary expression:
pass if True else continue
However, Python does not allow this. Can anyone help?
Thanks!
pass and continue are a statements, and cannot be used within ternary operator, since the operator expects expressions, not statements. Statements don't evaluate to values in Python.
Nevertheless, you can still shorten the condition you brought like this:
if False: continue
Point 1: Are your sure your condition is right? Because if True will always be True and code will never go to else block.
Point 2: pass and continue are not expressions or values, but a action instead You can not use these is one line. Instead if you use, 3 if x else 4 <-- it will work
Ternary expression are used to compute values; neither pass nor continue are values.

How to properly interpret a single line of python code?

I need to execute a line of python code that is entered by the user.
If it is a statement I want to execute it, but if it is an expression, I want the result to be returned and do some fancy stuff with it.
The problem is that python has two different functions for that, namely exec and eval.
Currently I just try to evaluate the string that the user entered.
If that raises a SyntaxError, this may indicate that the string is an statement instead, so I try to execute it.
try:
result = eval(command, scope)
except SyntaxError:
# Probably command is a statement, not an expression
try:
exec(command, scope)
except Exception as e:
return command + ' : ' + str(e)
except Exception as e:
return command + ' : ' + str(e)
else:
pass # Some fancy stuff
This feels rather hacky. Is there a neater, more pythonic way to do this?
While I think your existing code is probably reasonably Pythonic (under the doctrine that it's "easier to ask forgiveness than permission"), I suspect the best alternative approach is to use the ast module to inspect the code in your string:
tree = ast.parse(some_input_string)
if len(tree.body) == 1 and isinstance(tree.body[0], ast.Expr):
result = eval(some_input_string, scope)
else:
exec(some_input_string, scope)
result = None
Note that some common statements are really "expression statements". So, an input string like 'do_stuff("args")' will use the eval branch of the code above, rather than the exec branch. I don't think this will have any adverse consequences, but you never know.
It is also possible to compile the tree that has been parsed and then pass the result into the eval or exec calls later. I found it rather fiddly to get right though (you need to wrap the ast.Expr's value attribute in an ast.Expression in the top branch) and so I went with the simpler (to read and understand) alternative of just passing in the string and letting Python parse it again.
You can refactor the try-except a bit. There's no real context in your example, but assuming you want to be able to execute a=1 and then evaluate a afterwards and get 1, then you could do something like...
from code import InteractiveConsole
interpreter = InteractiveConsole()
def run(code):
try: return eval(code.strip(), interpreter.locals)
except: pass
try: interpreter.runcode(code)
except Exception as error: return error
This should work for more than one line of code too.
Without knowing a bit more about your objective it's difficult to say how to do it best, but what you have is fine in principle, it just needs tidying up. This similar answer includes a minimal version of the same try-except logic again, with a focus on mimicking the interpreter more faithfully.
you missed one, actually there are three functions related to executing code, and the one you missed is compile().
compile() takes three required arguments, the code to be compiled, the name of the module being compiled, which will appear in tracebacks originating from that code, and a "mode". The mode argument should be one of "exec", for compiling whole modules, "eval" for compiling simple expressions, and "single", which should be a single line of interactive input!
In all three cases, you pass the returned code object to eval, with the desired context:
>>> c = compile("if 1 < 2:\n print(3)", "<string>", "single")
>>> eval(c)
3
>>>

Categories