Python is not calling this function and I cannot find out why - python

Trying to make this code work and it's not calling my 'makeDictionary' function in my class. I cannot figure out why. Any thoughts?
from StringCount import *
def main():
products = StringCount()
doc = input("Enter File Location: ")
doc_object = open(doc, "r").read()
items = doc_object.split()
products.makeDictionary(items)
itemList = products.sortItems()
print(f"{'Product':^15}{'Quantity':^10}")
print("-" * 25)
for p in range(len(itemList)):
item, count = itemList[p]
print(f"{item:<15}{count:>10}")
if __name__ == "__main__":
main()
Edit: Sorry for the garbage post, I'm still trying to figure it all out. Here is my class code.
from operator import itemgetter
class StringCount:
def __init__(self):
self.notes = {}
self.key = []
self.value = []
def makeDictionary(self, items):
for item in items:
item.strip('')
if item == int:
self.value.append(item)
if item == str:
self.key.append(item)
for i in range(len(self.key) and len(self.value)):
self.notes[self.key[i]] = self.value[i]
EDIT #2: Okay, so to clarify my issue. I'm not looking for clarification on the class. Running this program in python I enter the file location, and it skips over the 'makeDictionary' method entirely. Now I just don't see why and I am sure there is a small reason. If anyone can help out that would be appreciated.

As #jasonharper points out,
if item == int:
Won't work. Instead use
if isinstance(item, int):
Same thing for str

Related

Call a function without really calling the function?

I know my question sounds weird, but I am searching for this but I can't find it nowhere. I want to simulate a TableScan statement from SQL with printing out a list of lists, so I call the method next() with the object 'x' as long as ("EOF" of list) is not returned. But if I write
while(x.next() != "EOF"): the function next() is already called once and this not what I want, because I skip already one tuple.
Here the code:
class TableScan(Iterator):
def __init__(self, collection):
super().__init__()
self.collection = collection
self.iter = None
def open(self):
self.iter = iter(self.collection)
def next(self):
try:
while(self.iter != None):
return next(self.iter)
except StopIteration:
return "EOF"
# The list.
cS = [[101,2,3,5,1],
[202,4,99,2,4],
[303,2,4,6,8],
[404,1,23,4,6],
[505,2,22,4,5]]
# Making object x and calling constructor of class TableScan.
x = TableScan(cS)
while(x.next() != "EOF"): ###Problem- lines###
print(x.next())
Can somebody please help me?
Assign the result to a variable so you can test it and print it.
while True:
n = x.next()
if n == 'EOF':
break
print(n)
i know this has an answer, but in python 3.8 and above you can do:
while (n := x.next()) != 'EOF':
print(n)

Tkinter: How to put user input into a list to access later?

When I try to access the list produced by the function stringToList, it always says TypeError: 'NoneType' object is not subscriptable.
class MyApp(Tk):
def __init__(self):
super().__init__()
# Many widgets defined and placed here
def my_fx(self):
def stringToList(input_str):
number_list = []
full_list = []
if list(input_str)[-1].isnumeric:
input_str += ","
for item in list(input_str):
if item.isnumeric():
number_list.append(item)
if not item.isnumeric():
num_str = ""
for item in number_list:
num_str += item
if int(num_str) not in full_list:
try:
full_list.append(int(num_str))
except ValueError:
pass
number_list = []
sorted_list = sorted(full_list).append(some_string)
return sorted_list
if True:
sorted_list = stringToList(some_entry_widget.get())
def do_stuff():
from my_other_file import my_other_fx
this_and_that = my_other_fx(sorted_list)
# More functions defined here
if __name__ == '__main__':
app = IntegratorApp()
app.mainloop()
This line in my_other_fx (which is properly named in my original code) is where I get the NoneType is not subscriptable error:
if sorted_list[-1] == some_value:
I've tried reworking stringToList so it uses IntVar and StringVar instead of regular int and str, but that didn't change anything. Why is it NoneType?
Also if anyone has other critique, it's more than welcome! I'm trying to learn!
EDIT: It seems to go "nope" and turn into NoneType when I try to append a string to the list. But why??
Try this:
full_list.append(some_string)
sorted_list = sorted(full_list)

