I was trying to write a code and check it with pytest. I thought I did everything ok, but I got a problem. After writing this, I want to check it with method of class Person. When I tried to use method id the function ends and I got the output:
TypeError: 'str' object is not callable
My code:
class Person:
def __init__(self, id, name, sex, birth_date):
self.name = name
self.id = id
self.sex = sex
self.birth_date = birth_date
def __str__(self):
return f'{self.name} born {self.birth_date} with {self.sex} has {self.id}'
def name(self):
return self.name
def sex(self):
return self.sex
def id(self):
return self.id
def date_of_birth(self):
return self.birth_date
def read_from_file(file_handle):
people = []
reader = csv.DictReader(file_handle)
for row in reader:
id = row['id']
name = row['name']
sex = row['sex']
birth_date = row['birth_date']
person = Person(id, name, sex, birth_date)
print(person.id())[Error in this line]
people.append(person)
return people
def test_files():
with open('people.txt', 'r') as people_txt:
people = read_from_file(people_txt)
Example of line of people.txt:
id,name,sex,birth_date
1,Doralyn Dovermann,Female,27/10/2005
2,Rickert Petschel,Male,10/7/2018
3,Whitney Girardoni,Female,7/3/1932
That error occurs when you try to call a string as if it were a function. In your code you call person.id(), but person.id is not a function. If you want to print the contents of the string attribute, just do print(person.id).
Related
I am an IT student and I'm completely new with Python. In a workshop I worked on there were a few lines in between that I don't really understand how they work and their purpose in the code. Those lines come from a fellow student who successfully ran it and I would like to fully understand. Thank you!
Overall, this is my code:
class AcademicPublication():
def __init__(self, title, year):
self.__year = year
self.__title = title
self.__authors = []
def addAuthor(self, author_name):
self.author_name = author_name
self.__authors.append(author_name)
def getReference(self):
return f"{self.__authors}, {self.__authors}({self.__year}): {self.__title}."
class Conference():
def __init__(self, acronym, name):
self.acronym = acronym
self.name = name
self.paper = []
def addPaper(self, conference_paper):
self.paper.append(conference_paper)
conference_paper.Conference = self
conference_paper.acronym = self.acronym
conference_paper.name = self.name
class ConferencePaper(AcademicPublication):
def __init__(self, title, year):
super().__init__(title, year)
def getReference(self):
return super().getReference() + '. In Proceedings of ' + str(self.name) + str(self.acronym)
And I'm struggling with this part:
self.paper.append(conference_paper)
conference_paper.Conference = self
conference_paper.acronym = self.acronym
conference_paper.name = self.name
At first I thought conference_paper is a class attribute, but there was no definition before in the code, and I did some research but I didn't find anything about a parameter from this method accessing another method's parameter.
i want to write a method of class and call it dumpData which will build a string that holds all the information about the object. i tried several codes but all i get is AttributeError: 'list' object has no attribute 'dumpData'
this is the code i have written so far:
class Car():
def __init__(self, brand, productionYear)
self.brand = brand
self.productionYear = productionYear
def dumpData(self,CarList1):
return CarList1
if __name__ =="__main__":
carObject = []
for i in range(10):
carObjectList = []
brand_list = ['kia', 'Hunday', 'BMW', 'Audi', 'Jeep']
brand = random.choice(brand_list)
productionYear = random.randint(1995, 2020)
carObject.append(Car(brand, productionYear))
carObjectList.append(carObject)
print(carObject.dumpData(carObjectList))
i edited this question because it didn't seem to be clear enough.
thank you in advance
Your error is saying you have a list object, not an instance of your class that you've tried to call your function on.
I suggest making your class actually hold the list, and the add function take the info you want
You don't need a parameter for the list, at that point.
class Car():
def __init__(self, brand, year):
self.brand = brand
self.year = year
def __repr__(self):
return self.brand + "," + str(self.year)
class CarList():
def __init__(self):
self.cars = []
def dump(self):
return str(self.cars)
def add(self, brand, year):
self.cars.append(Car(brand, year))
carList1 = CarList()
carList1.add('honda', 2009)
print(carList1.dump())
Lets assume that I have a class called Person, and a class that inherits this called Group. Person has an attribute called name and one called age. When I create a Group I want to pass n person objects and their new name is a combo of names, and their new age is their combined age.
also for the hell of it, going to keep track of how many people, and how many groups there are separately (just so inheriting makes any sense in this example.)
class Person:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.id = make_person() # count is also the person's id in this example
def __str__(self):
return f'Name: {self.name} Age: {self.age}'
#classmethod
def make_person(cls):
cls.count += 1
return cls.count
class Group(Person):
def __init__(self, *people):
#not sure how to do this, Below Does Not Work, something like
new_name = self.make_group(people)
new_age = self.new_age(people)
self.name = new_name
self.age = new_age
super().__init__(self.new_name, self.new_age)
def make_group(self, *people):
return (' & ').join([person.name for person in People])
def new_age(self, *people):
return sum([person.age for person in people])
then you would think i could write
anne = Person('Anne', 20)
bob = Person('Bob', 20)
carl = person('Carl', 25)
couple = Group(anne, bob)
threesome = Group(anne, bob, carl)
print(couple)
print(threesome)
but this doesnt work. For some reason the group class isnt getting the people object i pass, or i'm defining it wrong...any ideas?
What you have written is that a Group is a particular type of Person. This doesn't seem quite right to me. Regardless, here is a version that will run and give the desired output:
class Person:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.id = Person.make_person() # count is also the person's id in this example
def __str__(self):
return f'Name: {self.name} Age: {self.age}'
#classmethod
def make_person(cls):
cls.count += 1
return cls.count
class Group(Person):
def __init__(self, *people):
#not sure how to do this, Below Does Not Work, something like
new_name = self.make_group(*people)
new_age = self.new_age(*people)
self.name = new_name
self.age = new_age
super().__init__(self.name, self.age)
def make_group(self, *people):
return (' & ').join([person.name for person in people])
def new_age(self, *people):
return sum([person.age for person in people])
anne = Person('Anne', 20)
bob = Person('Bob', 20)
carl = Person('Carl', 25)
couple = Group(anne, bob)
threesome = Group(anne, bob, carl)
print(couple)
print(threesome)
Changes from your code:
some typos with capital letters
put a * before people when passing it
take care of variable scope
Here is the code, the explanation is at the bottom
#classing tests
class Employee(object):
raise_amount = 1.04
def __init__(self, name, age, pay):
self.name = name
self.age = age
self.pay = pay
def __repr__(self):
return ("Employee: {} Age: {} Pay: {:.2f}/month".format(self.name, self.age, self.pay))
def __str__(self):
return ("{} is {} and gets {:,.2f} per month".format(self.name, self.age, self.pay))
#property
def show_pay(self):
print ("{0} gets {1:,.2f} per month".format(self.name, self.pay))
#property
def pay_rise(self):
self.pay *= self.raise_amount
class Head(Employee):
raise_amount = 1.1
def __init__(self, name, age, pay, employees=None):
super().__init__(name, age, pay)
if self.employees == None:
self.employees = []
else:
self.employees = employees
def add_employee(self, employe):
if employe not in employees:
self.employees.append(employe)
def remove_employee(self, employe):
if employe in employees:
self.employees.remove(employe)
#property
def show_employees(self):
for i in self.employees:
print(i.name())
employee_1 = Employee("John", 55, 21377)
head1 = Head("Bob", 21, 22336)
employee_1.show_pay
employee_1.pay_rise
employee_1.show_pay
head1.show_pay
head1.pay_rise
head1.show_pay
print(head1)
print(repr(head1))
So this is my code,when i run it, it returns AttributeError: type object 'Head' has no attribute 'employees. Please help, im so confused. Please help because it worked until i added the head class with the importation of employees and it is frustrating
The problem arises in the line if self.employees is None: in the __init__() constructor.
As the exception says there is no attribute called employees in self, because you didn't define it yet, hence the error.
To check for the existence of an attribute you should instead use hasattr, so that the above line would become if not hasattr(self, 'employees'):.
With this change the code runs without problems
It is generally considered more pythonic to refactor the code in such a way as to not need to use hasattr or similar checks, though.
In the class Head you access the attribute self.employees before assigning a value to it, therefore the AttributeError. You probably meant employees, the argument:
class Head(Employee):
raise_amount = 1.1
def __init__(self, name, age, pay, employees=None):
super().init(name, age, pay)
self.employees = [] if employees == None else employees
Writing a function to reshelve books where the Library attempts to reshelve a book currently held by the indicated Patron. The book is moved from patron's borroweds to the Library's available books list. I coded most of it, but I'm not sure if my loop is correct and I have no idea where to insert my missingIdError, any suggestions? Note: I also have a Patron Class and defined them already along with the ID so no need to worry about the missing class.
class DuplicateIdError (Exception):
def __init__(self, id, category = "Book" or "Patron"):
self.id = int(id)
self.category = str(category)
def __str__(self):
return 'duplicate {} ID: #{}'.format(self.category,self.id)
def __repr__(self):
return 'duplicate {} ID: #{}'.format(self.category,self.id)
class MissingIdError (LookupError):
def __init__(self, id, category = "Book" or "Patron"):
self.id = int(id)
self.category = str(category)
def __str__(self):
return 'duplicate {}: {}'.format(self.id, self.category)
def __repr__(self):
return 'duplicate {}: {}'.format(self.id, self.category)
class Library:
def __init__(self, books=None, patrons=None):
self.books = []
self.patrons = []
def __str__(self):
return "Library(<{}>, <{}>)".format(self.self.books, self.patrons)
def __repr__(self):
return "Library(<{}>, <{}>)".format(self.self.books, self.patrons)
#Returns None.
#Raises a DuplicateIdError if there's already a book in the library with that id#.
#Raises a MissingIdError if the patron or book wasn't found
def reshelve_book(self, patron_id, book_id):
for patron in self.patrons:
for book in self.books:
try:
if book.book_id == book_id:
raise DuplicateIdError(book_id,"Book")
elif book.book_id != book_id:
self.books.append(book)
book.borroweds.remove(book)
Just a couple of simple guards would give you the other exception:
def reshelve_book(self, patron_id, book_id):
if patron_id not in self.patrons:
raise MissingIdError(patrod_id, 'Patron')
I don't understand book.borroweds.remove(book) but presumable you need to test book_id has been borrowed.
Do you really need a loop?
def reshelve_book(self, patron_id, book_id):
if patron_id not in self.patrons:
raise MissingIdError(patrod_id, 'Patron')
if book_id in self.books:
raise DuplicateIdError(book_id,"Book")
try:
book = self.patrons[patron_id].borrowed_books[book_id]
except KeyError:
raise MissingIdError(book_id, 'Book')
self.books[book_id] = book
del self.patrons[patron_id].borrowed_books[book_id]
BTW: your constructors for the exceptions don't do what I think you think it does:
def __init__(self, id, category = "Book" or "Patron"):
Is equivalent to do:
def __init__(self, id, category = True):
I would just avoid putting a default arg for category:
def __init__(self, id, category):