I have a a function that takes as input 2 strings and a tuple of points. Based on the combination of those two strings, a specific function should be called on the tuple. I know that I could program some nested if statements, but I'm interested in the idea of calling an existing function from a string.
For example, I have a conversion function 'foo2bar(points)' which converts 'foo' points to 'bar' points. I have many other types of points and conversions between them. I now want to implement a 'type2type(points, oldtype, newtype)' which takes strings oldtype and newtype, and baed on those strings should call the appropriate conversion.
If I call type2type(points, 'foo','bar'), I want it to result in calling foo2bar(points).
Is there a way to generate function calls by concatenating strings like that? I want to say something like functionName = oldtype + '2' + newtype and then call 'functionName somehow.
Well, this isn't the safest way to do things, by you could use eval. Using the code you posted at the bottom, functionName = oldtype + '2' + newtype, you could just do:
functionName = oldtype + '2' + newtype
args = [] #whatever arguments you want in the function
eval(functionName+"(**args)")
You're almost there: after you've constructed functionName you just need to find the function. If your functions are all in a class, you could write something like this:
def type2type(self, points, x, y):
name = '{}2{}'.format(x, y)
if hasattr(self, name):
return getattr(self, name)(points)
else:
raise ValueError("No function named {}".format(name))
If they're module-level functions, you can look for them in globals:
def type2type(points, x, y):
name = '{}2{}'.format(x, y)
if name in globals():
return globals()[name](points)
else:
raise ValueError("No function named {}".format(name))
Related
Sorry for my ugly English.
This is one of my homework.
I'm making function that finds the max integer in any list, tuple, integer..
like "max_val((5, (1,2), [[1],[2]])) returns 5"
When I ran my code, there was no syntax error. I ran as many various cases I can.
But the homework system told me this code was incorrect.
Anyone give me hint?
numList = []
def max_val(t):
if type(t) is int:
numList.append(t)
else:
for i in range(len(t)):
if t[i] is int:
numList.append(t[i])
else:
max_val(t[i])
return max(numList)
Your code gives wrong results when called several times:
>>> max_val((5,4,3))
5
>>> max_val((2, 1))
5
That's because numList is a global variable that you don't "reset" between calls of your function.
You can simplify your code quite a bit, without needing that global variable:
def max_val(t):
if isinstance(t, int):
return t # t is the only element, so it's by definition the biggest
else:
# Assuming max_val works correctly for an element of t,
# return the largest result
return max(max_val(element) for element in t)
As explained in L3viathan's answer, the main issue with your code is that numList is a global variable. Here is a simple way to fix it without changing the logic of your code:
def max_val(t):
numList = [] # local variable
max_val_helper(t, numList) # fill numList with elements from t
return max(numList)
def max_val_helper(t, numList): # this function modifies its second argument and doesn't return a value
if type(t) is int:
numList.append(t)
else:
for i in range(len(t)):
max_val_helper(t[i], numList)
The function max_val_helper is recursive and appends all numbers in the nested iterables to its argument numList. This function doesn't have a return value; the effect of calling it is that it modifies its argument. This kind of function is sometimes called a "procedure".
The function max_val, on the other hand, is a "pure" function: it returns a value without any side-effect, like modifying its argument or a global variable. It creates a local variable numList, and passes this local variable to max_val_helper which fills it with the numberss from the nested iterables.
The code suggested in L3viathan's answer is arguably more elegant than this one, but I think it's important to understand why your code didn't work properly and how to fix it.
It's also good practice to differentiate between functions with side-effects (like modifying an argument, modifying a global variable, or calls to print) and functions without side-effects.
How can I pass an integer by reference in Python?
I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.
How can I pass an integer into a function by reference?
What are the best practices?
It doesn't quite work that way in Python. Python passes references to objects. Inside your function you have an object -- You're free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:
def change(x):
x[0] = 3
x = [1]
change(x)
print x
This is ugly/clumsy at best, but you're not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).
Understanding this, we can see why there is no way to change the value of an immutable object inside a function -- you can't change any of its attributes because it's immutable, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.
Usually the workaround is to simply return the object that you want:
def multiply_by_2(x):
return 2*x
x = 1
x = multiply_by_2(x)
*In the first example case above, 3 actually gets passed to x.__setitem__.
Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A "best practice" is to use multiple return values, which is much easier to do in Python than in languages like Java.
Here's a simple example:
def RectToPolar(x, y):
r = (x ** 2 + y ** 2) ** 0.5
theta = math.atan2(y, x)
return r, theta # return 2 things at once
r, theta = RectToPolar(3, 4) # assign 2 things at once
Not exactly passing a value directly, but using it as if it was passed.
x = 7
def my_method():
nonlocal x
x += 1
my_method()
print(x) # 8
Caveats:
nonlocal was introduced in python 3
If the enclosing scope is the global one, use global instead of nonlocal.
Maybe it's not pythonic way, but you can do this
import ctypes
def incr(a):
a += 1
x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref
Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you're passing in to the function?
If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson's answer demonstrates.
If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can't think of anything, go back and read the sentence again a few times, and then use the list.
More generally, if you're trying to port some Java idiom directly to Python, you're doing it wrong. Even when there is something directly corresponding (as with static/#staticmethod), you still don't want to use it in most Python programs just because you'd use it in Java.
Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:
def inc_i(v):
v.i += 1
x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it's a more convenient by-reference number container than a single-element list.
import numpy as np
def triple_var_by_ref(x):
x[0]=x[0]*3
a=np.array([2])
triple_var_by_ref(a)
print(a+1)
output:
7
The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.
class Thing:
def __init__(self,a):
self.a = a
def dosomething(ref)
ref.a += 1
t = Thing(3)
dosomething(t)
print("T is now",t.a)
In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.
Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.
class PassByReference:
def Change(self, var):
self.a = var
print(self.a)
s=PassByReference()
s.Change(5)
class Obj:
def __init__(self,a):
self.value = a
def sum(self, a):
self.value += a
a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2
In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that's passed to a method.
integers are immutable in python and once they are created we cannot change their value by using assignment operator to a variable we are making it to point to some other address not the previous address.
In python a function can return multiple values we can make use of it:
def swap(a,b):
return b,a
a,b=22,55
a,b=swap(a,b)
print(a,b)
To change the reference a variable is pointing to we can wrap immutable data types(int, long, float, complex, str, bytes, truple, frozenset) inside of mutable data types (bytearray, list, set, dict).
#var is an instance of dictionary type
def change(var,key,new_value):
var[key]=new_value
var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])
I am getting an value from the user in getInteger.
I need to get the output from sqInteger in getInteger.
No matter how I set up the parameters or indent the sqInteger function, variable x is undefined.
I added a return line to try and pass the x variable, but that's definitely not helping.
Please help me understand what I'm missing!
def getInteger():
while True:
try:
x = int(input('Enter an integer: '))
except ValueError:
print()
print('That\'s not an integer. Try again.')
continue
else:
return x
print(x)
break
def sqInteger(getInteger, x):
y = x**2
print(y)
Is this the entire code? You need to call the getInteger() function at some point in the code before that loop will begin. You're also not calling function sqInteger() at any point.
Your exception handler will immediately stop evaluating the try block and move down to the except block upon a non-integer being typed into the input. Therefore, you can place a call to the sqInteger() function after the input() function. If the user types a non-integer into the terminal, it will move down to your Exception handler and prompt the user to retry. If they enter an integer, the code will continue to evaluate and run the function sqInteger.
For this, you also do not need to pass getInteger into the sqInteger() function. You are technically allowed to pass functions as parameters in Python but it's not necessary for this and probably out of the scope of this program.
So the following code would be suitable:
def getInteger():
while True:
try:
x = int(input('Enter an integer: '))
# variable 'squared' now receives the return value from the function
squared = sqInteger(x) # call to function sqInteger necessary for this function to be executed
except ValueError:
print('That\'s not an integer. Try again.')
continue
else:
print(x) # if user entered 2, prints 2, not 4
return x # this value is still only what the user input, not the result of sqInteger()
break
def sqInteger(x):
y = x**2
print(y)
return y #you need to return values from functions in order to access it from outside the function
The reason you pass a variable into a function (as a parameter) is to give that function access to that variable. Creating a function creates a local scope for that function so that variables named within that function are in a separate namespace from variables outside that function. This is useful in large programs where many variables might exist and you need to keep them separate.
Because you've separately defined a sqrt function, it does not have access to variables outside of its scope. You need to pass in variables that you'd like it to have access to.
You also need to call functions before they will run. Defining a function only serves to set up the function so that it can be called as one functional unit. It's useful for separating concerns within a program. The ability to call a function is useful because it allows you to separate your code out and only mention a single call to a function rather than having the entire functionality jumbled in with the rest of the code. It also allows for reusability of code.
You can also have access to the result of the squared integer by returning a value and assigning this value to a function call, like such:
# lets say x = 4
squared = sqInteger(x)
def sqInteger(x):
y = x**2
return y
This would NOT work:
x = input("Enter integer") #lets say you enter 3
squared = sqInteger()
print(squared)
def sqInteger():
print(x) # error: x is not defined
return x**2 # error: x is not defined
The function does not have access to outside variables like x. It must be passed these variables as parameters so that you can call this function and set the parameters at will. This is for the sake of modularity in a program. You can pass it all sorts of different integers as parameters and it allows you to have a resuable function for anytime you need to square an integer.
Edit: Sorry this was a mess, I finally fixed all the errors in my explanation though...
I have a function g() with takes a dict as an argument, ex:
>> g({'a':'foo', 'b':'bar', 'c','baz'})
a = foo
b = bar
c = baz
I would like to 'convert' g() or create a new function f() from g() such that it would take positional arguments instead of a dictionary, ex:
>> f(a='foo', b='bar', c='baz')
a = foo
b = bar
c = baz
Background:
My goal is to write a small API which will make it easy for users to leverage this core package: https://github.com/fmfn/BayesianOptimization.
To use the API, users will have to provide their user-defined-function.
My future API will provide the user-defined-function to the core package.
The core package expects functions which take positional arguments (not a dict).
These user-defined-function are potentially complex and will most likely take many arguments, I would rather tell users to build their functions taking dictionaries as an argument rather than a long list of positional arguments (and do some kind of transformation within my API before invoking the core package).
Or can anyone think of a better way to address this?
Thanks!
In essence, what you want is a function decorator, that executes some sort of preprocessing logic before calling your function. First, create your decorator. It will receive keyword arguments and pass it to an inner function.
In [239]: def baz(fnc):
...: def inner(**kwargs):
...: fnc(kwargs)
...: return inner
...:
Decorate your original function with the decorator syntax using #...:
In [240]: #baz
...: def foo(dict_):
...: for k in dict_:
...: print(k, '=', dict_[k])
...:
Call your original function:
In [241]: foo(a=1, b=2, c=3)
a = 1
b = 2
c = 3
Decorators
I would use the exec method, because it allows you to do anything you would be able to do in code, so there isn't much extra to learn. As an example, if you insert the following code into your code, you can create a simple function which has one arguments for every index in the dictionary, and the argument identifiers are each lowercase letter of the alphabet (so this only works if you don't exceed 26 arguments
def MakeFunction(DictionaryToUse):
arguments = ""#Defaults to no arguments
for i in range(97,97+len(DictionaryToUse)):#Adds another argument per dictionary item
arguments += chr(i) + ","
if len(arguments) > 0:
arguments = arguments[:-1]#Removes the last comma, if there is one
exec("def f(" + arguments + """):
print("hi")""",globals())#Defines a new function f so it can be called as a global function.
So to make a function with 3 arguments for example, you would use:
MakeFunction({"foo":0,"bar":10,"foobar":96})
and then the new function, named f, can be called, with 3 arguments.
f(1,2,3)
You'll have to tailor this to suit your needs obviously, replacing f with your desired function name, and adding whatever you would like the function to do instead of print("hi").
I have found a simple way to solve the problem
Here is a simple function g taking a dict as an argument I want to 'convert':
>>> def g(my_dict):
print('a:', str(my_dict['a']))
print('b:', str(my_dict['b']))
A new function f which takes keyword arguments can easily be created from g:
>>> def f(**kwargs):
return g(kwargs)
Let's try f with keyword args:
>>> f(a='foo', b='bar')
a: foo
b: bar
f will not work with positional args:
>>> f('foo', 'bar')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-619-505f263ccdf6> in <module>()
----> 1 f(1, 2)
TypeError: f() takes 0 positional arguments but 2 were given
Notes:
I originally asked the 'converted' function f to take positional arguments. After doing additional research, I found out I what I meant was keyword arguments. I used the wrong terminology in the question, my apologies.
My attempts with decorators as proposed by #COLDSPEED were only partially successful: I was able to create a function f which seemed to work but somehow the rest of the code was seeing the values it returned as None. Feel free to comment if you have an explanation.
Is there a way that I can write a predicate function that will compare two strings and see which one is greater? Right now I have
def helper1(x, y):
return x > y
However, I'm trying to use the function in this way,
new_tuple = divide((helper1(some_value, l[0]),l[1:])
Please note that the above function call is probably wrong because my helper1 is incomplete. But the gist is I'm trying to compare two items to see if one's greater than the other, and the items are l[1:] to l[0]
Divide is a function that, given a predicate and a list, divides that list into a tuple that has two lists, based on what the predicate comes out as. Divide is very long, so I don't think I should post it on here.
So given that a predicate should only take one parameter, how should I write it so that it will take one parameter?
You should write a closure.
def helper(x):
def cmp(y):
return x > y
return cmp
...
new_tuple = divide(helper1(l[0]), l[1:])
...