How to change function name dynamically in python - python

I want to change the function name according to result obtained from another function but the function definition remains same How can i do this i tried the following example but it didn't work
def f(text):
def x(text):
return text+"example"
name=x(text)
def name(y):
return y
return name
p=f("hi ")
print p("hello")
print p.__name__
OUTPUT
hello
name
But i want the function name p.__name__ as "hi example" not name

You can simply assign to __name__:
def f(text):
def r(y):
return y
r.__name__ = text + "example"
return r
p = f("hi ")
print (p("hello")) # Outputs "hello"
print (p.__name__) # Outputs "hi example"
Note that a function name does not have any influence on the function's behavior though, and does not have any meaning except as a part of the string representation or a debugging aid.

Related

How to call functions and variables from a dictionary or a json file

I am trying to print a string, call functions and variables in a line.
such as [Hello! %(job), %(name)s, (function_name)]->[Hello! student, John, This is the function.]
json01.json
{
"test" : "Hello! %(job), %(name)s, (function_name)"
}
test01.py
import json
a = 'test'
name = 'John'
job = 'student'
def function_name(message):
print(message)
with open('json01.json') as json_file:
json_dict = json.load(json_file)
if a in json_dict:
print(json_dict[a] %locals())
#This works if there's only variables in the value
#but I don't know how to call functions when the value is not only function's name but also variables..
Is there any simple way to print whatever they are in the value?
or is there another way to do this work?
Sorry for the poor explanation and Thank you!
You can define your own function replacer using regular expressions. I defined an example syntax here as: Hello, !(function_name) where function_name is the name of the function that is called.
Using regular expressions we find all occurences of a function call and try to
evaluate them one by one. If successfull, we replace the function's name with the return value.
import re
def runfunctions(string):
# find all functions defined with our syntax
funcs = re.findall(r'!\((.*?)\)', string)
result = string
# iterate through found functions
for func in funcs:
try:
# try to evaluate with globals()[func]() and replace function call
# with return value
result = re.sub(r'!\(' + func + r'\)', globals()[func](), result)
except (KeyError, TypeError) as e:
# if func is not callable or does not exist catch error
print("Error while evaluating functions in string:", e)
# return final result
return result
Note: I used globals instead of locals as otherwise the function is not found.
You can use it like this:
if a in json_dict:
replaced_vars = json_dict[a] % locals()
replaced_funcs = runfunctions(replaced_vars)
print(replaced_funcs)

Get variable from a parent function

I have a function that produces another function.
def make_func(greeting):
def func(name):
return greeting + " " + name
return func
>>> say_hello = make_func("Hello")
>>> say_hello("there")
"Hello there"
Elsewhere in the script, I have access to say_hello, but I have no idea what the greeting in that function actually is. I'd like to find out.
name, of course, isn't possible to get because it's specified when the function is called. But greeting is static, because it's defined outside of the function.
Is there some attribute of say_hello I can examine to get the original "Hello"?
You can find a good explanation of how inner functions are compiled in python here
Then the easiest way to get the variable is say_hello.__closure__[0].cell_contents
You can just store the attribute greeting in func:
def make_func(greeting):
def func(name):
return func.greeting + " " + name
func.greeting = greeting
return func
say_hello = make_func("Hello")
print(say_hello.greeting) # Hello
say_hello.greeting = 'Bye'
print(say_hello('there')) # Bye there

How to check arguments passed to the function call are empty?

