Retrieving information from dictionary - python

I'm having hard time trying to read my dictionary variable. Python keeps throwing the following error:
TypeError: string indices must be integers
This is a sample that should give you an idea of what my problem is:
self.dict = {}
self.dict['User'] = 'User_name'
self.dict['Dir'] = 'user_home_dir'
self.dict['userID'] = 1
if self.dict['userID'] == 1: # this is the line that is said to contain an error
then do somethin ...
This is all I get as a Traceback:
user_id = self.dict['userID']
TypeError: string indices must be integers
No I'm positive that self.dict is not a string.
It's being created in a function called createUser and it's being returned to the main thread.
def createUser(self):
self.dict = {}
... user inputs information ...
... and then information is inserted into self.dict ...
self.dict['User'] = self.lineEdit_User.text()
self.dict['Dir'] = self.lineEdit_path.text()
self.dict['userID'] = int(self.lineEdit_ID.text())
return self.dict
After that self.dict is only referenced for reading data from it.

I've found the problem, and it was in my signal definition. Dictionary 'self.dict' is being returned via pyqtSignal which was defined like this:
addUser = pyqtSignal(object)
After thorough examination of my code I've figured out that I should change it to:
addUser = pyqtSignal(dict)
and once I did that it was all right. Once again, thanks everyone for their contribution.

Related

How to extract data one by one from the array in a simple way and pass it to the constructor

I am new to python, here is the first part of my graduation project. I want to extract data from MySql 'insert' statements
if tableName == 'accounts':
a = Account(rm_apostrophe(slippedMsgs[0]), rm_apostrophe(slippedMsgs[1]),
rm_apostrophe(slippedMsgs[2]))
print(a.account_id, a.account_name, a.customer_code)
Accounts.append(a)
In the code above, Account is a class used to save data, rm_apostrophe is a method for handle strings.
class Account:
def __init__(self, account_id, account_name, customer_code):
self.account_id = account_id
self.account_name = account_name
self.customer_code = customer_code
def rm_apostrophe(raw_data):
if raw_data is None or raw_data == "Null":
return None
elif raw_data.startswith("'"):
return raw_data[1:-1]
else:
return raw_data
Account is a simple method with only three attributes, so there is no problem with writing this way.
But I have another class named Ticket with 73 attributes, which means that I have to do rm_apostrophe(slippedMsgs[x]) 73 times in
t = Ticket(rm_apostrophe(slippedMsgs[0]), rm_apostrophe(slippedMsgs[1]),
rm_apostrophe(slippedMsgs[2])...etc)
I guess there should be an easier way to help me pass in these parameters, maybe I need to modify the constructor. Hope someone can help me, thank you very much
You can use a list comprehension to create the list of arguments:
args = [rm_apostrophe(x) for x in slippedMsgs]
Then you can pass these arguments using t = Ticket(*args)
The * before the args passes every item in the list as an argument to Ticket

TypeError: Error while checking if the values in a list existed in a dict

