How to change a python dictionary within a function? - python

So im running into an issue trying to get my dictionary to change within a function without returning anything here is my code:
def load_twitter_dicts_from_file(filename, emoticons_to_ids, ids_to_emoticons):
in_file = open(filename, 'r')
emoticons_to_ids = {}
ids_to_emoticons = {}
for line in in_file:
data = line.split()
if len(data) > 0:
emoticon = data[0].strip('"')
id = data[2].strip('"')
if emoticon not in emoticons_to_ids:
emoticons_to_ids[emoticon] = []
if id not in ids_to_emoticons:
ids_to_emoticons[id] = []
emoticons_to_ids[emoticon].append(id)
ids_to_emoticons[id].append(emoticon)
basically what im trying to do is to pass in two dictionaries and fill them with information from the file which works out fine but after i call it in the main and try to print the two dictionaries it says they are empty. Any ideas?

def load_twitter_dicts_from_file(filename, emoticons_to_ids, ids_to_emoticons):
…
emoticons_to_ids = {}
ids_to_emoticons ={}
These two lines replace whatever you pass to the function. So if you passed two dictionaries to the function, those dictionaries are never touched. Instead, you create two new dictionaries which are never passed to the outside.
If you want to mutate the dictionaries you pass to the function, then remove those two lines and create the dictionaries first.
Alternatively, you could also return those two dictionaries from the function at the end:
return emoticons_to_ids, ids_to_emoticons

Related

Calling existing variable (list) reconstructed with StringVar()

I have a several lists that I am trying to activate or use that are named as follows:
public_forum_jr_soc = []
parliamentary_jr_soc = []
european_jr_soc = []
etc...
I have a bunch of radiobuttons that has variables to recreate these lists names, and it outputs something like this.
print(self.select_league.get()+self.select_age.get()+self.select_grade.get())
append_name = self.select_league.get()+self.select_age.get()+self.select_grade.get()
>>>
european_jr_soc
I try to proceed to use this list in as an argument for a function.
output_data(append_name)
def master_groper2(outof48):
for i in outof48:
if i[15] in ['ENGLISH','english','']:
i[15] = 'English'
elif i[15] in ['Mandarin','CHINESE',]:
i[15] = 'Chinese'
However, I get a IndexError: string index out of range as python reads it as european_jr_soc, instead of the actual list, despite sharing the same name, how could I have python have it read it as the variable list?

Path inside the dictionary from the variable

I have a code:
def replaceJSONFilesList(JSONFilePath, JSONsDataPath, newJSONData):
JSONFileHandleOpen = open(JSONFilePath, 'r')
ReadedJSONObjects = json.load(JSONFileHandleOpen)
JSONFileHandleOpen.close()
ReadedJSONObjectsModifyingSector = ReadedJSONObjects[JSONsDataPath]
for newData in newJSONData:
ReadedJSONObjectsModifyingSector.append(newData)
JSONFileHandleWrite = open(JSONFilePath, 'w')
json.dump(ReadedJSONObjects, JSONFileHandleWrite)
JSONFileHandleWrite.close()
def modifyJSONFile(Path):
JSONFilePath = '/path/file'
JSONsDataPath = "['first']['second']"
newJSONData = 'somedata'
replaceJSONFilesList(JSONFilePath, JSONsDataPath, newJSONData)
Now I have an error:
KeyError: "['first']['second']"
But if I try:
ReadedJSONObjectsModifyingSector = ReadedJSONObjects['first']['second']
Everything is okay.
How I should send the path to the list from the JSON's dictionary — from one function to other?
You cannot pass language syntax elements as if they were data strings. Similarly, you could not pass the string "2 > 1 and False", and expect the function to be able to insert that into an if condition.
Instead, extract the data items and pass them as separate strings (which matches their syntax in the calling routine), or as a tuple of strings. For instance:
JSONsDataPath = ('first', 'second')
...
Then, inside the function ...
ReadedJSONObjects[JSONsDataPath[0]][JSONsDataPath[1]]
If you have a variable sequence of indices, then you need to write code to handle that case; research that on Stack Overflow.
The iterative way to handle an unknown quantity of indices is like this:
obj = ReadedJSONObjects
for index in JSONsDataPath:
obj = obj[index]

Multiple dictionary list of values assignment with a single for loop for multiple keys