I want the function to simply check if an argument is passed or not. If not, print something, else say some hello and that argument.
Here is sample of my code:
def say_name(name):
if name is None:
print("Hello there")
else:
print("Hello, "+ name + "!")
run code:
class Test(unittest.TestCase):
def test_should_say_hello(self):
self.assertEqual(say_name("Michael"), "Hello, Michael!")
I have tried using None, Kwargs and still not working. How can I check whether argument is passed to the function?
To make a parameter optional assign it a default value:
def say_name(name=None):
if name is None:
print("Hello there")
else:
print("Hello, "+ name + "!")
Addendum: As Barmar pointed out in the comments to your question, your function needs to return a string to make your check work.
def say_name(name=None):
if name is None:
return "Hello there"
else:
return "Hello, "+ name + "!"
To check whether "any" of the argument is passed with the function call
In general, in order to check whether any argument is passed or not, you may create your function using *args (for non-keyworded variable length argument list) and **kwargs (for keyworded variable length argument list). For example:
def check_argument(*args, **kwargs):
if args or kwargs: # check if any among the `args` or `kwargs` is present
return "Argument Passed!"
else:
return "Argument Not passed!"
Sample Run:
# For "non-keyworded" argument
>>> check_argument('something')
'Argument Passed!'
# For "keyworded" argument
>>> check_argument(some_param='some_value')
'Argument Passed!'
# For no argumenet
>>> check_argument()
'Argument Not passed!'
To check if any "specific" argument is passed with the function call
For your scenario, since you only care about one specific parameter name and perform operation based on the value passed, you may assign a default value to it's function definition as:
# v Default value as `None`
def say_name(name=None):
if name is None:
return "Hello, there!"
else:
return "Hello, "+ name + "!"
Above function could be simplified as:
# v setting default name as "there"
def say_name(name="there"):
return "Hello, {}!".format(name)
# Or you may also check it within the format as
def say_name(name=None):
return "Hello, {}!".format(name or "there")
Sample Run:
>>> say_name()
Hello, there!
>>> say_name('StackOverflow')
Hello, StackOverflow!
def say_hello(*name):
if name:
return "Hello, "+name[0]+"!"
else:
return "Hello there!"
This should work

Using return value inside another function

