Python Class and Attribute Error - python

Please look at the code below and the Attribute error I get. Thanks for your help.
This is the error I get.
Traceback (most recent call last):
File "ClassError.py", line 45, in <module>
if __name__ == '__main__':Main()
File "ClassError.py", line 43, in Main
printTest(i)
File "ClassError.py", line 38, in printTest
print f.FirstName
AttributeError: 'str' object has no attribute 'FirstName'
CODE
class CompKeyData():
def __init__(self,
FirstName,\
MiddleName,\
LastName):
self.FirstName = FirstName
self.MiddleName = MiddleName
self.LastName = LastName
def __repr__(self):
return repr((self.FirstName,\
self.MiddleName,\
self.LastName))
def __iter__(self):
return iter((self.FirstName,\
self.MiddleName,\
self.LastName))
def ckDataClassList(dataList):
dataObjects = []
for FirstName,\
MiddleName,\
LastName in dataList:
dataObjects.append(CompKeyData(
FirstName,\
MiddleName,\
LastName))
return dataObjects
ckData = [['John', 'Ralph', 'DuMont'], ['Jack', 'Lowry', 'Matern']]
ckClassData = ckDataClassList(ckData)
def printTest(classData):
for f in classData:
print f.FirstName
return None
def Main():
for i in ckClassData:
printTest(i)
if __name__ == '__main__':Main()

When you do
for i in ckClassData:
Each i is a CompKeyData instance. You then do:
printTest(i)
Which calls:
for f in classData:
where classData is the i you passed in.
This iterates through the individual CompKeyData instance, which (due to your implementation of __iter__) assigns FirstName, MiddleName and LastName in turn to f- each of these is a string, and doesn't have FirstName.
Instead, printTest should be:
printTest(classData):
print classData.FirstName
You don't need to explicitly return None, this happens automatically if you don't explicitly return anything else.
Also, it is worth reading PEP-0008; following this will make your code more readable.

You need to change your printTest function to the following:
def printTest(classData):
print classData.FirstName
classData is not a list of CompKeyData instances, but rather a single CompKeyData instance.
PEP8 is also certainly worth a look for python style.

Related

Using decorator in a class in python

For understanding decorators in Python, i created in a class an example. But when i run it i receive an error.
class Operation:
def __init__(self, groupe):
self.__groupe = groupe
#property
def groupe(self):
return self.__groupe
#groupe.setter
def groupe(self, value):
self.__groupe = value
def addition(self, func_goodbye):
ln_house = len('house')
ln_school = len('school')
add = ln_house + ln_school
print('The result is :' + str(add))
return func_goodbye
#addition
def goodbye(self):
print('Goodbye people !!')
if __name__ == '__main__':
p1 = Operation('Student')
p1.goodbye()
I receive this error :
Traceback (most recent call last):
File "Operation.py", line 1, in
class Operation:
File "Operation.py", line 21, in Operation
#addition
TypeError: addition() missing 1 required positional argument: 'func_goodbye'
You can have a class scoped decorator, however there won't be a self when the decorator is called
a decorator:
#foo
def bar(): ...
is roughly equivalent to
def bar(): ...
bar = foo(bar)
in your particular example, if you remove the self parameter, it should function as you expect:
def addition(func_goodbye):
ln_house = len('house')
ln_school = len('school')
add = ln_house + ln_school
print('The result is :' + str(add))
return func_goodbye
#addition
def goodbye(self):
print('Goodbye people !!')
for good measure, I might del addition after that just to ensure it isn't accidentally called later
(an aside: one unfortunate side-effect of this is many linters and type checkers will consider this "odd" so I've yet to find a way to appease them (for example mypy))

TypeError: '<' not supported between instances - objects

I am trying to sort by name but it is typing an Error: TypeError: '<' not supported between instances of 'Person' and 'Person'. Could you tell me where the problem is? Here is my code.
class Person:
def __init__(self, name, year_of_birth, degree):
self.name = name
self.year_of_birth = year_of_birth
self.degree = degree
self.mentor = None
self.mentees = []
def create_mentorship(mentor, mentee):
mentee.mentor = mentor
mentor.mentees.append(mentee)
def get_founder(people):
for person in people:
if people[person].mentor == None:
return people[person]
def print_mentorship_tree(people):
person = get_founder(people)
print_mentorship_subtree(person)
def print_mentorship_subtree(person, level=0):
a = []
print((" " * level) + person.name +' (' + str(person.year_of_birth) + ')')
for mentee in person.mentees:
print_mentorship_subtree(mentee, level + 1)
a = sorted(person.mentees)
>>> people = {}
>>> people['Martin'] = Person('Martin', 1991, 'phd')
>>> people['Lukas'] = Person('Lukas', 1991, 'phd')
>>> people['Tom'] = Person('Tom', 1993, 'mgr')
>>> people['Honza'] = Person('Honza', 1995, 'bc')
>>> create_mentorship(people['Martin'], people['Tom'])
>>> create_mentorship(people['Tom'], people['Honza'])
>>> create_mentorship(people['Martin'], people['Lukas'])
>>> print_mentorship_tree(people)
Error:
Traceback (most recent call last):
File "so.py", line 38, in <module>
print_mentorship_tree(people)
File "so.py", line 20, in print_mentorship_tree
print_mentorship_subtree(person)
File "so.py", line 28, in print_mentorship_subtree
a = sorted(person.mentees)
TypeError: unorderable types: Person() < Person()
It's just what it says: you cannot sort Person objects. If you want this to work, you have to define at least the __lt__ operator for your class, using whatever sort criterion you had in mind -- perhaps alphabetical by name?
Another possibility is to simply write your own function, and call it with person.mentees.obj_sort.
Also, I'm not sure why this matters: you never use the return value of this operation. You store it in the local variable a (that's a poor variable name, by the way), and never use it.
How about writing a custom key function and pass it as sorted() argument?
sorted_list = sorted(person.mentees, key=lambda p: p.name)

