Python class and array interaction - python

So the basic idea is to make a "phonebook" type deal using classes and I'm not sure how it would interact with arrays.
class Person:
name = None
b_year = None
phone = None
So that is supposed to be the base. Then I want to be able to use
array[0].name #The name of the first person
array[1].phone #Number of the second person etc.
What I'm not sure about is how the get this interaction between the two. Any tips would be appreciated.
Thanks in advance!

class Person:
def __init__(self, name, b_year, phone):
self.name = name
self.b_year = b_year
self.phone = phone
p1 = Person(name="Jedrzej", b_year="1882", phone="321432555")
p2 = Person(name="Michael", b_year="1282", phone="321432553")
arr = [p1, p2]
print(arr[0].name)
This prints Jedrzej for me.
I think you should read about classes in Python, for example here:
http://www.diveintopython.net/object_oriented_framework/defining_classes.html

Related

Printing instances of class through inherited method

I am trying to do some simple stuff with OOP and Python, building some simple books service. I am trying to create class for Books, where each object will be a Book with attributes, that works, it is not the best, but good enough for now.
# Definition of class
class Books(object):
book_id = ""
book_title = ""
book_author = ""
book_year = ""
book_pub = ""
book_ac = ""
book_date = ""
Books = [book_id, book_title, book_author,
book_year, book_pub, book_ac, book_date]
# Set constructor
def __init__(self, book_id, book_title, book_author, book_year, book_pub, book_ac, book_date):
self.book_id = book_id
self.book_title = book_title
self.book_author = book_author
self.book_year = book_year
self.book_pub = book_pub
self.book_ac = book_ac
self.book_date = book_date
# Set attributes
def set_book_id(self, book_id):
self.book_id = book_id
def set_book_title(self, book_title):
self.book_title = book_title
def set_book_author(self, book_author):
self.book_author = book_author
def set_book_year(self, book_year):
self.book_year = book_year
def set_book_pub(self, book_pub):
self.book_pub = book_pub
def set_book_ac(self, book_ac):
self.book_ac = book_ac
def set_book_date(self, book_date):
self.book_date = book_date
# Show attributes
def show_book_id(self):
print(self.book_id)
def show_book_title(self):
print(self.book_title)
def show_book_author(self):
print(self.book_author)
def show_book_year(self):
print(self.book_year)
def show_book_pub(self):
print(self.book_pub)
def show_book_ac(self):
print(self.book_ac)
def show_book_date(self):
print(self.book_date)
# Show book
def show_book(self):
print(self.book_id)
print(self.book_title)
print(self.book_author)
print(self.book_year)
print(self.book_pub)
print(self.book_ac)
print(self.book_date)
Second Class is Booklist, which should hold the books inside and manage books inside, I am trying to create some basic methods as to create objects in Booklist automatically as I create Books object(this should work). Then I would like to operate with Booklist as with inherited methods from Books class to show the Books or etc.
# Definition of class
class BookList(Books):
listbook = []
# Set constructor
def __init__(self):
self.listbook = []
# Add book
def add_book(self, Books):
return self.listbook.append(Books)
# Show book
def show_books(self):
for b in self.listbook:
super().show_book(self)
# Search book
def search_book_by_id(self):
self.listbook = []
for Books in self.book_id:
if Books.book_id == id:
id.append(Books)
return id
Bellow are my tests, as I am still fighting with error like issues of parsing arguments-Expected one or more arguments from would anyone help here what would be the easiest please to use inherited method or to manipulate with inheritance for this use case please? Thank you
# Books defining
book1 = Books('1504234', 'Murders', 'Peter Jacob',
'2015', 'Ikaro', '5', '25.5.2015')
book2 = Books('1504231', 'Murders', 'Peter Jacob',
'2015', 'Ikaro', '5', '25.5.2015')
book3 = Books('1504232', 'Hiden language', 'Samuel Fellow',
'2005', 'Parik', '3', '21.4.2006')
book4 = Books('1504233', 'Saturday', 'Filp Sapko',
'2012', 'Satik', '4', '25.3.2012')
book1.show_book()
book1.set_book_title('New Murders')
book1.show_book()
book1.show_book_ac()
print("Booklist ******************************")
BookList.listbook.append(book1)
BookList.listbook.append(book2)
BookList.listbook.append(book3)
BookList.listbook.append(book4)
(Until here it works)Now the issue begins:
BookList.show_books()ERROR:
TypeError: show_books() missing 1 required positional argument: 'self'
Would anyone please tell me what I am doing wrong here?
Thank you very much!
Best Regards
To start with, I think you're imagining the structure of these classes a little wrong. The "Books" class shouldn't be the parent of "BookList" if you intend to use the super() method to access "show_books". Not to worry, you're almost there already
you only need to change it from this:
#Show book
def show_books(self):
for b in self.listbook:
super().show_book(self)
to this:
#Show book
def show_books(self):
for b in self.listbook:
b.show_book()
Your "search_book_by_id" method will also need to change from this:
#Search book
def search_book_by_id(self):
self.listbook = []
for Books in self.book_id:
if Books.book_id == id:
id.append(Books)
return id
to this:
#Search book
def search_book_by_id(self, id):
id_books = []
for b in self.listbook:
if b.book_id == id:
id_books.append(Books)
return id_books
Though I'm not sure exactly what that function was attempting before.
You also said you wanted the BookList class to automatically add books when you create them, there are far more complicated ways to link classes which I think you might not need, if all you need is for the Book class to live inside the BookList class, then I would suggest making a create_book function inside the BookList class that adds the book to the list once created, that way you only use one object. That would look something like this:
def create_book(self,book_id,book_title,book_author,book_year,book_pub,book_ac,book_date):
self.listbook.append(Books(book_id,book_title,book_author,book_year,book_pub,book_ac,book_date))
That's a pretty messy function, and you should probably look into better ways to handle objects with many attributes, checkout the #property decorator and look for other ways to store data than attributes, you can also use (*args, **kwargs) to really make things easy on the user of the function, but if you're very new to python, sometimes keeping things messy but simple is better to learn the basics with. Let me know if that helps or you need something else!

