Fixing Python Code - python

I'm trying to implement an iterator class named CharCounter. This class opens a textfile and provides an iterator that returns words from the text file containing a user specified number of characters. It should output a word per line. Which is not what's it's doing, it's outputting the words as a list and then it continuously outputs 'a'. How can I fix my code?
class CharCounter(object):
def __init__(self, fileNm, strlen):
self._fileNm = fileNm
self._strlen = strlen
fw = open(fileNm)
text = fw.read()
lines = text.split("\n")
words = []
pwords =[]
for each in lines:
words += each.split(" ")
chkEnd = ["'",'"',",",".",")","("]
if words[-1] in chkEnd:
words = words.rstrip()
for each in words:
if len(each) == strlen:
pwords.append(each)
print(pwords)
def __iter__(self):
return CharCounterIterator(self._fileNm)
class CharCounterIterator(object):
def __init__(self,fileNm):
self._fileNm = fileNm
self._index = 0
def __iter__(self):
return self
def next(self):
try:
ret = self._fileNm[self._index]
return ret
except IndexError:
raise StopIteration
if __name__=="__main__":
for word in CharCounter('agency.txt',11):
print "%s" %word

Code posted on SO should not read a file unless the question is about reading files. The result cannot be duplicated and verified. (See MCVE.) Instead, define a text string as a stand-in for the file.
Your code prints the words of length n as a list because that is what you ask it to do with print(pwords). It repeatedly prints the first char of the filename because that is what you ask it to do in the __next__ method.
Your class __init__ does more than you describe. The attempt to strip punctuation from words does not do anything. The code below defines a class that turns a text into a list of stripped words (with duplicates). It also defines a parameterized generator method that filters the word list.
class Words:
def __init__(self, text):
self.words = words = []
for line in text.split('\n'):
for word in line.split():
words.append(word.strip(""",'."?!()[]{}*$#"""))
def iter_n(self, n):
for word in self.words:
if len(word) == n:
yield word
# Test
text = """
It should output a word per line.
Which is not what's it's doing!
(It outputs the words as a [list] and then continuously outputs 'a'.)
How can I fix my #*!code?
"""
words = Words(text)
for word in words.iter_n(5):
print(word)
# Prints
Which
doing
words

Related

why can't I get this code to run I keep getting type error: 'Method' object is not subscriptable [duplicate]