I want to create a dictionary with a list of values for multiple keys with a single for loop in Python3. For me, the time execution and memory footprint are of utmost importance since the file which my Python3 script is reading is rather long.
I have already tried the following simple script:
p_avg = []
p_y = []
m_avg = []
m_y = []
res_dict = {}
with open('/home/user/test', 'r') as f:
for line in f:
p_avg.append(float(line.split(" ")[5].split(":")[1]))
p_y.append(float(line.split(" ")[6].split(":")[1]))
m_avg.append(float(line.split(" ")[1].split(":")[1]))
m_avg.append(float(line.split(" ")[2].split(":")[1]))
res_dict['p_avg'] = p_avg
res_dict['p_y'] = p_y
res_dict['m_avg'] = m_avg
res_dict['m_y'] = mse_y
print(res_dict)
The format of my home/user/test file is:
n:1 m_avg:7588.39 m_y:11289.73 m_u:147.92 m_v:223.53 p_avg:9.33 p_y:7.60 p_u:26.43 p_v:24.64
n:2 m_avg:7587.60 m_y:11288.54 m_u:147.92 m_v:223.53 p_avg:9.33 p_y:7.60 p_u:26.43 p_v:24.64
n:3 m_avg:7598.56 m_y:11304.50 m_u:148.01 m_v:225.33 p_avg:9.32 p_y:7.60 p_u:26.43 p_v:24.60
.
.
.
The Python script shown above works but first it is too long and repetitive, second, I am not sure how efficient it is. I was eventually thinking to create the same with list-comprehensions. Something like that:
(res_dict['p_avg'], res_dict['p_y']) = [(float(line.split(" ")[5].split(":")[1]), float(line.split(" ")[6].split(":")[1])) for line in f]
But for all four dictionary keys. Do you think that using list comprehension could reduce the used memory footprint of the script and the speed of execution? What should be the right syntax for the list-comprehension?
[EDIT] I have changed the dict -> res_dict as it was mentioned that it is not a good practice, I have also fixed a typo, where the p_y wasn't pointing to the right value and added a print statement to print the resulting dictionary as mentioned by the other users.
You can make use of defaultdict. There is no need to split the line each time, and to make it more readable you can use a lambda to extract the fields for each item.
from collections import defaultdict
res = defaultdict(list)
with open('/home/user/test', 'r') as f:
for line in f:
items = line.split()
extract = lambda x: x.split(':')[1]
res['p_avg'].append(extract(items[5]))
res['p_y'].append(extract(items[6]))
res['m_avg'].append(extract(items[1]))
res['m_y'].append(extract(items[2]))
You can initialize your dict to contain the string/list pairs, and then append directly as you iterate through every line. Also, you don't want to keep calling split() on line on each iteration. Rather, just call once and save to a local variable and index from this variable.
# Initialize dict to contain string key and list value pairs
dictionary = {'p_avg':[],
'p_y':[],
'm_avg':[],
'm_y':[]
}
with open('/home/user/test', 'r') as f:
for line in f:
items = line.split() # store line.split() so you don't split multiple times per line
dictionary['p_avg'].append(float(items[5].split(':')[1]))
dictionary['p_y'].append(float(items[6].split(':')[1])) # I think you meant index 6 here
dictionary['m_avg'].append(float(items[1].split(':')[1]))
dictionary['m_y'].append(float(items[2].split(':')[1]))
You can just pre-define dict attributes:
d = {
'p_avg': [],
'p_y': [],
'm_avg': [],
'm_y': []
}
and then append directly to them:
with open('/home/user/test', 'r') as f:
for line in f:
splitted_line = line.split(" ")
d['p_avg'].append(float(splitted_line[5].split(":")[1]))
d['p_y'].append(float(splitted_line[5].split(":")[1]))
d['m_avg'].append(float(splitted_line[1].split(":")[1]))
d['m_avg'].append(float(splitted_line[2].split(":")[1]))
P.S. Never use variable names equal to built-in words, like dict, list etc. It can cause MANY various errors!

How do I use a for loop to store function output in separate variables?

