How do I do this? Can I do this?
def aFunction(argument):
def testSomething():
if thisValue == 'whatItShouldBe':
return True
else:
return False
if argument == 'theRightValue': # this is actually a switch using elif's in my code
testSomething()
else:
return False
def aModuleEntryPoint():
if aFunction(theRightValue) == True:
doMoreStuff()
else:
complain()
aModuleEntryPoint()
aModuleEntryPoint() needs to first make sure that a condition is true before it starts doing things. Because of encapsulation, aModuleEntryPoint doesn't know how to check the condition, but aFunction() has a sub-function called testSomething() that does know how to check the condition. aModuleEntryPoint() calls aFunction(theRightValue).
Because theRightValue was passed to aFunction() as an argument, aFunction() calls testSomething(). testSomething() performs the logic test, and either returns True or False.
I need for aModuleEntryPoint() to know what testSomething() decided. I do not want aModuleEntryPoint() to know anything about how testSomething() came to its conclusion.
It would actually be an accomplishment to post my actual source while removing other functions and what-not, so I had to setup the general gist like this.
The only thing I see wrong right now is you need a return before testSomething() on line 9.
Perhaps a sub-function is not the right encapsulation tool for you here. You want to expose internal functionality to an external entity. Python classes provide a better mechanism for expressing this than sub-function. Having a class, you can expose whatever parts of internal functionality you want in a very controlled manner.
My first thought upon looking at your code is that it's a little too complicated. Why have aFunction at all? You could just write
def aModuleEntryPoint():
argument = ...
if argument in (theRightValue, theOtherRightValue, theOtherOtherRightValue)\
and testSomething():
doMoreStuff()
else:
complain()
This if clause will first check whether argument is one of the possible right values, and if it is, then it will proceed to call testSomething() and check the return value of that. Only if that return value is true will it call doMoreStuff(). If either of the tests fails (that's why I used and), it will complain().
Related
Let's say,
def sample():
if a==1:
print(a)
else:
continue
for i in language:
a=i
sample()
I want to use this function in a loop, but the continue command gives me an error because there is no loop. What can I do?
Return a boolean from the function and based on the return value make continue or not because continue must be within a loop
continue keyword in python is only available in for or while loops. Also block defined variables like a are not available on the global scope.
I don't know what you want to achieve but assuming your code, you want to extract a condition into a function, something like this:
def condition(a):
return a == 1
def sample(a):
print(a)
for i in language:
a=i
if condition(a):
sample(a)
else:
continue
There are several best-practice patterns of exactly how to do this, depending on your needs.
0. Factor your code better
Before doing any of the below, stop and ask yourself if you can just do this instead:
def sample(a):
print(a)
for i in language:
if i != 1:
continue
sample(i)
This is so much better:
it's clearer to the reader (everything you need to understand the loop's control flow is entirely local to the loop - it's right there in the loop, we don't have to look anywhere else farther away like a function definition to know when or why or how the loop will do the next thing),
it's cleaner (less boilerplate code than any of the solutions below),
it's more efficient, technically (not that this should matter until you measure a performance problem, but this might appeal to you; going into a function and coming back out of it, plus somehow telling the loop outside the function to continue - that's more work to achieve the same thing), and
it's simpler (objectively: there is less code complected together - the loop behavior is no longer tied to the body of the sample function, for example).
But, if you must:
1. Add boolean return
The simplest change that works with your example is to return a boolean:
def sample(a):
if a==1:
print(a)
else:
return True
return False
for i in language:
if sample(i):
continue
However, don't just mindlessly always use True for continue - for each function, use the one that fits with the function. In fact, in well-factored code, the boolean return value will make sense without even knowing that you are using it in some loop to continue or not.
For example, if you have a function called check_if_valid, then the boolean return value just makes sense without any loops - it tells you if the input is valid - and at the same time, either of these loops is sensible depending on context:
for thing in thing_list:
if check_if_valid(thing):
continue
... # do something to fix the invalid things
for thing in thing_list:
if not check_if_valid(thing):
continue
... # do something only with valid things
2. Reuse existing return
If your function already returns something, or you can rethink your code so that returns make sense, then you can ask yourself: is there a good way to decide to continue based on that return value?
For example, let's say inside your sample function you were actually trying to do something like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
else:
continue
Well then you can rewrite it like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
return record
for i in language:
record = sample(a)
if record.status != 1:
continue
Of course in this simple example, it's cleaner to just not have the sample function, but I am trusting that your sample function is justifiably more complex.
3. Special "continue" return
If no existing return value makes sense, or you don't want to couple the loop to the return value of your function, the next simplest pattern is to create and return a special unique "sentinel" object instance:
_continue = object()
def sample(a):
if a==1:
print(a)
else:
return _continue
for i in language:
result = sample(i):
if result = _continue:
continue
(If this is part of a module's API, which is something that you are saying if you name it like sample instead of like _sample, then I would name the sentinel value continue_ rather than _continue... But I also would not make something like this part of an API unless I absolutely had to.)
(If you're using a type checker and it complains about returning an object instance conflicting with your normal return value, you can make a Continue class and return an instance of that instead of an instance of object(). Then the type hinting for the function return value can be a type union between your normal return type and the Continue type. If you have multiple control flow constructs in your code that you want to smuggle across function call lines like this.)
4. Wrap return value (and "monads")
Sometimes, if the type union thing isn't good enough for some reason, you may want to create a wrapper object, and have it store either your original return value, or indicate control flow. I only mention this option for completeness, without examples, because I think the previous options are better most of the time in Python. But if you take the time to learn about "Option types" and "maybe monads", it's kinda like that.
(Also, notice that in all of my examples, I fixed your backdoor argument passing through a global variable to be an explicit clearly passed argument. This makes the code easier to understand, predict, and verify for correctness - you might not see that yet but keep an eye out for implicit state passing making code harder to follow and keep correct as you grow as a developer, read more code by others, and deal with bugs.)
It is because the scope of the function doesn't know we are in a loop. You have to put the continue keyword inside the loop
continue keyword cannot be used inside a function. It must be inside the loop. There is a similar question here. Maybe you can do something like the following.
language = [1,1,1,2,3]
a = 1
def sample():
if a == 1:
print(a)
return False
else:
return True
for i in language:
if sample():
continue
else:
a = i
OR something like this:
language = [1,1,1,2,3]
a = 1
def gen(base):
for item in base:
if a == 1:
yield a
else:
continue
for i in gen(language):
a = i
print(a)
I'm not sure how to phrase this question exactly, but I'll give an example that explains what I am wondering about:
I have a function that is a permission check, let's call it A. And I call this function in another function, let's call B. If the permission check in A fails, I want function B to return. So what I would do is:
def permission_check_A(user):
# check if user has permission
return result_of_check
def another_function_B(user):
used_passed_permission_check = permission_check_A(user)
if not used_passed_permission_check:
return
# do other stuff if user passed
Now I'm wondering if it is possible to cause function B to return directly if the check in A fails. Something like:
def permission_check_A(user):
# check if user has permission
if not used_passed_permission_check:
# cause the calling function B to return
return
return True
def another_function_B(user):
permission_check_A(user)
# do other stuff if user passed
I guess in the example I am giving here, it would make sense to use a decorator for this kind of functionality. But if the security check happens somewhere in the middle of function B, this would not work.
My main motivation to do this, is that I don't want to repeat the "if, return" lines over and over again in every function that calls function A.
Also I'm wondering if would even be a good idea if this was possible because it could make the code less readable (a reader would have to check function A to realize that function B could be forced to return when A is called). What are your thoughts?
You could create an exception
class PermissionError(Exception):
pass
def permission_check_A(user):
# check if user has permission
if no_good():
raise PermissionError("No permission")
def another_function_B(user):
permission_check_A(user)
# do other stuff if user passed
Raising the exception stops execution of the current function. If the next higher function doesn't have a try/except block active, it goes to the next higher function until its caught or the whole program exits.
A function could call many other functions within a single try/except. Or a top level function could catch all of the errors from a large swath of code.
In cases where certain trivial conventions apply, you can achieve something like this with a decorator:
def check(p):
def make(f):
#functools.wraps(f)
def call(first,*a,**kw):
if p(first): return f(first,*a,**kw)
return call
return make
#check(permission_check_A)
def another_function_B(user): …
This of course will not work if someone calls another_function_B(user=…) or if another_function_B adds parameters before user.
Lets say I have a function myFunc defined as
def myFunc(value):
return value if isinstance(value, int) else None
Now wherever in my project I use myFunc the enclosing funciton should return automatically if the value returned from myFunc is None and should continue if some integer value is returned
For example:
def dumbFunc():
# some code
# goes here..
result = myFunc('foo')
# some code
# goes here..
This funciton should automatically behave like..
def dumbFunc():
# some code
# goes here..
result = myFunc('foo')
if not result:
return
# some code
# goes here..
PS - I don't know whether this thing even possible or not.
This is simply not possible.
Apart from exceptions, you cannot give a called function the ability to impact the control flow of the calling scope. So a function call foo() can never interrupt the control flow without throwing an exception. As a consumer of the function, you (the calling function) always have the responsibility yourself to handle such cases and decide about your own control flow.
And it is a very good idea to do it like that. Just the possibility that a function call might interrupt my control flow without having a possibility to react on it first sounds like a pure nightmare. Just alone for the ability to release and cleanup resources, it is very important that the control flow is not taken from me.
Exceptions are the notable exception from this, but of course this is a deeply rooted language feature which also still gives me the ability to act upon it (by catching exceptions, and even by having finally blocks to perform clean up tasks). Exceptions are deliberately not silent but very loud, so that interruptions from the deterministic control flow are clearly visible and have a minimum impact when properly handled.
But having a silent feature that does neither give any control nor feedback would be just a terrible idea.
If myFunc is used at 100 places in my project, everywhere I need to put an if condition after it.
If your code is like that that you could just return nothing from any function that calls myFunc without having to do anything, then either you are building an unrealistic fantasy project, or you simply are not aware of the implications this can have to the calling code of the functions that would be returned that way.
ok, I'll bite.
on the one hand, this isn't really possible. if you want to check something you have to have a line in your code that checks it.
there are a few ways you could achieve something like this, but i think you may have already found the best one.
you already have this function:
def myFunc(value):
return value if isinstance(value, int) else None
I would probably have done:
def myFunc(value):
return isinstance(value, int)
but either way you could use it:
def dumb_func():
value = do_something()
if myFunc(value):
return
do_more()
return value
alternately you could use try and except
I would raise a TypeError, seeing as that seems to be what you are checking:
def myFunc(value):
if not isinstance(value, int):
raise TypeError('myFunc found that {} is not an int'.format(value))
then you can use this as such
def dumb_func():
value = do_something()
try:
myFunc(value):
Except TypeError as e:
print e # some feedback that this has happened, but no error raised
return
do_more()
return value
for bonus points you could define a custom exception (which is safer because then when you catch that specific error you know it wasn't raised by anything else in your code, also if you did that you could be lazier eg:)
Class CustomTypeError(TypeError):
pass
def dumb_func():
try:
value = do_something()
myFunc(value):
do_more()
return value
Except CustomTypeError as e:
print e # some feedback that this has happened, but no error raised
return
but none of this gets around the fact that if you want to act based on the result of a test, you have to check that result.
Python has a ternary conditional operator, and the syntax you used is right, so this will work:
def myFunc(value):
return value if isinstance(value, int) else None
def dumbFunc():
print("Works?")
result = myFunc(5)
print(result)
dumbFunc()
Result:
Works?
5
I want the function to return automatically in that case
This is not possible. To do that, you have to check the return value of myFunc() and act upon it.
PS: You could do that with a goto statement, but Python, fortunately, doesn't support this functionality.
I wonder how to correctly use python 2.7 callback functions.
I have some callback functions from Cherrypy auth examples in my code.
(These callbacks return a function that can evaluate to True or False, depending on the logged in user being in a group or not.)
I wonder if a callback is executed or not if I write a piece of code like this:
Given the definition from the library is:
def member_of(groupname):
def check():
if groupname == 'admin':
if cherrypy.request.login == 'joe':
return True
if cherrypy.request.login == 'toni':
return True
return False
return False
# .... (other groups checked in the same way)
return check # returns a callback function from my understanding?
How can I apply and execute the callback in my code?
If I put it like this:
if member_of('admin'):
do_something()
else:
do_something_else()
Will this execute the calllback and check for the admin group? Or will it find out if the value of "member_of" is a function definition and a function definition is probably always a "True" value (or maybe a False value) but both are wrong, because it needs to be executed
Can you enlighten me on this? How can I make sure a callback is executed? An how can I pass it around as it is?
In python, like in many other languages, a variable can also contain a function and you can pass them around like other variables that contain e.g. numbers or strings.
CherryPy's member_of function itself does return a function in your example.
I am explaining it in simple steps:
If you write member_of() it returns the result of the function member_of() which is the function with the name check in this case.
cb_function = member_of('admin')
At this point the variable cb_function holds the result of calling the function member_of, and in the last line member_of returns check, which was defined within the function member_of as another function!
You have to call the first result again, because you can and you have to treat it in almost the same way as a local function, that you defined in the current context, to get the final result, by doing something like:
my_result = cb_function()
And then you would continue and use the result. For example you could check its boolean value:
if my_result:
# do something
...
The 3 steps from above together can be written shorter:
cb_function = member_of('admin')
if cb_function():
# do something
...
Or even shorter:
if member_of('admin')():
# do something
...
At first it may appear a little strange in python to have the double ()(), but if you think about it for a while it makes sense.
If you execute it, it is plain simple.
member_of() will return method object check.
you have to execute to get result by doing something like if member_of('admin')():
or,
k=member_of('admin')
if k():
To do your task.
I'm wondering if anyone can think up a way to check if a function needs to return a meaningful value in Python. That is, to check whether the return value will be used for anything. I'm guessing the answer is no, and it is better to restructure my program flow. The function in question pulls its return values from a network socket. If the return value is not going to get used, I don't want to waste the resources fetching the result.
I tried already to use tracebacks to discover the calling line, but that didn't work. Here's an example of what I had in mind:
>>> def func():
... print should_return()
...
>>> func()
False
>>> ret = func()
True
The function "knows" that its return value is being assigned.
Here is my current workaround:
>>> def func(**kwargs):
... should_return = kwargs.pop('_wait', False)
... print should_return
...
>>> func()
False
>>> ret = func(_wait=True)
True
The very second line of the body of import this says it all: "explicit is better than implicit". In this case, if you provide an optional argument, the code will be more obvious (and thus easier to understand), simpler, faster and safer. Keep it as a separate argument with a name like wait.
While with difficulty you could implement it magically, it would be nasty code, prone to breaking in new versions of Python and not obvious. Avoid that route; there lieth the path unto madness.
All functions return a value when they complete.
If you're asking if they should return at all, then you are actually asking about The Halting Problem
One approach might be to return an object with a __del__ method that relies on the garbage collector removing the unused value some time in the future.
Note that it won't happen immediately; it might not even happen at all :)
You might consider returning a future, or 'promise'. That is, return another function that, when executed, performs the necessary work to actually determine the result. I seem to be thinking that you want lazy evaluation, which is "evaluate only what you need" (more or less), rather than your question, which confusingly asks: "Evaluate only if it returns a value, which might be needed".
i have some code that kinda works using inspect module, but it might be prone to break like others mention.
inspect.stack()[1].frame.f_code.co_names[-1]
will be holding the function name when user didn't assign return value to anything, when user assign to var with name XXX, this var will hold XXX. Code comparing this vs the function name to decide whether user assign the return value to any var
import inspect
def func():
tmp = inspect.stack()[1].frame.f_code.co_names[-1]
should_return = tmp != 'func'
print("execute") # execute something
# if should_return False, end here without fetching result
if should_return:
print("fetching result, user assign to {}".format(tmp))
# fetching result and return the result here
>>> func()
execute
>>>
>>> xxx=func()
execute
fetching result, user assign to xxx
>>>
All functions in Python always return. If you don't explicitly return, functions return None.
===========
def func():
while True:
pass
This function does not return.
There is no way of determining if an arbitrary function will return. If you can, you have solved the Turing problem.