Sorting List of Objects python. Objects are of different class than the one I'm sorting in

I've seen similar questions but I just can't seem to figure this out. I have two classes, my Item class, and then my Receipt class. In Receipt I have a method read_file that reads a .txt file line by line, splitting it. I then append an Item object onto my list such that I have a list of Item objects. I'm trying to sort this list by price but I keep getting "AttributeError: type object 'Item' has no attribute 'price'" I've tried a few different things, and looked at similar answers on StackOverflow but I just can't seem to figure it out. From what I understand it's because it's looking at the class instead of the instance? Any help is appreciated, thank you.
The actual error is as follows:
Error message : items.sort(key=operator.attrgetter('price'),reverse=False)
AttributeError: type object 'Item' has no attribute 'price'
And my code:
import operator
import sys
class Item(object):
def __init__(self, category, name, quantity, price):
self.category = category
self.name = name
self.quantity = quantity
self.price = price
def getPrice(self):
return self.price;
class Receipt(object):
def __init__(self):
pass
def read_file(self):
with open('grocery.txt') as file:
items = [Item]
for line in file:
c,n,q,p = line.rstrip('\n').split(" ")
items.append(Item(c,n,q,float(p)))
return items
def ask_receipt_format(self):
answer = input("How would you like this receipt printed? (P for by price, C for by category, A for alphabetical order)")
if answer.capitalize() == 'P':
answer = 'P'
elif answer.capitalize() == 'C':
answer = 'C'
elif answer.capitalize() == 'A':
answer = 'A'
else:
print("You must choose a valid receipt format!\n")
self.ask_receipt_format()
return answer
def calculate_total(self):
pass
def print_bill(self, receipt_format,items):
if receipt_format == 'P':
print("Receipt by price")
print("Category Item Quantity Price Sub-Total")
items.sort(key=operator.attrgetter('price'),reverse=False)
for n in range(len(items)):
print("{:d} {0:4} {:d} {:4d} {:5d}".format(items[n].category,items[n].name,items[n].quantity,items[n].price, float(items[n].quantity) * float(items[n].price)))
def API(self):
self.print_bill(self.ask_receipt_format(),self.read_file())
def main():
receipt = Receipt()
receipt.API()
if __name__ == "__main__":
main()
Looking at this following snippet:
def read_file(self):
with open('grocery.txt') as file:
items = [Item]
The first thing you put in the list is the class itself, which doesn’t have the attribute price. Attributes are only passed on within instances of the class. Instead, you want to declare the list as empty: items = [].

Program error in text prediction algorithm in Python 2.7

I came across the following code from this question :
from collections import defaultdict
import random
class Markov:
memory = defaultdict(list)
separator = ' '
def learn(self, txt):
for part in self.breakText(txt):
key = part[0]
value = part[1]
self.memory[key].append(value)
def ask(self, seed):
ret = []
if not seed:
seed = self.getInitial()
while True:
link = self.step(seed)
if link is None:
break
ret.append(link[0])
seed = link[1]
return self.separator.join(ret)
def breakText(self, txt):
#our very own (ε,ε)
prev = self.getInitial()
for word in txt.split(self.separator):
yield prev, word
prev = (prev[1], word)
#end-of-sentence, prev->ε
yield (prev, '')
def step(self, state):
choice = random.choice(self.memory[state] or [''])
if not choice:
return None
nextState = (state[1], choice)
return choice, nextState
def getInitial(self):
return ('', '')
When i ran the code on my system the example didn't work.
When i ran the bob.ask() line i got an error saying ask() required 2 parameters whereas it got just one. Also when i ran the bob.ask("Mary had") part i got ' ' as the output.
P.S I ran the the code exactly as told in the answer.
Could anyone help? Thanks!
I think you're right. It doesn't work because ask expects an argument (seed), as defined by
def ask(self, seed):
This line
if not seed:
seed = self.getInitial()
suggests that you can fix the issue by setting a default argument for seed. Try this:
def ask(self, seed=False):
which works for me.