This question already has an answer here:
TypeError : 'method' object is not subscriptable
(1 answer)
Closed 1 year ago.
I keep getting error codes on this code and I do not know why.... it keeps telling me method object is not subscriptable no matter what I do.. Any help is appreciated. I also know my code might not be pretty. I'm still just learning Python. Literally almost anything I do I'm getting an error code and I don't know how to fix it. Ive tried almost everything I can think of.
import string
def load_words(file_name):
'''
file_name (string): the name of the file containing
the list of words to load
Returns: a list of valid words. Words are strings of lowercase letters.
Depending on the size of the word list, this function may
take a while to finish.
'''
print('Loading word list from file...')
file = open(file_name, 'r')
line = file.readline()
word_list = line.split()
print(' ', len(word_list), 'words loaded.') #word_list is the list of valid words
file.close()
return word_list
def is_word(word_list, word):
'''
Determines if word is a valid word, ignoring
capitalization and punctuation (" !##$%^&*()-_+={}[]|\:;'<>?,./\"")
word_list (list): list of words in the dictionary.
word (string): a possible word.
Returns: True if word is in word_list, False otherwise
Example:
>>> is_word(word_list, 'bat') returns
True
>>> is_word(word_list, 'asdf') returns
False
'''
word = word.lower
word = word.strip("!##$%^&*()-_+={}[]|\:;'<>?,./\"")
return word in word_list
def get_story_string():
"""
Returns: a joke in encrypted text.
"""
f = open("story.txt", "r")
story = str(f.read())
f.close()
return story
WORDLIST_FILENAME = 'words.txt'
class Message(object):
def __init__(self, text):
'''
Initializes a Message object
text (string): the message's text
a Message object has two attributes:
self.message_text (string, determined by input text)
self.valid_words (list, determined using helper function load_words
'''
self.message_text = text
self.valid_words = load_words(WORDLIST_FILENAME)
def get_message_text(self):
'''
Used to safely access self.message_text outside of the class
Returns: self.message_text
'''
return self.message_text
def get_valid_words(self):
'''
Used to safely access a copy of self.valid_words outside of the class
Returns: a COPY of self.valid_words
'''
return self.get_valid_words[:]
def build_shift_dict(self, shift):
'''
Creates a dictionary that can be used to apply a cipher to a letter.
The dictionary maps every uppercase and lowercase letter to a
character shifted down the alphabet by the input shift. The dictionary
should have 52 keys of all the uppercase letters and all the lowercase
letters only.
shift (integer): the amount by which to shift every letter of the
alphabet. 0 <= shift < 26
Returns: a dictionary mapping a letter (string) to
another letter (string).
'''
lower = list(string.ascii_lowercase)
lower_values = list(string.ascii_lowercase)
shift_lower_values = lower_values[shift:] + lower_values[:shift]
upper = list(string.ascii_uppercase)
upper_values = list(string.ascii_uppercase)
upper_shift_values = upper_values[shift:] + upper_values[:shift]
full_keys = lower + upper
full_values = shift_lower_values + upper_shift_values
self.shift_dict = dict(zip(full_keys, full_values))
return self.shift_dict
def apply_shift(self, shift):
'''
Applies the Caesar Cipher to self.message_text with the input shift.
Creates a new string that is self.message_text shifted down the
alphabet by some number of characters determined by the input shift
shift (integer): the shift with which to encrypt the message.
0 <= shift < 26
Returns: the message text (string) in which every character is shifted
down the alphabet by the input shift
'''
message = self.get_message_text()
new_string = ""
shiftDictonary = self.build_shift_dict(shift)
for letter in message:
if letter in shiftDictonary:
new_string += shiftDictonary[letter]
else:
new_string += letter
return new_string
class PlaintextMessage(Message):
def __init__(self, text, shift):
'''
Initializes a PlaintextMessage object
text (string): the message's text
shift (integer): the shift associated with this message
A PlaintextMessage object inherits from Message and has five attributes:
self.message_text (string, determined by input text)
self.valid_words (list, determined using helper function load_words)
self.shift (integer, determined by input shift)
self.encrypting_dict (dictionary, built using shift)
self.message_text_encrypted (string, created using shift)
Hint: consider using the parent class constructor so less
code is repeated
'''
Message.__init__(self, text)
self.shift = shift
self.encrypting_dict = self.build_shift_dict(shift)
self.message_text_encrypted = self.apply_shift(shift)
def get_shift(self):
'''
Used to safely access self.shift outside of the class
Returns: self.shift
'''
return self.shift
def get_encrypting_dict(self):
'''
Used to safely access a copy self.encrypting_dict outside of the class
Returns: a COPY of self.encrypting_dict
'''
return self.encrypting_dict.copy()
def get_message_text_encrypted(self):
'''
Used to safely access self.message_text_encrypted outside of the class
Returns: self.message_text_encrypted
'''
return self.message_text_encrypted
def change_shift(self, shift):
'''
Changes self.shift of the PlaintextMessage and updates other
attributes determined by shift (ie. self.encrypting_dict and
message_text_encrypted).
shift (integer): the new shift that should be associated with this message.
0 <= shift < 26
Returns: nothing
'''
self.__init__(self.message_text, shift)
class CiphertextMessage(Message):
def __init__(self, text):
Message.__init__(self, text)
def decrypt_message(self):
best_shift = None
best_real_words = 0
best_msg = ""
for s in range(26):
decrypted_text = self.apply_shift(s)
words = decrypted_text.split()
real_words = sum([is_word(self.get_valid_words(), w) for w in words])
if real_words > best_real_words:
best_shift = s
best_real_words = real_words
best_msg = decrypted_text
return (best_shift, best_msg)
#Example test case (PlaintextMessage)
plaintext = PlaintextMessage('hello', 2)
print('Expected Output: jgnnq')
print('Actual Output:', plaintext.get_message_text_encrypted())
#Example test case (CiphertextMessage)
#Uncomment the following lines when you have completed your CiphertextMessage class
ciphertext = CiphertextMessage('jgnnq')
print('Expected Output:', (24, 'hello'))
print('Actual Output:', ciphertext.decrypt_message())
The issue is with this line:
word = word.lower
You are giving word a reference to a method which propagates to everything you use word for afterwards. You probably wanted to write this:
word = word.lower()
Consider type hinting as it will allow your IDE to catch this kind of mistake easily.

It doesn't give anthing. Can someone help me about dictionaries and objects and classes in python?