How to make each instance of a child class not require parent attributes (kinda?)

class User:
def __init__(self, username):
self.username = username
#classmethod
def get_user(cls):
return cls(input("Username: "))
class Budget(User):
def __init__(self, monthtly_income):
super().__init__(User.get_user())
self.monthly_income = monthtly_income
self.perc_lis = []
self.category_obj_lis = []
self.category_name_lis = []
self.value_lis = []
...
# creates objects and adds them to a list
for i in range(len(self.category_name_lis)):
self.category_obj_lis.append("")
self.category_obj_lis[i] = Category(self.category_name_lis[i], self.monthly_income)
...
class Category(Budget):
def __init__(self, name, monthly_income):
super().__init__(monthly_income)
self.name = name
self.perc = 0
self.amt = 0
self.left = 0
self.max = 0
# defines the percentage for each category
def get_perc(self):
self.perc = float(input(f"{self.name}: "))
When I run this it asks for username 3 times after I have asked for the categories because I create each Category object in a loop. Username is asked for at the start of the code. I need the category class to be a child class because I need the monthly_income variable to use in code not posted. I am not very good at inheritance so i could easily be missing something obvious. Is there a way for each instance of Category to not ask for username and just use the one already asked in the beginning? I apologize if this is somewhat confusing but idk where to go from here.

How to input data in classes in python, if number of students I want to input is not known

I want to input data in a class. I don't know the number of students I want to input. I can only write p1.name="John" p2.name="Jack" etc but if I want to input more students I have to write p3,p4,p5...
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person
p1.name="John"
p1.age=15
print(p1.name)
print(p1.age)
Is there a method to work like with arrays for example p[0].name="John"....... p[123].name="Jack" or something like that... Sorry for my bad english
You probably meant
p1 = Person('John', 15)
p2 = Person('Jack', 42)
If you needed an arbitrary number of objects, you can store them in a data structure like
people = [Person('John', 15), Person('Jack', 42)]
for person in people:
print(person.name)
You can read data into that array as well-
people = []
with open('people.txt') as f:
for line in f:
name, age = line.split()
people.append(Person(name, age))
But my advice would be to find a more introductory tutorial to follow, you're going to struggle :)
Sounds like you need a list.
A list is a data structure that you can use for zero or more elements, and you can access each element by iteration or by indexing the list.
You can do something like this:
persons = [
Person("John", 15),
Person("Adele", 16),
...
]
and then you can access each person by an index: persons[0] will give you Jonh, and persons[1] will give Adele.
if your objective is to store the students in an array-like structure, then you can definitely do this in Python. What you're currently doing is instantiating a new class object for each student. While this is totally valid, it may not be appropriate for the task you're trying to achieve.
Before mastering classes, I'd recommend familiarising yourself with python data structures like dictionaries, lists and tuples.
Just another idea. You could store all of the students in a dictionary that is contained within a class. Wrapping the dictionary in a class will let you add or fetch students very easily.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Classroom:
def __init__(self):
self.students = {}
def add_student(self, student):
self.students[student.name] = student
def get_student(self, name):
return self.students[name]
classroom = Classroom();
classroom.add_student(Person("John", 12))
classroom.add_student(Person("Sarah", 13))
print(classroom.get_student("Sarah").age)
#Output
#13
def main():
classroom = Classroom()
n = input("How many students would you like yo add? ")
for i in range(int(n)):
classroom.add_student(Person(input("Enter Name: "), int(input("Enter Age: "))))