I have a code as follows:
class SifFile():
setting = {}
interesting_param = ['Temp', 'Pressure']
def __init__(self, get_param):
self.File_Type = "Andor Technology Multi-Channel File"
for k, v in get_param.items():
if SifFile.interesting_param in k:
SifFile.setting[k] = v
return SifFile.setting
get_parameter = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile(get_parameter)
There is a big dict named get_parameter that has a few parameters and their values.
There is also a list named interesting_param that contains 2 elements.
What I want to do is to check which parameters from interesting_param list are present in the get_parameter dictionary and I want to save those parameters in an empty dict named setting
I tried running the above code, but it gives me the following error:
Traceback (most recent call last):
File "", line 16, in
sif = SifFile(get_parameter)
File "", line 8, in init
if SifFile.interesting_param in k:
TypeError: 'in ' requires string as left operand, not list
Expected output:
setting = {'Temp':75, 'Pressure':50}
Here is the code that will give you the expected answer:
class SifFile():
setting = {}
interesting_param = ['Temp', 'Pressure']
def __init__(self):
self.File_Type = "Andor Technology Multi-Channel File"
return
def func(self, get_param):
for k, v in get_param.items():
if k in SifFile.interesting_param:
SifFile.setting[k] = v
return SifFile.setting
get_parameter = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile()
x=sif.func(get_parameter)
print(x)
I have created anothter funcion called "func" because "init()" cannot return a dictionary. It should only return "None".
Besides that, the condition statement within the for loop is changed.
The error is telling you what's wrong: you are trying to check if a key exists in a dict but the key that you're checking for isn't a string. Let's look at the line in question:
if SifFile.interesting_param in k:
The error thinks that SifFile.interesting_param is a list, so let's have a look at where you define that:
interesting_param = ['Temp', 'Pressure']
Oh yeah, that is a list. Since a list can't be a dict key it throws an error.
You need to loop through your items in interesting_param one by one to check whether they're in the dict. I've implemented that here, along with a range of other issues in your code, mainly surrounding how you'd implemented the class:
class SifFile():
"""
Class for holding and processing sif files.
"""
def __init__(self, params):
"""
Define the variables you want to use in your class
"""
self.file_type = "Andor Technology Multi-Channel File"
self.interesting_params = ['Temp', 'Pressure']
self.given_params = params
self.setting = {}
def get_settings(self):
"""
Return list of settings of interest
"""
# Look at every parameter of interest in turn
for param in self.interesting_params:
# Check to see if it is in the dict of given parameters
if param in self.given_params:
# If it is then add it to the setting dict
self.setting[param] = self.given_params[param]
# Return the setting dict once the loop is done
return self.setting
parameters = {'Temp':75, 'Pressure':50, 'Helium':90, 'Exp':96}
sif = SifFile(parameters)
print(sif.get_settings())
Note that your variables are now all instance variables rather than class variables (they start with self) because you're changing them, so they are unlikely to be the same for every class.

Python issues with objects inside of dictionary? Cant get all data back out

Sorry this is the second post in two days.. I am pulling my hair out with this. I am attempting to take data from reddit and put it into an array in a way I can pull the data out later for tensorflow to parse it. Now the issue is my second object inside of the other object is not giving me whats inside it... "<main.Submission" why am I getting this back?
Goals of this post:
1: Why am I getting <main.Submission> and how should I be doing this.
File "C:/automation/git/tensorflow/untitled0.py", line 35, in <module>
submissions[sm.id].addSubSubmission(Submission.addComment(cmt.id, cmt.author.name, cmt.body))
TypeError: addComment() missing 1 required positional argument: 'body'
Sorry for the long winded and most likely basic questions. Going from powershell to python was not as straight forward as I thought..
Thanks
Cody
import praw
# sets log in data for session
reddit = praw.Reddit(client_id='bY',
client_secret='v9',
user_agent='android:com.example.myredditapp:'
'v1.2.3 (by /u/r)')
class Submission(object):
def __init__(self, id, title, author):
self.id = id
self.title = title
self.subSubmission = {}
self.author = author
def addComment(self, id, author, body):
self.id = id
self.author = author
self.body = body
def addSubSubmission(self,submission):
self.subSubmission[submission,id] = submission
def getSubSubmission(self,id):
return self.subSubmission[id]
submissions = {}
for sm in reddit.subreddit('redditdev').hot(limit=2):
# pulls the ID and makes that the head of each
submissions[sm.id] = Submission(sm.id, sm.title, sm.author.name)
mySubmission = reddit.submission(id=sm.id)
mySubmission.comments.replace_more(limit=0)
# Get all the comments and first post and list their id author and body(comment)
for cmt in mySubmission.comments.list():
submissions[sm.id].addSubSubmission(Submission.addComment(cmt.id, cmt.author.name, cmt.body))
# My trying to read what all there??!? ##
for key in submissions.keys():
value = submissions[key]
print(key, "=", value)
for key, value in submissions.items():
print(key, "=", value)
expecting to see:
{Title = test {comment.id = 1111 {Comment = 'blah', Author = 'Bob'}}
{comment.id = 1112 {Comment = 'blah2', Author = 'Bob2'}}
}
It is giving you back the entire Submission object - but then you're printing it. How should a submission object look on screen when printed? This is something you can define in the Submission class - check out the first answer in this post: Difference between __str__ and __repr__ in Python
To explain this further: python doesn't know how to represent a class on screen. Sure, the class has attributes that are strings, lists, dicts etc, but python knows how to print those. Your class you just created? What's important? What should be printed? python doesn't know this, and is smart enough not to make any assumptions.
If you add a __repr__ function to your class, python will call it and print whatever that function returns.