Attribute Error with Python

I can't seem to figure out what is causing the below attribute error. I am really not sure what I am doing wrong here. Any help would be great!
Traceback (most recent call last):
File "project2.py", line 140, in
movie_writter.writerow([movie.title, movie.author, movie.itunes_id, movie.itunes_URL, movie.length])
AttributeError: 'Movie' object has no attribute 'length'
class Movie(Media):
def __init__(self, diction_file):
Media.__init__(self, diction_file)
self.rating = diction_file['contentAdvisoryRating']
self.genre = diction_file['primaryGenreName']
try:
self.track_time = diction_file['trackTimeMillis']
except:
self.track_time = 0
try:
self.description = diction_file['longDescription']
except:
self.description = None
def __len__(self):
return self.track_time/1000
def title_words_num(self):
if self.description != None:
return len(self.description.split())
else:
return 0
movie_list = [Movie(diction_file) for diction_file in movie_samples]
with open('movies.csv', 'w', newline = '') as movies_csv:
movie_writter = csv.writer(movies_csv, delimiter=',')
movie_writter.writerow(["Title", "Artist", "ID", "URL", "Length"])
for movie in movie_list:
movie_writter.writerow([movie.title, movie.author, movie.itunes_id, movie.itunes_URL, movie.length])
movies_csv.close()
It means what it means: the object has no attribute length. You probably meant len(movie), which maps to __len__ magic method.
Also, keep in mind, this is not the best use for the __len__ method. It is supposed to be used for collections/containers of any kind, to show the amout of items inside. The movie duration is not an amount of things.

Understanding variable scopes in python: An Exercise Program

This is an exercise that I wanted to try because I thought it was interesting. The exercise is unnecessarily complex for what it is doing, but it is trying to act as practice for understanding class, function and variable behavior in more complex python programs.
import os
class grabFile:
fileObject = None
def __init__(self, filename):
self.fileObject = open(filename, "r")
def getFile():
return self.fileObject
class counter:
fileC = None
lineCount = 0
def __init__(self, fileObject):
self.fileC = fileObject
def lineCounter(self):
while True:
self.fileC.readline()
print(x)
return lineCount
def Main():
fileGrabber = grabFile("test.txt")
fileObj = fileGrabber.getFile
countObj = counter(fileObj)
lineCount = countObj.lineCounter()
print(lineCount)
Main()
However, when I run this, I get the following error:
Traceback (most recent call last):
File "/home/may/Desktop/Tree/Programming/MiscProjects/TextAnalyzer.py", line 32, in <module>
Main()
File "/home/may/Desktop/Tree/Programming/MiscProjects/TextAnalyzer.py", line 29, in Main
lineCount = countObj.lineCounter()
File "/home/may/Desktop/Tree/Programming/MiscProjects/TextAnalyzer.py", line 19, in lineCounter
self.fileC.readline()
AttributeError: 'function' object has no attribute 'readline'
[Finished in 0.2s with exit code 1]
Can anyone help me understand this program fully? And also, although this is not the correct place to ask, offer any critique on styling or formatting of the program? Especially one the use of "self".
Thank you!
I think you meant to call the method:
fileObj = fileGrabber.getFile()
And you need to change to instance method:
def getFile(self):
return self.fileObject
And your line counter method needs some work:
def lineCounter(self):
self.lineCount = len(self.fileC.readlines())
return self.lineCount

Python Issue - Map and Classes - Beginner

I'm attempting to use Map to reference a class function, but am having difficulty with formatting/ordering. I have heard that using map is sort of obsolete so I am definitely open to alternative solutions (for loops?) Thanks in advance.
lognames = [ "C:\Users\makker1\Desktop\logs\loga.txt",
"C:\Users\makker1\Desktop\logs\logb.txt",
"C:\Users\makker1\Desktop\logs\logc.txt" ]
class LogFile:
def __init__(self,filepath):
self.logfile = open(filepath, "r")
self.head = None
def __str__(self):
return "x=" + str(self.x) + "y="+str(self.y)
def readline (self):
if self.head != None:
self.head = self.logfile.readline()
def previewline (self):
if self.head == None:
self.head = self.logfile.readline()
def close (self):
self.logfile.close()
logs = map(LogFile(self,filepath).__init__(), lognames)
heads = map(lambda log: None, logs)
>>>
Traceback (most recent call last):
File "C:\Users\makker1\Desktop\mergesort-final.py", line 30, in <module>
logs = map(LogFile(self,filepath).__init__, lognames)
NameError: name 'self' is not defined
>>>
If any more info is needed, please let me know. I realize that there are tons of posts about this very problem and have sorted through many of them with no avail.
Here is a list comprehension answer. I like this better than map().
logs = [LogFile(fname) for fname in lognames]
You don't have to call __init__ explicitly. Try:
logs = map(LogFile, lognames)
Sometimes it helps to think of a class as being callable. You can think of a class as something like the following:
def LogFile(filepath):
class _LogFile:
def __init__(self, path):
...
return _LogFile(filepath)
Basically, a class can be thought of as something that you call to create an object instance. This isn't really true, but in many cases it will appear to be.

Categories