Suppose I have the following function:
def function3(start, end):
"""Read MO information."""
config_found = False
var = []
for line in v['molecular orbital primitive coefficients']:
if line.strip() == end:
config_found = False
elif config_found:
i = line.rstrip()
var.append(i)
elif line.strip() == start:
config_found = True
var1 = [elem.strip() for elem in var]
var2 = var1[1:-1]
var3 = np.array([line.split() for line in var2])
var3 = np.asarray([list(map(float, item)) for item in var3])
return var3
And suppose I store its output in variables like so:
monumber1=function3('1','2')
monumber2=function3('2','3')
monumber3=function3('3','4')
etc.
Is there a way for me to execute this function a set number of times and store the output in a set number of variables without manually setting the variable name and function arguments every time? Maybe using a for loop? This is my attempt, but I'm struggling to make it functional:
for i in xrange(70):
monumber[x] = function3([i],[i+1])
Thank you!
The problem is your use of square brackets. Here is code that should work:
monumber = [] # make it an empty list
for i in xrange(70):
monumber.append(function3(str(i),str(i+1))) # you had string integers, so cast
For the more Pythonic one-liner, you can use a list comprehension:
monumber = [function3(str(i),str(i+1)) for i in xrange(70)]
Now that the monumber variable has been created, I can access the element at any given index i using the syntax monumber[i]. Some examples:
first = monumber[0] # gets the first element of monumber
last = monumber[-1] # gets the last index of monumber
for i in xrange(10,20): # starts at i = 10 and ends at i = 19
print(monumber[i]) # print the i-th element of monumber
You've almost got it. Except you should use i on the left hand side, too:
monumber[i] = function3([i],[i+1])
Now, this is the basic idea, but the code will only work if monumber is already a list with enough elements, otherwise an IndexError will occur.
Instead of creating a list and filling it with placeholders in advance, we can dynamically append new values to it:
monumber = []
for i in xrange(70):
monumber.append(function3([i],[i+1]))
Another problem is that you seem to be confusing different types of arguments that your function works with. In the function body, it looks like start and end are strings, but in your code, you give to lists with one integer each. Without changing the function, you can do:
monumber = []
for i in xrange(70):
monumber.append(function3(str(i),str(i+1)))

Returning two dictionaries, using each one in separate functions

def make(node): # takes some input
for reg_names in reg.names # dont worry about reg_names and reg.names
if reg.size > 0: #reg.size is an inbuilt function
found_dict = {} # first dictionary
found_dict['reg.name'] = 'reg.size' # i want to save the name of the register : size of the register in the format name : size
else:
not_found_dict = {}
not_found_dict['reg.name'] = 'reg.size' #again, i want to save the name of the register : size of the register in the format name : size
return found_dict, not_found_dict
Ok, so can you tell me whether from the for loop above, if the constructs for creating the dictionaries (found_dict and not_found_dict) are correct assuming reg.name and reg.size are valid constructs?
I then want to use found_dict in function_one and not_found_dict in function_two like below:
def function_one(input): # should this input be the function 'make' as I only want found_dict?
for name, size in found_dict.items(): #just for the names in found_dict
name_pulled = found_dict['reg.name'] # save the names temporarily to name_pulled using the key reg.name of found_dict
final_names[] = final_names.append(name_pulled) #save names from name_pulled into the list final_names and append them through the for loop. will this work?
def function_two(input): # i need not_found_dict so what should this input be?
for name, size in not_found_dict.items(): #using the names in not_found_dict
discard_name_pulled = not_found_dict['reg.name'] # save the names temporarily to discard_name_pulled using on the 'reg.name' from not_found_dict which is essentially the key to the dict
not_used_names[] = not_used_names.append(discard_name_pulled) # in the same way in function_one, save the names to the list not_used_names and append them through the for loop. Will this construct work?
Main question is, since def make is returning two dictionaries (found_dict and not_found_dict) how do I correctly input found_dict in function_one and not_found_dict in function_two?
First of all in your first section in the for loop every time you do :found_dict = {} or not_found_dict = {} you are clearing the contents of the dictionary. I'm not sure if this is what you want.
Second if you want to return more than one thing from a function you could always return them as an array or a tuple, something like this:
return [found_dict, not_found_dict]
Look at this question for more information.
After you return your array or tuple you can then store it in another variable like this:
result=make(inputVariable)
this will let you use each element as you want.
result[0]
result[1]
you can input them into the functions you want like this:
def function_one(inputParameter, found_dict):
#code ....
def function_one(inputParameter, not_found_dict):
#code ....
function_one(inputVariable, result[0])
function_two(inputVariable, result[1])

Categories