I am trying to print frequencies of all words in a text.
I wanna print all keys according to their sorted values.
Namely, I wanna print the frequencies from most frequent to least frequent.
Here is my code:
freqMap = {}
class analysedText(object):
def __init__(self, text):
# remove punctuation
formattedText = text.replace('.', '').replace('!', '').replace('?', '').replace(',', '')
# make text lowercase
formattedText = formattedText.lower()
self.fmtText = formattedText
def freqAll(self):
wordList = self.fmtText.split(' ')
freqMap = {}
for word in set(wordList):
freqMap[word] = wordList.count(word)
return freqMap
mytexte = str(input())
my_text = analysedText(mytexte)
my_text.freqAll()
freqKeys = freqMap.keys()
freqValues = sorted(freqMap.values())
a = 0
for i in freqValues:
if i == a:
pass
else:
for key in freqKeys:
if freqMap[key] == freqValues[i]:
print(key,": ", freqValues[i])
a = i
Your function freqAll returns a value that you are not catching.
It should be:
counts = my_text.freqAll()
Then you use the counts variable in the rest of your code.
freqAll method of your class does return freqMap which you should store but do not do that, therefore you are in fact processing empty dict freqMap, which was created before class declaration. Try replacing
my_text.freqAll()
using
freqMap = my_text.freqAll()

How do I use this variable in another file?

My method store_useful_words take some text and compare each word in the entered text and then compares those words to some keywords in my database. The impWords variable stores those words that match with the database from the sentence. I have imported WebOutput to my database file and I want to use the impWords list to iterate through. How do I use the impWords variable in the database file?
WebOutput.py file
import DatabaseInteractor
import nltk
db = DatabaseInteractor.DatabaseInteractor()
class WebOutput:
def __init__(self,text, impWords = None):
self.text= text
self.impWords = self.store_useful_words()
def store_useful_words(self):
keywords = db.get_keywords()
tweetWords = []
for word in self.text.split():
if word in keywords:
tweetWords.append(word)
return tweetWords
Just pass keyword to __init__ and then create instance of class. Code:
class WebOutput:
def __init__(self, text, keywords, impWords=None):
self.text = text
self.keywords = keywords
self.impWords = self.store_useful_words()
def store_useful_words(self):
tweetWords = []
for word in self.text.split():
if word in self.keywords:
tweetWords.append(word)
return tweetWords
# Using
db = DatabaseInteractor.DatabaseInteractor()
output = WebOutput('some_text', db.get_keywords())
for word in output.impWords:
print(word)
# ... do something else ...

Writing strings to file using class - empty output

Quite new to python, I am trying to create a small function that is meant to write a given number of instances of a string to a file (e.g. as input for a word cloud tool). I have tried doing this with the class below but for some reason do not receive any output, but no error message either.
I thought maybe I am not declaring count correctly as an integer as input? However, no error message is displayed which makes it somewhat confusing.
Again, very new to Python so any help along with some explanation would be greatly appreciated :) Code below!
#Prints multiple instances of a string as input for a word cloud tool
class print_list(object):
wordlist = []
def __init__(int(count), word, self):
self.count = count
self.word = word
def write_list(self):
while count > 0:
wordlist.append(word)
print word + "\n"
count = count - 1
return wordlist
def write_file(self):
my_file = open("cloud.txt", "w")
for word in wordlist:
my_file.write(word + "\n")
my_file.close
Python = print_list(10, "Python")
You have a lot of syntax errors. First of all, self needs to come first, and type conversions don't happen in function definitions. so your __init__ should look like
def __init__(self, count, word):
self.count = int(count)
self.word = word
Second, all attribute, like wordlist count and word need to be accessed as self.wordlist, self.word etc. inside the methods. So for example, write_file should be
def write_file(self):
my_file = open("cloud.txt", "w")
for word in self.wordlist:
my_file.write(word + "\n")
my_file.close
And write_list should be
def write_list(self):
while self.count > 0:
self.wordlist.append(self.word)
print self.word + "\n"
self.count = self.count - 1
return self.wordlist
(I also un-indented the return statement so the loop actually gets executed, but I assume that was a copying into stackexchange error).
Lastly, you are not calling any of your methods that do the things like filling in wordlist and writing it. So to get your class to actually write the file you need to call the write_file method. Making these changes to your code, we have:
#Prints multiple instances of a string as input for a word cloud tool
class print_list(object):
wordlist = []
def __init__(self, count, word):
self.count = count
self.word = word
def write_list(self):
while self.count > 0:
self.wordlist.append(self.word)
print self.word + "\n"
self.count = self.count - 1
return self.wordlist
def write_file(self):
my_file = open("cloud.txt", "w")
for word in self.wordlist:
my_file.write(word + "\n")
my_file.close()
Python = print_list(10, "Python")
Python.write_list()
Python.write_file()
First of all, I did get a syntax error...
class print_list(object):
#int(count) isn't necessary and causes Syntax Error on my python 2.7
def __init__(self, count, word):
self.count = count
self.word = word
#I think wordlist will be more useful here, as a class attribute (1)
self.wordlist = []
def write_list(self):
#I copy the self.count to a local variable (2)
countCopy = self.count
while count > 0:
self.wordlist.append(self.word)
print self.word + "\n"
countCopy = countCopy - 1
def write_file(self):
#nitpick: hardcoding filenames is bad practice, it would be better to pass it as an argument
my_file = open("cloud.txt", "w")
#self.wordlist is the list built in the above function
#so if this function is called first, self.wordlist is an empty list
for word in self.wordlist:
my_file.write(word + "\n")
#you forgot parentheses below
my_file.close()
#More code here... (3)
Remarks:
Making wordlist a class attribute allows you to keep the once build list inside the class, and it is easily accessed by other class methods, like write_file.
Thanks to this, the self.count remains unchanged since the moment __init__ was called.
Simply instancing the class won't call all the methods we've defined. This means, that aside from tool = print_list(10, "word") you'll have to call each method as well. By the way, "Python" is a bad name for a class...
And a general comment:
You seem to get confused with what should be a class attribute (e. i. self.x instead of x) and what should be a local variable. And how to use those. Python, by default, looks for local variables but not class attributes. If you want to access a class attribute you have to prefix its name with self.. Otherwise you'll get a NameError or simply a wrong result.
class PrintList(object):
def __init__(self,count, word):# self comes first in your init method
self.count = count
self.word = word # use self to refer to instance attributes
self.wordlist=[] # make wordlist an attribute
def write_list(self):
while self.count > 0:
self.wordlist.append(self.word)
print self.word + "\n"
self.count -= 1
return self.wordlist
def write_file(self):
with open("cloud.txt", "w") as my_file: # using with automatically closes the file
for word in self.wordlist:
my_file.write(word + "\n")
pl = PrintList(10, "Python") # create instance of Printlist class
print pl.write_list()
pl.write_file()# need to call method on instance to write to the file
Python classes

