passing the values to a function - python

I have a function that returns the replaced values correctly, but for some reason, the run_instances function receives the entire string as a single object (instead of 4 separate values).
import boto
ec2_conn = boto.connect_ec2(aws_access_key_id='XXX', aws_secret_access_key='XXX')
ami='ami-XXX'
key_name='XXX15a.pem'
instance_type='t1.macro'
aid="image_id='%s', placement='us-east-1a', key_name='%s', instance_type='%s'" % (ami, key_name, instance_type)
When I try to execute the run_instances function...
ec2_conn.run_instances(aid)
<Message>Invalid id: "image_id='ami-XXX', placement='us-east-1a', key_name='XXX.pem', instance_type='t1.macro'" (expecting "ami-...")</Message>
Is there any way to pass the values to the function correctly?

Simplifying the problem statement to: how to pass multiple variables around so they can be passed into a function later on without passing all variables individually...:
params = dict(ami='ami-XXX', key_name='XXX15a.pem', instance_type='t1.macro', placement='us-east-1a')
ec2_conn.run_instances(**params)
Store them in a dict and expand them to keyword arguments with **.

Related

Passing a list as arguments to function python

Scenario: I am trying to pass a list of strings to a function, as variable inputs.
Issue: Since the variables in the list are just for one of the arguments, I get the error must be str, not list.
The function hakes three inputs as arguments:
transformfile(path, name, id)
I have a list of names I want to pass:
list_names =['Name1', 'Name2', 'Name3']
I tried passing it directly, but got the aforementioned error...
transformfile(path, list_names, id)
Objective: In this case, my objective would be to make the function run multiple times, for each of the names in list_names.
Question: Is it possible to do this kind of procedure, or do I have to simply call the function directly multiple times?
The function isn't made to receive multiple names, it can only handle single names and there is no way to call it that will change that.
Luckily, this is exactly what for loops are for:
for name in list_names:
transformfile(path, name, id)
This is perfectly fine, normal, etc. Even if the function could receive a list, it'd probably have a for loop internally to do that.
You could also use list comprehensions if transformFile returns something:
result = [transformfile(path, n, id) for n in list_names]
Or even map builtin function with or without functools.partial:
result = map(lambda n: transformFile(path, n, id), list_names)
from functools import partial
result = map(partial(path=path, id=id), list_names)
Note: map returns an iterable so, if you want the result of each call, you need to create a list: list(result)

Function executes either the key is there or not in dictionary.get in python 2.7

I am working with dictionaries in Python and I am searching for a value using:
my_dictionary_object.get("key")
As we all know if the key is missing in dictionary, it will return None object.
So to save extra line and to make my code more interesting I am trying:
def my_function():
'''do some calculations'''
return missing_value_from_dictionary
Now here is the fun part; when I do
my_dictionary_object.get("key", my_function())
it executes the function whether the key is missing or not so I thought let's remove the brackets and I did:
my_dictionary_object.get("key", my_function)
and (just in case)
my_dictionary_object.get("key", lambda: my_function())
but the one without lambda didn't execute (because it was never called) same happened with the one with lambda.
TL;DR
My question is why is the function get executed if the key is present in the dictionary?
Is it something that I am doing wrong or something I am missing here?
In: my_dictionary_object.get("key", my_function()) the execution looks something like:
Evaluate the first argument ("key")
Evaluate the second argument which is an expression: my_function(). So let's call the function, and use the return value in its place. Very much like in: a = my_function(), python would call the function and put the returned value in its place.
Call the mydictionary_object.get(..) with the above two evaluated arguments.
In other words, dictionary.get("key", default) will simply return the 2nd argument if the key doesn't exist. If it is a lambda, lambda is returned. A lambda is an object. Note that in .get("key", my_function()), my_function() is not technically the second argument. The resultant value returned as a result of execution of that function is the second argument -- which explains where you're wrong, hopefully.
What you are looking for is actually captured in another container called defaultdict.
What you'd do is:
from collections import defaultdict
my_dictionary_object = defaultdict(my_function) # my_function should not take any argument.
my_dictionary_object["non-existing-key"] # Magic happens, see below.
What happens is, if the key (=x) doesn't exist, my_function is called without any arguments and the dictionary is updated with the value returned by the function against the key (=x). Something like:
if "key" not in dictionary:
dictionary["key"] = my_function()
return dictionary["key"]

how to pass the parameters to apply correctly

