I am trying to write a state machine whose inputs are the characters of a string (representing a
Python program) and which outputs either (a) the input character if it is part of a
comment or (b) None
but so far I have failed
I got the error TypeError: cannot unpack non-iterable NoneType object
def split(word):
return [char for char in word]
class SM:
def start(self):
self.state = self.startState
def sit(self,inp):
(s,o) = self.comments(inp,self.state)
self.state = s
return o
def transduce(self,input):
self.start()
return [self.sit(inp) for inp in input]
class commentSM(SM):
startState = ''
def showcom(self,list,val):
for char in list:
if list.find(char) < list.find(val):
return None
else:
return char
def comments(self,input,state):
if state == '':
return('commented',self.showcom(input,'#'))
input = '''print(hello) # comment'''
ninput = split(input)
m = commentSM()
print(m.transduce(ninput))
Related
I am writing code to insert words into a trie data structure and then search the words. I am getting invalid syntax error for line self = self.trieDict[word[0]] (3rd line in the insert function)
#Trie data structure
class TrieNode():
trieDict = {}
isComplete = False
def __init__(self, dic, isComplete):
self.trieDict = dic
self.isComplete = isComplete
#self is the root node
def insert(self, word):
while len(word) != 0 and self is not None:
if word[0] in self.trieDict:
self = self.trieDict[word[0]]
word = word[1:]
else:
child = self.TrieNode({}, False)
self.trieDict[word[0]] = child
self = child
word = word[1:]
self.isComplete = True
def search(self, word):
while len(word) != 0 and self is not None:
if word[0] in self.trieDict:
word = word[1:]
self = self.trieDict[word[0]]
else:
return False
return self.isComplete
When I copied the following line from your code
self = self.trieDict[word[0]]
an unrecognized symbol is right in front of the second self that is causing your syntax error. (It seems to be Unicode 0013) Simply delete it or rewrite the line on a new line and remove the offending line.
On a sidenote, assigning to self in a method is usually not a good idea as it points to the instance on which you are executing the method. While not syntactically incorrect, it will definitely cause confusion to the reader.
Here is the code after correction (for inserting nodes into a trie and searching nodes in the trie:
class TrieNode():
trieDict = {}
isComplete = False
def __init__(self, dic, isComplete):
self.trieDict = dic
self.isComplete = isComplete
#self is the root node
def insert(self, word):
current = self
while len(word) != 0 and current is not None:
if word[0] in current.trieDict:
current = current.trieDict[word[0]]
word = word[1:]
else:
child = TrieNode({}, False)
current.trieDict[word[0]] = child
current = child
word = word[1:]
current.isComplete = True
def search(self, word):
current = self
while len(word) != 0 and current is not None:
if word[0] in current.trieDict:
current = current.trieDict[word[0]]
word = word[1:]
else:
return False
return current.isComplete
def test():
node = TrieNode({}, False)
node.insert('cat')
node.insert('car')
node.insert('pod')
print(node.search('car'))
print(node.search('ccar'))
print(node.search('pod'))
print(node.search('pode'))
test()
I am coding a huffman coding tree in python, I have used one class for tree nodes, but I want the whole program to be object oriented. I just cant seem to be able to turn my functions into classes and run the whole thing as OOP. Is it possible to convert functions into classes/methods or does it involve rewriting the entire code in OOP style. The code works ok, im just trying to get my head around OOP and how to implement it. Any help would be great! Code below.
'''
import heapq
class TreeNode(object):
def __init__(self, freq, char=None, left=None, right=None):
self.char = char
self.freq = freq
self.left = left
self.right = right
def __lt__(self, other):
return self.freq < other.freq
def isLeaf(self):
return (self.left == None and self.right == None)
def createTree(freqData):
huffmanNodes = []
for char in freqData:
huffmanNodes.append(TreeNode(freqData[char], char))
heapq.heapify(huffmanNodes)
while (len(huffmanNodes) > 1):
# obtain the two minimum-frequency Huffman nodes
child1 = heapq.heappop(huffmanNodes)
child2 = heapq.heappop(huffmanNodes)
parent = TreeNode(child1.freq + child2.freq, left=child1, right=child2)
heapq.heappush(huffmanNodes, parent)
return None if huffmanNodes == [] else heapq.heappop(huffmanNodes)
def hTreeToHCode(hTree):
code = dict()
def getCode(hNode, curCode=""):
if (hNode == None): return
if (hNode.left == None and hNode.right == None):
code[hNode.char] = curCode
getCode(hNode.left, curCode + "0")
getCode(hNode.right, curCode + "1")
if hNode.char == None:
print("")
else:
print('Character = {} : Freq = {} --- Encoded into {}'.format(hNode.char, hNode.freq, curCode))
getCode(hTree)
return code
def encode(s, freqData):
hTree = createTree(freqData)
hCode = hTreeToHCode(hTree)
hEncoded = ""
for char in s:
hEncoded += hCode[char]
return hEncoded.strip()
def decode(s, freqData):
hTree = createTree(freqData)
decodedStr = ""
curTreeNode = hTree
for charCode in s:
if (charCode == "0"):
curTreeNode = curTreeNode.left
else:
curTreeNode = curTreeNode.right
if (curTreeNode.isLeaf()):
decodedStr += curTreeNode.char
curTreeNode = hTree
return decodedStr
words = "hello welcome to my huffman algorithm code"
charlst = {}
for char in words:
charlst[char] = charlst.get(char,0) + 1
freqData = charlst
encodedStr = encode(words, freqData)
print("encodedStr", encodedStr)
decodedStr = decode(encodedStr, freqData)
print("decodedStr", decodedStr)
'''
you can put function outside the NodeTree class in a Main class and add a run method with var initialisation etc and put at the end of your program a
if __name__=='__main__':
Main.run()
This is the most strange error that I got since I started to program with Python years ago.
First, theses are my classes (Sorry for the long code):
class Quran(Iterable):
def __init__(self):
self.sourats = []
def __iadd__(self, other):
# There is some code here
pass
def __getitem__(self, sourat_num):
if not (isinstance(sourat_num, int) or isinstance(sourat_num, slice)):
raise TypeError('Indexing Quran can be done only using ints or slices')
if isinstance(sourat_num, int):
sourat_num -= 1
else:
sourat_num = slice(sourat_num.start - 1, sourat_num.stop)
try:
return self.sourats[sourat_num]
except IndexError:
return None
def __len__(self):
return len(self.sourats)
# Other methods ...
class Sourat(Iterable):
sourats_titles = [ # 114 strs here
]
def __init__(self, number, quran):
if not isinstance(number, int):
raise TypeError('number must be int')
if not isinstance(quran, Quran):
raise TypeError('quran must be Quran')
self.num = number
self.ayats = []
self.quran = quran
def __int__(self):
return self.num
def __iadd__(self, other):
# Some code here
pass
def __getitem__(self, ayat_num):
if not (isinstance(ayat_num, int) or isinstance(ayat_num, slice)):
raise TypeError('Indexing Sourat can be done only using ints or slices')
if isinstance(ayat_num, int):
ayat_num -= 1
else:
ayat_num = slice(ayat_num.start-1, ayat_num.stop)
try:
return self.ayats[ayat_num]
except IndexError:
return None
def __len__(self):
return len(self.ayats)
def location(self):
return self.num
def previous(self):
p_num = self.num-1
if p_num < 1:
return None
return self.quran[p_num]
def next(self):
n_num = self.num+1
if n_num > len(self.quran):
return None
return self.quran[n_num]
# Other methods ...
class Word(Iterable):
def __init__(self, number, text, features, ayat):
if not isinstance(number, int):
raise TypeError('number must be int')
if not isinstance(text, str):
raise TypeError('text must be str')
if not (isinstance(features, dict) and features['type'] in ('PREFIX', 'STEM', 'SUFFIX')):
raise TypeError('features[type] must be one of PREFIX, STEM, SUFFIX')
if not isinstance(ayat, Ayat):
raise TypeError('ayat must be Ayat')
self.num = number
self.text = text
self.root = features.get('ROOT', None)
self.lem = features.get('LEM', None)
self.type = features['type']
self.next = None
self.previous = None
self.ayat = ayat
def __iadd__(self, other):
# Some code here
def __hash__(self):
# Some code here
pass
def previous(self):
p_num = self.num-1
if p_num < 1:
previous_ayat = self.ayat.previous()
if previous_ayat:
return previous_ayat[-1]
else:
return None
return self.ayat[p_num]
def next(self):
n_num = self.num+1
if n_num > len(self.ayat):
next_ayat = self.ayat.next()
if next_ayat:
return next_ayat[0]
else:
return None
return self.ayat[n_num]
# Other methods ...
And this is what I am have in the main code :
quran_last_14_sourats = parse_quranic_corpus('quranic-corpus-morphology-0.4-last-14-sourats.txt')
sourat = quran_last_14_sourats[2]
ayat = sourat[2]
word = ayat[1]
assert isinstance(ayat, Ayat)
assert isinstance(word, Word)
print(ayat.previous())
print(ayat)
print(ayat.next())
print(Word.next(word)) # This works !!!
print(word.next()) # This doesn't work !!!
My problem is in the next(self) and previous(self) in the class Word, everything else works perfectly.
When I try to use word.next() or word.previous(), it complains that NoneType is not callable. I tried to print(word.next) and it showed None, but this is not logical because these two methods are inside the class Word. This problem doesn't happen in classes Sourat and Ayat even that they have the same structure. And the most crazy thing is that Word.next(word) works without any problem !
Is this a bug in Python 3 ? (BTW I am using the latest version: 3.5.2)
Is this a bug in Python 3 ?
In a word, no.
Instance members and instance methods share the same namespace. Thus, your line in Word.__init__():
self.next = None
obliterates the reference to the method Word.next() inside the newly-allocated Word object.
I would like to write a class that will return true if and only if the expression entered contains only correctly matching delimiters such as " (), <>, [], {} " What I have written thus far will do exactly that.
delim_openers = '{([<'
delim_closers = '})]>'
def check_delimiters(expr):
val = Stack()
for c in expr:
if c == (any(x) for x in delim_openers):
val.push(c)
elif c == (any(y) for y in delim_closers):
try:
val.pop()
except:
return False
return val.empty()
I am a little confused however if I were test this case against specific cases such as the one below, it'll return true when I assumed it would return False, my stack shouldn't be popping the delimiter in this case. Test case:
from unittest import TestCase
tc = TestCase()
tc.assertFalse(check_delimiters('[ ( ] )'))
tc.assertFalse(check_delimiters('((((((( ))))))'))
How might I edit the `check_delimiters' method to correctly return False in these scenarios? The stacks first-in-last-out capability tends to confuse me. Also here's the stack class code in case anything else is confusing.
class Stack:
class Node:
def __init__(self, val, next=None):
self.val = val
self.next = next
def __init__(self):
self.top = None
def push(self, val):
self.top = Stack.Node(val, self.top)
def pop(self):
assert self.top, 'Stack is empty'
val = self.top.val
self.top = self.top.next
return val
def peek(self):
return self.top.val if self.top else None
def empty(self):
return self.top == None
def __bool__(self):
return not self.empty()
def __repr__(self):
if not self.top:
return ''
return '--> ' + ', '.join(str(x) for x in self)
def __iter__(self):
n = self.top
while n:
yield n.val
n = n.next
No need for any, a simple contains-check will suffice. Then you have to check whether the closer matches the opener, otherwise you are just checking whether closers and openers are equal in numbers and that the closers never take the lead count-wise:
class Stack(list):
push = list.append
def peek(self):
return self[-1] if self else None
# ...
match = dict(zip('{([<', '})]>')) # dict makes the matching check faster
delim_openers = set(match.keys()) # set makes the 'in' check faster
delim_closers = set(match.values())
def check_delimiters(expr):
val = Stack()
for c in expr:
if c in delim_openers:
val.push(c)
elif c in delim_closers:
try:
assert match[val.pop()] == c
# fails if stack is empty or brackets don't match
except:
return False
return not val
> check_delimiters('[ ( ] )')
False
> check_delimiters('[ ( ) ]')
True
So this character ▯ appears when I run my code which I think means there is a missing character therefor it can't be displayed. (Not sure correct me if I am wrong) And well basically I want to be able to get rid of that character. Here is what it looks like when I run my code:
However in the back-end in the idle when I click on one of the boxes for it to be displayed up top it doesn't register and looks like this in idle:
Why does it appear on screen if it isn't going to appear in idle?
Also how can I get rid of the ▯ character from the main screen?
Here is my full code.
Here are segments in which I think the problem lies. (However I have not been able to solve the problem)
My classes for Tree comparison to find the sentences and their frequent use:
class Branch():
def __init__(self, value):
self.left = None
self.right = None
self.value = value
self.frequency = 1
def incFreq(self):
self.frequency = self.frequency + 1
def freq(self):
return self.frequency
class Tree():
highest = []
def __init__(self):
self.root = None
self.found = False
def findHighest(self):
from operator import itemgetter, attrgetter
self.highest = []
self.inorder(self.root)
self.highest = sorted(self.highest, key=itemgetter(1), reverse=True)
return self.highest
#lessThan function needed to compare strings
def lessThan(self, a, b):
if len(a) < len(b):
loopCount = len(a)
else:
loopCount = len(b)
for pos in range(0, loopCount):
if a[pos] > b[pos]:
return False
return True
def outputTree(self):
self.inorder(self.root)
def insert(self, value):
#increment freq if already exists, else insert
if not self.exists(value):
self.root = self.insertAtBranch(self.root, value)
def exists(self, value):
#set the class variable found to False to assume it is not there
self.found = False
self.findAtBranch(self.root, value)
return self.found
#Used to fine a value in a tree
def findAtBranch(self, branch, value):
if branch == None:
pass
else:
#print ("[" + branch.value + "][" + value + "]") # Error checking
if branch.value == value:
self.found = True
#print("found " + value)
branch.incFreq()
#print(branch.freq())
else:
self.findAtBranch(branch.left, value)
self.findAtBranch(branch.right, value)
def insertAtBranch(self, branch, value):
if branch == None:
return Branch(value)
else:
if self.lessThan(branch.value, value):
branch.right = self.insertAtBranch(branch.right, value)
else:
branch.left = self.insertAtBranch(branch.left, value)
return branch
def inorder(self, branch):
if branch == None: return
self.highest.append((branch.value, branch.freq()))
#print (branch.value)
#print (branch.freq())
#print(self.highest[0])
self.inorder(branch.left)
self.inorder(branch.right)
This is where I use the tree and pass sentences to be used on a different function:
def getPhrases(self, numToReturn):
topPhrases = []
phrasesTree = Tree()
#load tree with phrases from phrase text file
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line)
#create a list of the top n of phrases to return
val = 0
for phrase in phrasesTree.findHighest():
if val < numToReturn:
topPhrases.append(phrase)
val = val + 1
return topPhrases
This is where I use the sentences to be able to display them on the screen:
def createPhrases(self):
print("createPhrases")
self.deletePanes()
self.show_keyboard = False
self.show_words = False
self.show_phrases = True
self.show_terminal = True
words = self.getPhrases(10)
for word, count in words:
self.addPane("{}".format(word, count), WORDS)
self.addPane("Boxes", PHRASE)
self.addPane("Keyboard", PHRASE)
self.addPane("OK", PHRASE)
self.drawPanes()
When you read lines from file, newline characters are at the end. pygame's documentation states that:
The text can only be a single line: newline characters are not rendered.
So, you should change this fragment:
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line)
to this:
file = open('setPhrases.txt', 'r')
for line in file:
phrasesTree.insert(line.strip())