Appending objects to a global list in python

I am trying to get the user to make an object called a NoteSet, each NoteSet will be put into a global list called db. This is my attempt at making this:
import sys
import datetime
db = list()
class NoteSet:
nextseqNum = 0
def __init__(self,name,description,hidden):
global db
self.seqNum = Note.nextseqNum
self.name = name
self.description = description
self.dateCreated = datetime.date.today()
self.hidden = hidden
self.notes = list()
db[self.seqNum] = self
print(self)
print(len(db))
Note.nextseqNum += 1
When I try to create an object for example:
NoteSet('example','ex',True)
It gives me the error
Traceback (most recent call last):
File "", line 1, in
NoteSet('example','ex',True)
File "C:\Users\Brandon\Desktop\step5.py", line 22, in init
db[self.seqNum] = self
IndexError: list assignment index out of range
Is this the right way to make a global list of objects?
As #aruisdante said you will need to append to the list
Try this:
db = []
class ListObj:
def __init__(self, name, msg, hide=False):
self.name = name
self.msg = msg
self.hide = hide
db.append(self)
Good Luck!
You get this error because db has no elements in it (python lists are initialized to length 0), so when you try and replace the element at location self.seqNum, you are acessing an invalid index. It has nothing to do with the global-ness of it.
If we assume that this global list is only ever going to be accessed in a thread-safe manner, you should simply be able to do:
db.appened(self)
Instead. However, as mentioned in the comments, it makes more sense in this use case to make db a class variable if this class is the 'gate keeper' to interfacing with the db list.
UPDATE
To address the OP's question in the comments,
I am looking to be able to keep track of the location of the objects in the list by the seqNum
As currently written, seqNum will always increment linearly, forever, with each new NoteSet instance. If we assume thread-safe access of Note.nextseqNum, then what you're trying to do via db[self.seqNum] is already implicitly done via db.append(self), because len(db) == Note.nextseqNum, always. For now, we're going to ignore what happens if you cand remove elements from db, because right now your system doesn't account for that at all and would completely break anyway.
If, however, in the future seqNum doesn't just increase monotonically forever each time you make a new instance, you can simply make db a dict instead of a list:
db = dict()
And then insert the new instance to it exactly as you are currently,
db[self.seqNum] = self
db now represents a mapping of a seqNum to a NoteSet explicitly, rather than an implicit relationship based on an array index.
I would actually recommend doing it this way anyway, as it will also solve the problem of removing items from db for 'free'. As is, doing del db[instance.seqNum] will completely invalidate all mappings of seqNum into db for any instance that came after the removed instance. But if db is a dict, then this operation does what you expect it to and all of the seqNum values still map to the correct instance in db.
So, to bring it all together, I would recommend you alter your class to look like the following:
import sys
import datetime
class NoteSet:
nextseqNum = 0
db = dict()
def __init__(self,name,description,hidden):
self.seqNum = NoteSet.nextseqNum
self.name = name
self.description = description
self.dateCreated = datetime.date.today()
self.hidden = hidden
self.notes = list()
NoteSet.db[self.seqNum] = self
print(self)
print(len(db))
NoteSet.nextseqNum += 1

Error with converting list item to integer

I am trying to pass class element to method. Element is formed dynamically inserting current time in it. Mine class looks something like this:
class MineContact(dict):
def __init__(self, **kwargs):
# set your default values
import time
curr_time = repr(time.time()).replace('.', '')
self['tel'] = [{
'type': ['Mobile'],
'value': '555%s' % curr_time[8:]}]
...
So, I create object of this class and now I want to insert it as method argument:
contact = MineContact()
extra_text = "-%d" % (self.iteration)
new_contact.insert_phone(contact.tel['value'])
When I run this script, I get this type of error:
TypeError: list indices must be integers, not str
So, does anyone knows where am I getting it wrong?
You have a list of one dictionary [{}] instead of {}. The following will work:
contact = MineContact()
extra_text = "-%d" % (self.iteration)
new_contact.insert_phone(contact.tel[0]['value'])
Alternatively, you could change your self['tel'] to a dictionary instead of a list of a dictionary. Here is what it would look like:
self['tel'] = {'type': ['Mobile'], 'value': '555%s' % curr_time[8:]}
Then, your original new_contact.insert_phone(contact.tel['value']) would work

Categories

Resources