Calling a function from a class in main

I seem to be making a stupid mistake that I cant find. Im simply trying to call my functions from my record class and having an invalid syntax error despite looking at sample code and trying to emulate the syntax.
Ive tried following tutorials and calling the function in every which way so the problem may not be in the calling of the function but something else I feel.
class definitions
class record:
def __init__(self,telephone,lastname,firstname):
self.telephone = telephone
self.lastname = lastname
self.firstname = firstname
def addrecord(self,x,y,z):
x = input('Enter telephone number')
y = input('Enter lastname')
z = input('Enter firstname')
phonebook.append(record(x,y,z))
return
def deleterecord(self,x):
phonebook[x-1].pop
return
Main
phonebook = record[]
addrecord(515,'fin','matt')
print(phonebook[0].firstname)
deleterecord(1)
print(phonebook[0].firstname)
If all this works I expect the output to be
"matt"
"null"
There are a number of problems with your code:
you are defining phonebook otuside of the class
in deleterecord you should call phonebook.pop(x).
there should be two classes that handle the phonebook and records, and the record could be modeled using a namedtuple.
there are syntax errors like calling record[] which is not valid Python.
Alternative implementation:
from collections import namedtuple
PhoneRecord = namedtuple("PhoneRecord", ['firstname', 'lastname', 'telephone'])
class PhoneBook:
def __init__(self):
self._phonebook = []
def addrecord(self, record):
self._phonebook.append(record)
return self._phonebook.index(record)
def deleterecord(self, i):
self._phonebook.pop(i)
phonebook = PhoneBook()
record_index = phonebook.addrecord(PhoneRecord(firstname="matt", lastname="snow", telephone="25512521"))
print(phonebook._phonebook)
phonebook.deleterecord(record_index)
print(phonebook._phonebook)
which will yield in the console:
[PhoneRecord(firstname='matt', lastname='snow', telephone='25512521')]
[]
The simplified version of your question is, given code
records = []
records.append("matt")
print(records[0])
del records[0]
print(records[0])
why don't I get the following output
"matt"
None
Instead, you get an IndexError exception.
The reason is that you are accessing an element beyond the size of the list, and Python handles this by raising an exception rather than returning None.

Python input Job Code

I'm Code doesn't seem to work, I am trying to get input of a job, category, and salary, and store the input
class Jobs:
def GetJob(self):
name = raw_input('Enter a Job Title: ')
category = raw_input('Enter what Category that Job is: ')
salary = raw_input('Enter the salary of that Job: ')
print name,category, salary
def __init__(self,name,category,salary):
self.name = Jobs.GetJob(name)
self.category = Jobs.GetJob(category)
self.salary = Jobs.GetJob(salary)
GetJob = Jobs()
print GetJob
Your code is totally out of good OOP practices, and the first part eandersson's answer too…
A class has for role to store values, get/set them and return (or apply) transformations to its encapsulated values. What you tried to achieve is totally nonsense: you're calling the GetJob method of the Jobs class inside another method. It could work if you would have written:
def __init__(self,name…):
self.name = Jobs.GetJob(self, name)
…
But that would be a wrong way to design your program. You'd better stick your class to hold your values and making it good at that, and make another function that helps populate your class:
class Jobs:
def __init__(self, name, category, salary):
self.name = name
self.category = category
self.salary = salary
def __repr__(self):
return "Jobs<%s,%s,%s>" % (self.name, self.category, self.salary)
def GetJob():
name = raw_input('Enter a Job Title: ')
category = raw_input('Enter what Category that Job is: ')
salary = raw_input('Enter the salary of that Job: ')
return Jobs(name, category, salary)
print GetJob()
I do not agree with eandersson's approach because it deceives the purpose of the constructor, by directly calling the GetJob method. Then GetJob is not useful. And one would want to be able to use the Job class without always having the raw inputs at construction. EDIT: valid only as a comment on the first part of his answer.
And finally, I think that you really misunderstands a lot about programming. You should better read thoroughly a python course like the ones on http://wiki.python.org/moin/BeginnersGuide/NonProgrammers, because there's really a lot of concepts you ignored to be able to write something like that.
go have a look at:
http://hetland.org/writing/instant-hacking.html
http://www.learnpython.org/
http://cscircles.cemc.uwaterloo.ca/
http://learnpythonthehardway.org/book/

Categories