'MarkovGenerator' object has no attribute 'together'

I come up with a problem about the class and I don't know the reason, does anyone can help me out?
The problem is in def together(), here are my code.
class MarkovGenerator(object):
def __init__(self, n, max):
self.n = n # order (length) of ngrams
self.max = max # maximum number of elements to generate
self.ngrams = dict() # ngrams as keys; next elements as values
beginning = tuple(["That", "is"]) # beginning ngram of every line
beginning2 = tuple(["on", "the"])
self.beginnings = list()
self.beginnings.append(beginning)
self.beginnings.append(beginning2)
self.sentences = list()
def tokenize(self, text):
return text.split(" ")
def feed(self, text):
tokens = self.tokenize(text)
# discard this line if it's too short
if len(tokens) < self.n:
return
# store the first ngram of this line
#beginning = tuple(tokens[:self.n])
#self.beginnings.append(beginning)
for i in range(len(tokens) - self.n):
gram = tuple(tokens[i:i+self.n])
next = tokens[i+self.n] # get the element after the gram
# if we've already seen this ngram, append; otherwise, set the
# value for this key as a new list
if gram in self.ngrams:
self.ngrams[gram].append(next)
else:
self.ngrams[gram] = [next]
# called from generate() to join together generated elements
def concatenate(self, source):
return " ".join(source)
# generate a text from the information in self.ngrams
def generate(self,i):
from random import choice
# get a random line beginning; convert to a list.
#current = choice(self.beginnings)
current = self.beginnings[i]
output = list(current)
for i in range(self.max):
if current in self.ngrams:
possible_next = self.ngrams[current]
next = choice(possible_next)
output.append(next)
# get the last N entries of the output; we'll use this to look up
# an ngram in the next iteration of the loop
current = tuple(output[-self.n:])
else:
break
output_str = self.concatenate(output)
return output_str
def together(self):
return "lalala"
if __name__ == '__main__':
import sys
import random
generator = MarkovGenerator(n=2, max=16)
for line in open("us"):
line = line.strip()
generator.feed(line)
for i in range(2):
print generator.generate(i)
print generator.together()
But I got the error saying:
Traceback (most recent call last):
File "markovoo2.py", line 112, in <module>
print generator.together()
AttributeError: 'MarkovGenerator' object has no attribute 'together'
Does anyone know know the reason?
You have indented the def together() function definition too far, it is part of the def generate() function body.
Un-indent it to match the other functions in the class body.
It looks your def together is indented too deeply. It is inside the generate method. Move it out one indentation level.

Categories

Resources