Making a database with custom commands in python

I'm trying to make a simple, local database using Python where I can set values, get values, etc and I keep getting this error:
#Simple Database
#Functions include Set[name][value]
# Get[name]
# Unset[name]
# Numequalto[value]
# End
# Begin, Rollback, Commit
varlist = []
ops = []
class item:
def __init__(self,name,value):
self.name = name
self.value = value
class db:
def __init__(self):
self.varlist = []
self.ops = []
def Set(self,nm,val):
changed = False #Bool for keeping track of update
for item in varlist: #run through current list
if item.name == nm: #If the name is found
item.value = val #update the value
changed = True #found it
break #exit if found
if not changed:
newitem = item() #Create a new one and append it
newitem.name = nm
newitem.value = val
varlist.append(newitem)
def Get(key):
for item in varlist:
if item.name == key:
return item.value
break
def Unset(key):
for item in varlist:
if item.name == key:
item.value = -1
break
def Numequalto(key):
count = 0
for item in varlist:
if item.value == key:
count+=1
return count
def main():
newdb = db()
varlist=[]
comm = "" #prime it
while comm.lower() != "end":
comm = input("Command: ")
if comm.lower() == "begin":
print("----SESSION START---")
while comm.lower() != "end":
comm = input("Command: ")
part = []
for word in comm.split():
part.append(word.lower())
print(part)
if part[0].lower()=="set":
newdb.Set(part[1],part[2])
print(varlist)
elif part[0].lower()=="get":
gotten = Get(part[1])
print(gotten)
elif part[0].lower()=="unset":
Unset(part[1])
elif part[0].lower()=="numequalto":
numequal = Numequalto(part[1])
print(numequal)
print("Finished")
else:
print("--ERROR: Must BEGIN--")
if __name__ == "__main__":
main()
When I run this, and try to create a new item in my list using the command
set a 25
I get this error:
Traceback (most recent call last):
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 81, in <module>
main()
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 65, in main
newdb.Set(part[1],part[2])
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 27, in Set
newitem = item() #Create a new one and append it
UnboundLocalError: local variable 'item' referenced before assignment
Any help would be much appreciated. I'm pretty new to Python
The line
for item in varlist:
shadows the class item with a local variable. So that when you get to your item() it thinks you are trying to call the local variable instead of the class. You can tell that your class item is never being constructed because it would fail as you are passing no parameters to the __init__
Also you should really call your class Item. Once I did that I got the constructor error as expected.
You have a few issues with your code:
You are shadowing the class item with a local variable of the same name.
You are using varlist instead of self.varlist.
Some of your class methods doesn't recieve a self first argument.
Also there is a strong convention in python to name classes with a first capital letter.
Not trying to be implite, just constructive here. I'm concerned that while there are comments questioning the intent to implement your own dictionary, no answer stated this forcefully. I say this only because part of Python (beyond the semantics, language, etc...) is the culture. We speak of things being 'Pythonic' for a reason - part of the value of this language is the culture. There are two aspects here to pay attention to - first, 'Batteries Included' and second, "Don't Reinvent the Wheel". You're reimplimenting the most fundamental composite (oxymoron, I know) data type in Python.
>>> a = {}
>>> a['bob'] = 1
>>> a['frank'] = 2
>>> a
{'frank': 2, 'bob': 1}
>>> del a['frank']
>>> a
{'bob': 1}
>>> del a['bob']
>>> a
{}
>>> a['george'] = 2
>>> b = len([x for x in a.values() if x == 2])
>>> b
1
And there you have it - the pythonic way of handling the functionality you're after.
If you're trying to add functionality or limitations beyond that, you're better off starting from the dict class and extending rather than rolling your own. Since Python is "duck-typed" there's a HUGE benefit to using the existing structure as your basis because it all falls into the same patterns.

Categories

Resources