There is an api function
get_next_trading_date(exchange='SZSE', date='2017-05-01')
and I have a DataFrame backTestRecordAfterModified showed as follow
when I run
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(func=get_next_trading_date, exchange='SZSE')
the console displayed the message : TypeError: get_next_trading_date() got multiple values for argument 'exchange'
so,how to pass the parameters correctly
supplementary
backTestRecordAfterModified['createdAt'] = backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'))
the code above still displays the same error.
i add the definition of get_next_trading_date
I got the final answer just now.
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date=date,exchange='SZSE'))
You'll have to use a lambda-function to pass the additional parameter to the get_next_trading_date() function:
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date=date, exchange='SZSE'))
The pandas.Series.apply() function does in fact support additional keyword arguments for the function, but the first argument to the function is always the value from the pandas series.
If get_next_trading_date() was defined differently, with the order of arguments reversed:
get_next_trading_date_2(date='2017-05-01', exchange='SZSE')
you could have used
backTestRecordAfterModified['createdAt']=backTestRecordAfterModified['createdAt'].apply(func=get_next_trading_date, exchange='SZSE').
The apply function is called for each value of the pandas series, and the value is passed as an argument to the function by default.
The additional arguments you specify are passed after the series value.
So in your example, each time the function call would be like
get_next_trading_date(<i-th value of the series>, exchange='SZSE')
But in your function, the first argument is for exchange, so the <i-th value of the series> (current date) is passed to exchange and then there's another keyword argument trying to set the same variable. This causes the error. More in here.
Here you have two options.
a) Change the function definition to take date as first argument, so that you don't have to change your function call. But be sure to make the change everywhere you call this function.
get_next_trading_date(date='2017-05-01', exchange='SZSE')
b) Change your function call to pass date as second argument.
backTestRecordAfterModified['createdAt'] = backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'))
Or simplified as,
backTestRecordAfterModified['createdAt'].apply(lambda date: get_next_trading_date(date, exchange='SZSE'), inplace=True)
One option is to use df.apply instead of series.apply:
df['createdAt'] = df.apply(lambda row: get_date(row['createdAt'], 'SZSE'), axis=1)
Or, if you don't want to pass the whole dataframe:
df['createdAt'] = [get_date(x, 'SZSE') for x in df['createdAt'].values]

Is there any way to access a variable from outside a function, explicitly as a variable and not via assignment to a function?

I'm wanting to replace keywords with values from an associated dictionary.
file1.py
import file2
file2.replacefunction('Some text','a_unique_key', string_variable1)
file2.replacefunction('Other text','another_unique_key', string_variable2)
file2.replacefunction('More text','unique_key_3', string_variable2)
stringvariable1, used in the first function call, is a local variable in file1.py and therefore is accessible as a parameter in the function. It is intentionally a different variable than the one later used in that parameter position.
file2.py
import re
keywords = {
"a_unique_key":"<b>Some text</b>",
"another_unique_key":"<b>Other text</b>",
"unique_key_3":"<b>More text</b>",
}
def replacefunction(str_to_replace, replacement_key, dynamic_source):
string_variable2 = re.sub(str_to_replace, keywords[replacement_key], dynamic_source)
return string_variable2 <-- this variable needs to be accessible
The replacement values in the keywords dictionary are more complicated than shown above, and just demonstrated like this for brevity.
The problem occurs at the second call to replacefunction in file1.py - it cannot access stringvariable2 which is the result of the first function that is run.
I have seen that the way to access a variable produced in a function outside of that function is to do something like:
def helloworld()
a = 5
return a
mynewvariable = helloworld()
print mynewvariable
5 <-- is printed
But this approach won't work in this situation because the function needs to work on a string that is updated after each function call ie:
do this to string 2 # changes occur to string 2
do this to string 2 # changes occur to string 2
do this to string 2 # changes occur to string 2
I can achieve the required functionality without a function but was just trying to minimise code.
Is there any way to access a variable from outside a function, explicitly as a variable and not via assignment to a function?
Don't confuse variables with values. The name string_variable2 references a value, and you just return that from your function.
Where you call the function, you assign the returned value to a local variable, and use that reference to pass it into the next function call:
string_variable2 = file2.replacefunction('Some text','a_unique_key', string_variable1)
string_variable2 = file2.replacefunction('Other text','another_unique_key', string_variable2)
file2.replacefunction('More text','unique_key_3', string_variable2)
Here the replacefunction returns something, that is stored in string_variable2, and then passed to the second call. The return value of the second function call is again stored (using the same name here), and passed to the third call. And so on.

Is it in Python possible to set the last parameter of several in a function call?

Is it in Python possible to set the last parameter of several in a function call if all have a default value?
Example: in the ftplib.FTP the module defines this:
ftplib.FTP([host[, user[, passwd[, acct[, timeout]]]]])
All these parameters have a default value, so you donĀ“t need to set them all, you could, for example, just call ftp = ftplib.FTP() to get a FTP object. But what if I would like to set only the timeout parameter? How would I achieve this?
You can pass this (or any other) parameter by name:
ftplib.FTP(timeout=10)
Yes, by using named arguments you can specify the value with a name-value pair.
ftp = ftplib.FTP(timeout=100)

Categories

Resources