I need to define a function depending on a condition, so that it either does something or nothing.
e.g.
# Code block that *defines* bar
if condition:
bar = do_stuff
else:
bar = # ?
# End of the definition of bar
bar()
do_stuff is a function defined somewhere else that does some useful computation. I want bar() to do be defined to do nothing if the condition above is not met. Any ideas?
Note: I designed the if-else block above for illustration purposes. I know that I could just call do_stuff() in the if body and pass in the else body. The code above is just to illustrate a code block after which I need bar to be defined either to do something or to do nothing. The block just defines the function and is not meant to call it.
To set the variable bar to be a function that does nothing, there are two options:
Using a lambda:
bar = lambda: None
Using a function definition:
def bar():
pass
You could also use return None instead of pass for the function definition, the behavior is equivalent.
You can make a function that does nothing with:
def func():
pass
Related
I understand that you can use "pass" in a user defined function, say, when you do not want to put anything in it at the moment. Where else can I possibly use this keyword? When assigning it to a variable for example, I get an error: my_item = pass Why is this happening and where else can I use this keyword at?
pass is, by itself, an entire statement, and can be used anywhere a statement is expected, but almost always are found in the body of a compound statement.
def foo():
pass
if True:
pass
for x in y:
pass
class Bar:
pass
with foo as bar:
pass
etc.
It is typically used where some statement is needed to fill an otherwise empty code block. Note that since any expression can be used as a statement (a so-called expression statement), you can sometimes use a doc string in place of a pass statement:
class FooError(ValueError):
'''A very specific kind of ValueError'''
instead of
# Legal, but unnecessary
class FooError(ValueError):
'''A very specific kind of ValueError'''
pass
You can only place an expression, not a statement, on the right-hand side of an assignment statement, which is why my_item = pass is a syntax error.
I'm learning the lambda options to return in python and i have a question:
I need to fill the returns in this function:
def func(n):
if n==0:
print("finished")
else:
return ___
func(5)()()()()()
func(3)()()()
func(8)()()()()()()()()
The output:
finished
finished
finished
I thought this one is a recursive call like return func(n-1) but it doesn't work, and throws an error.
Is there an option to overcome the extra empty brackets? count them? do something, because it should be runnable.
Thanks
You're right about needing to use lambdas and func n-1, specifically
return lambda: func(n-1)
This returns a lambda that doesn't need any parameters passed in, to handle the brackets, and the return of the is the function being called with n-1, which in most calls you're making, is returning the next lambda function call
The operator () is the function call.
So for example:
def foo():
print('Foo executed')
def bar():
# We return the foo FUNCTION itself, without calling it.
return foo
In the above code, if you execute foo(), it'll print "Foo executed". But if you execute bar(), it will return foo, which is the function. So you can execute bar()(), where the first () is executing the function bar, returning foo, and then with the second (), you call the returned foo function.
Edit: When I typed it, you removed the what are those bunch of () because they are new to you... But I just leave it there maybe it'll help.
This simple Python code gets "False".
def foo():
def bar():
return 0
return bar
print(foo() == foo())
When I request
print(foo(),foo())
I get
<function foo.<locals>.bar at 0x03A0BC40> <function foo.<locals>.bar at 0x03C850B8>
So does Python store the result of the bar function every time in the new memory slot? I'd be happy if someone explain how it works behind the scene and possibly how this code can be a little bit modified to get "True" (which still seems logical to me!).
Each def statement defines a new function. The same name and body doesn't really matter. You're basically doing something like this:
def foo():
pass
old_foo = foo
def foo():
pass
assert old_foo == foo # will fail
bar is locally defined within foo the same way a local variable would be each time you call the foo().
As you can see by the defult __repr__, they have different memory addresses, and since bar does not implement __eq__, the two instances of bar will not be equal.
I'm trying to modify a function which uses a module-level variable variable defined below it, similar to this:
def say_hello():
print(MESSAGE)
MESSAGE = "Hello, world!"
say_hello()
I would like to make the message a parameter, like so:
MESSAGE = "Hello, world!"
def say_hello(message=MESSAGE):
print(message)
say_hello()
I've noticed that in order for this to work, I had to move the definition of MESSAGE up in the code. Apparently, all module-levels are first 'bound' and are then available within function bodies, but when provided as default function arguments, they have to be defined before the function. Is this correct?
(I would also like to read up on this to fully understand it; any references would be much appreciated).
... when provided as default function arguments, they have to be defined before the function. Is this correct?
Correct. Default arguments are evaluated at function definition time.
If you need them evaluated at function call time, this common pattern works:
def say_hello(message=None):
if message is None:
message = MESSAGE
print(message)
MESSAGE = "Hello, world!"
say_hello()
def say_hello():
print(MESSAGE)
# ^^^^^^^ This...
...is evaluated when say_hello is called. As long as MESSAGE has been assigned by the time say_hello is called, say_hello will see the value.
# vvvvvvv This...
def say_hello(message=MESSAGE):
print(message)
...is evaluated when say_hello is defined. Python evaluates default argument values at function definition time, so MESSAGE has to be assigned before say_hello is even defined for this to work.
While you're learning about default argument binding, give this a try:
def foo(bar=[]):
bar.append(3)
print(bar)
baz = []
faz = []
foo(baz)
foo(faz)
foo()
foo()
The calls with their own arguments will do what you expect - each one prints only one variable. But the calls to foo with the default argument may surprise you. The first time you call it, you get the expected result: [3]. The second time you call it, you may be surprised that the result is [3, 3].
There's actually nothing in this answer that isn't in the others. As others have said, the default argument is evaluated at the time the function is defined. What you see here is a consequence of that - the arguments are evaluated only at the time that the function is defined. bar=[] is evaluated once, giving you one list.
If you do object creation or function calls as part of your default argument, they only happen once, with the net result being a surprisingly static-acting argument. Most of the time, this is not what we're looking for.
The definitive reference for python is found at docs.python.org . The specific reference for defining functions is at https://docs.python.org/3/tutorial/controlflow.html#defining-functions.
I would like to do this:
def foo():
if <a magical condition>:
return x
else:
poof()
# or...
def foo():
x = <a magical object>
return x
def poof():
print 'poof!'
bar = foo() # bar points to <a magical object> but poof() is not called
foo() # prints 'poof!'
I guess it comes down to what the circumstanses are when the returned object's __del__ method is called. But maybe there is a better way. Like if the function itself knew it's returned value was being assigned. I guess I'm worried about relying on the timing of the garbage collection. Also I don't like that global at_end_of_program flag.
My solution:
class Magic:
def __del__(s):
poof()
def foo():
x = Magic()
return x
def poof():
if not at_end_of_program:
print 'poof!'
bar = foo() # No poof.
foo() # prints 'poof!'
I'm pretty confused by your question, but I think what you are trying to do is run a function when a value is reassigned.
Instead of doing tricky things with a __del__() method function, I suggest you just put your value into a class instance, and then overload __setattr__(). You could also overload __delattr__() to make sure you catch del(object.x) for your value x.
The very purpose of __setattr__() is to give you a hook to catch when something assigns to a member of your class. And you won't need any strange end_of_program flag. At the end of your program, just get rid of your overloaded function for __delattr__() so it doesn't get called for end-of-program cleanup.
A function can't tell what its return value is used for. Your solution will print poof if you re-assign to bar for example.
What's the real problem you are trying to solve?