I have these two functions:
def check_channel_number(self):
print "***************Channel Checker *********************"
print ''
user_channel_number = int(re.sub('\D', '', raw_input("Enter a channel number, (3digit): "))[:3]);
channel = ("channelNr= '%d'") % (user_channel_number)
print channel
# channel_search = channel + str(user_channel_number)
datafile = file('output.txt')
found = False
for line in datafile:
if channel in line:
found = True
print 'The channel number you entered is correct and will be deleted'
return user_channel_number
print 'The channel number you entered is not on the planner'
return False
and
def delete_events(self):
if user_channel_number == True:
return 'The program number is correct and will be deleted'
# action = 'DeleteEvent'
menu_action = 'all'
book = 'RECYC:687869882'
arg_list = [('C:\\Users\\yke01\\Documents\\StormTest\\Scripts\\Completed'
'\\Utils\\UPNP_Client_Cmd_Line.py')]
arg_list.append(' --action=')
arg_list.append(action)
arg_list.append(' --ip=')
arg_list.append('10.10.8.89')
arg_list.append(' --objectId=')
arg_list.append(book)
subprocess.call(["python", arg_list])
print 'The program deleted successfully'
When I run my script, it says that user_channel_number is not defined globally. How can I use user_channel_number inside the delete_events function?
When you define a variable inside of a function, it is a local variable, meaning that it can only be accessed within that function.
Within a Class
It looks like you're inside a class, so you can make the variable accessible to all methods in the class by defining it like this:
def check_channel_number(self):
self.user_channel_number = ...
And then in your second function, you can use it like the following:
def delete_events(self):
if self.user_channel_number:
Outside of a class
If you aren't using methods inside of a class, you can instead use the global builtin.
For example,
def check_channel_number():
global user_channel_number
user_channel_number = ...
def delete_events():
if user_channel_number:
...
Using a value returned from a function
Instead in your first function, check_channel_number(), you can have it return user_channel_number. You can then call that function inside of delete_events(), like the following:
def check_channel_number():
user_channel_number = ...
return user_channel_number
def delete_events():
if check_channel_number():
...
Functions can not share their local variables. You can return the value from the first and pass it to the second:
def check_channel_number(self):
...
return user_channel_number
def delete_events(self):
user_channel_number = self.check_channel_number()
...
Or save value on the object:
def check_channel_number(self):
...
self.user_channel_number = user_channel_number
...
def delete_events(self):
if self.user_channel_number:
....
So I think when you call the check_channel_number function, user_channel_number is defined in there, so when you call delete_events, it has gone out of scope, maybe something like this would help?
user_channel_number = check_channel_number()
delete_events()
I'd probably have the user_channel_number as an input to the delete function too, so it would turn into this: (where ucn is the user_channel_number)
def delete_events(self, ucn):
if ucn == True:
print 'The program number is correct and will be deleted'
# action = 'DeleteEvent'
menu_action = 'all'
book = 'RECYC:687869882'
arg_list = [('C:\\Users\\yke01\\Documents\\StormTest\\Scripts\\Completed'
'\\Utils\\UPNP_Client_Cmd_Line.py')]
arg_list.append(' --action=')
arg_list.append(action)
arg_list.append(' --ip=')
arg_list.append('10.10.8.89')
arg_list.append(' --objectId=')
arg_list.append(book)
subprocess.call(["python", arg_list])
print 'The program deleted successfully'
I have also changed `return 'The program number is correct and will be deleted'' to a print statement as I have a feeling the return would end the function before the other lines of code would be run
So the code would probably end up being something like:
user_channel_number = check_channel_number()
delete_events(user_channel_number)
EDIT:
just noticed it looks like your functions are part of a class,
in that case, you could do:
self.ucn = self.check_channel_number()
self.delete_events(self.ucn)
(or if you dont want to pass the user_channel_number into the function you could change if user_channel_number: to if self. user_channel_number:

How to get just the return value from a function in Python?

I'm trying to learn programming through Python and I like to know if it's possible to get just the return value of a function and not its other parts. Here's the code:
Let's say, this is the main function:
variable_a = 5
while variable_a > 0 :
input_user = raw_input(": ")
if input_user == "A":
deduct(variable_a)
variable_a = deduct(variable_a)
else:
exit(0)
Then this is the deduct function:
def deduct(x):
print "Hello world!"
x = x - 1
return x
What happens is that, it does the calculation and deduct until variable_a reaches 0. However, "Hello world!" gets printed twice, I think because of variable_a = deduct(variable_a) (correct me if I'm wrong). So I was thinking, can I just capture the return value of deduct() and not capture the rest? So that in this instance, after going through deduct(), variable_a would just have a plain value of 2 (without the "Hello world!").
Am I missing things? :?
Editor's note: I remove the blank lines, so it can be pasted to REPL.
The printing of "Hello world" is what's known as a side effect - something produced by the function which is not reflected in the return value. What you're asking for is how to call the function twice, once to produce the side effect and once to capture the function return value.
In fact you don't have to call it twice at all - once is enough to produce both results. Simply capture the return value on the one and only call:
if input_user == "A":
variable_a = deduct(variable_a)
else:
If you don't want your function to print output, the correct solution is to not use print in it. :P
The first time you call deduct, it doesn't do anything except print that message, so you could probably just remove that line and be fine.
However, there is a slightly messy way to suppress print statements. You can temporarily replace your program's output file with a placeholder that does nothing.
import sys
class FakeOutput(object):
def write(self, data):
pass
old_out = sys.stdout
sys.stdout = FakeFile()
print "Hello World!" # does nothing
sys.stdout = old_out
print "Hello Again!" # works normally
You could even make a context manager to make this more convenient.
import sys
class FakeOutput(object):
def __enter__(self):
self.out_stdout = sys.stdout
sys.stdout = self
return self
def __exit__(self, *a):
sys.stdout = self.out_stdout
def write(self, data):
pass
print "Hello World!" # works
with FakeOutput():
print "Hello Again!" # doesn't do anything
print "Hello Finally!" # works

Categories