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!
Related
So I'm trying to create a program that resembles an auction, and so far I have created a class that takes in information about the person who is bidding, the bidder id, and the code (in that order in def(__init__(self...))) and here is what I have so far...
class Starter:
def __init__(self, startd, starterid, bidding):
self.startd = startd
self.starterid = starterid
self.bidding = bidding
and now, I'm trying to implement a new class, Bidding, where each auction is identified by an auction identifier.
The class has the following features:
• It can be created via Bidding(bidding), (bidding) is from class Starter btw for example,
bidtest = Auction('ewmzr')
creates an instance of Bidding with bidding identifier 'ewmzr'.
• The method beginbid(bidder_id) reflects the action of the bidder with bidder_id placing a
bid on this auction. That is to say, if a is an Bidding instance, the call to a.beginbid(starterid) places a bid from a bidder with starterid.
• If a is a Bidding instance, then a.price is the current price of this bidding, and a.winner
is the current winner of this bidding. Before anyone places a bid, a.winner is, by convention,
None.
Here is what I have so far...
class Starter:
def __init__(self, startd, starterid, bidding):
self.startd = startd
self.starterid = starterid
self.bidding = bidding
c = Starter(1, '8dac2b', 'ewmzr')
class Bidding:
def __init__(self,bidding):
self.bidding = self.bidding
def Beginbid(self,starterid):
return starterid
However, this doesn't work at all. I think I'm not understanding the concept of classes ig. Can someone please help me solve this issue?
It sounds like you want your bidding object to hold the id of the current highest bidder and that you want to give it an initial value of whoever started the bidding?
You could pass in the Starter object like this:
class Starter:
def __init__(self, startd, starterid):
self.startd = startd
self.starterid = starterid
class Bidding:
def __init__(self, starter):
self.current_bidder = starter.starterid
c = Starter(1, '8dac2b', 'ewmzr')
b = Bidding(c)
It would probably work better to directly store a reference to the current bidder rather than their ID though:
class Starter:
def __init__(self, startd, starterid):
self.startd = startd
self.starterid = starterid
class Bidding:
def __init__(self, starter):
self.current_bidder = starter
c = Starter(1, '8dac2b', 'ewmzr')
b = Bidding(c)
That way you don't need to be able to look up the object from its ID later.
If begin_bid is intended to update the current highest bidder then it simply looks like:
def begin_bid(self, bidder):
self.current_bidder = bidder
The other methods would be variations on a theme after that, updating or fetching instance variables.
Does this help at all?
I don't understand this strange things...I've this class:
class cChallenge:
def __init__(self, Id:int = 0 , Difficulty:str = '', Title:str = '',
Challenge:str = '', Url:str = '', Solved:bool = False):
self.Id = Id
self.Difficulty = Difficulty
self.Title = Title
self.Challenge = Challenge
self.Url = Url
self.Solved = Solved
Everything works fine so I've pushed all my generated cChallenge elements into a list: cList.
If I query the list for single object everything works fine:
print(cList[1].Id)
>> 380
but if I use list comp:
print([x.Id for x in cList])
>> AttributeError: type object 'cChallenge' has no attribute 'Id'
[https://pastebin.com/cGuhPAG8] That's the link if someone want to try
In the code of the complete script to fill the list you need to create an instance of a class i.e. each object (look at added variable c):
for s in submission:
#other code...
c = cChallenge(Id, Difficulty, '', Url, Solved)
cList.append(c)
#other code...
Don't know exactly what are you trying to put into the list, but probably this will do.
Just like #Alecx note
to fill the list you need to create an instance of a class
so the right code for who look inside the pastebin is:
for s in submission
...
_ = cChallenge(...)
cList.append(_)
I will post the github link to the project tomorrow for who is interested!
I was trying to write a function in python to print out all the overlapping movie interests.
I wanted to write this program as a little classes and objects exercise. So this is what it looks like, right now:
def main():
class Person:
def __init__(self, Film):
self.Film = Film
like_it = "Film" , "Movie"
def likes(self, Film):
if (Film in like_it):
return Film
else:
print("no movies in common")
Person1 = Person("Movie")
print(Person1.likes)
I wanted to initialize different People as objects in the class "Person". The Program doesn't see any mistakes, but prints nothing. What is wrong here? Where should I look?
Thank you so much for your help!!
You aren't passing Film as an argument in the likes method.
Working with Classes
class Person:
def __init__(self, Film):
self.Film = Film
like_it = "Film" , "Movie"
def likes(self):
if (self.film in like_it):
return self.film
else:
return "no movies in common" #we are returning string instead of printing
Person1 = Person("Movie")
print(Person1.likes()) #likes is a method that has to be called
References:
Object Oriented Programming with python
Further Reading:
Converting methods to property
Here is Customer class:
class Customer:
def __init__(self, timestamp, cid, item_count):
self.time_stamp = timestamp
self.customer_name = cid
self.item_count = item_count
def checkout(self, new_timestamp):
self.time_stamp = new_timestamp
def get_cus_name(self):
return self.customer_name
If I create an empty list of Customer objects like:
customers = [Customer]
And then somewhere else I try to call Customer methods in a loop like:
def checkout_customer(self, cid):
for cus in self.customers:
if cus.get_cus_name == cid:
cus.checkout(self.cur_num_customers + 7)
why do I get an error when I try to call cus.checkout? My ide tells me that it expects a Customer but got an int. Why doesn't it pass itself into the 'self' arg here?
However if I just create a Customer object and directly call its methods, it works fine:
def foo(self):
cus = Customer(1,'pop',2)
cus.checkout(23)
This is my first time learning python, and ive been stuck trying to figure out lists, and accessing its members. Perhaps my initialization of self.custormers = [Customer] is incorrect?
EDIT:
In my constructor of tester class I create an empty list like this:
self.customer = [Customer]
I am able to add customers no problem:
def add_custormer(self, customer):
self.customers.append(customer)
My problem is not adding customers, but accessing their methods once they are in a list. Doing something like this self.customers[0].checkout(1,'pop',2) gives me an error "Expected type 'Customer' got int".
I am not sure of the class where checkout_customer lives but I am assuming you declare the list self.customers somewhere in it.
self.costumers = []
If you intend to add an element Customer to the list you should use something like: self.customers.append(Customer(x,y,z)) since you want to add a new customer to the list and when doing so you are required to initialize the Customer class.
I didn't try the code but I believe something like this should work:
def foo(self):
self.customers.append(Customer(1,'pop',2))
self.checkout_customers(23)
Looking at the bottom of the post you can see i have three classes. The code here is pseudo code written on the fly and untested however it adequately shows my problem. If we need the actual classes I can update this question tomorrow when at work. So ignore syntax issues and code that only represents a thought rather than the actual "code" that would do what i describe there.
Question 1
If you look at the Item search class method you can see that when the user does a search i call search on the base class then based on that result return the correct class/object. This works but seems kludgy. Is there a better way to do this?
Question 2
If you look at the KitItem class you can see that I am overriding the list price. If the flag calc_list is set to true then I sum the list price of the components and return that as the list price for the kit. If its not marked as true I want to return the "base" list price. However as far as I know there is no way to access a parent attribute since in a normal setup it would be meaningless but with sqlalchemy and shared table inheritance it could be useful.
TIA
class Item(DeclarativeBase):
__tablename__ = 'items'
item_id = Column(Integer,primary_key=True,autoincrement=True)
sku = Column(Unicode(50),nullable=False,unique=True)
list_price = Column(Float)
cost_price = Column(Float)
item_type = Column(Unicode(1))
__mapper_args__ = {'polymorphic_on': item_type}
__
def __init__(self,sku,list_price,cost_price):
self.sku = sku
self.list_price = list_price
self.cost_price = cost_price
#classmethod
def search(cls):
"""
" search based on sku, description, long description
" return item as proper class
"""
item = DBSession.query(cls).filter(...) #do search stuff here
if item.item_type == 'K': #Better way to do this???
return DBSession.query(KitItem).get(item.item_id)
class KitItem(Item):
__mapper_args__ = {'polymorphic_identity': 'K'}
calc_list = Column(Boolean,nullable=False,default=False)
#property
def list_price(self):
if self.calc_list:
list_price = 0.0
for comp in self.components:
list_price += comp.component.list_price * comp.qty
return list_price
else:
#need help here
item = DBSession.query(Item).get(self.item_id)
return item.list_price
class KitComponent(DeclarativeBase):
__tablename__ = "kit_components"
kit_id = Column(Integer,ForeignKey('items.item_id'),primarykey=True)
component_id = Column(Integer,ForeignKey('items.item_id'),primarykey=True)
qty = Column(Integer,nullable=False, default=1)
kit = relation(KitItem,backref=backref("components"))
component = relation(Item)
Answer-1: in fact you do not need to do anything special here: given that you configured your inheritance hierarchy properly, your query will already return proper class for every row (Item or KitItem). This is the advantage of the ORM part. What you could do though is to configure the query to immediatelly load also the additional columns which do belong to children of Item (from your code this is only calc_list column), which you can do by specifying with_polymorphic('*'):
#classmethod
def search(cls):
item = DBSession.query(cls).with_polymorphic('*').filter(...) #do search stuff here
return item
Read more on this in Basic Control of Which Tables are Queried.
To see the difference, enabled SQL logging, and compare your tests scripts with and without with_polymorphic(...) - you will most probably require less SQL statements being executed.
Answer-2: I would not override one entry attributed with one which is purely computed. Instead I would just create another computed attribute (lets call it final_price), which would look like following for each of two classes:
class Item(Base):
...
#property
def total_price(self):
return self.list_price
class KitItem(Item):
...
#property
def total_price(self):
if self.calc_list:
_price = 0.0
for comp in self.components:
_price += comp.component.list_price * comp.qty
return _price
else:
# #note: again, you do not need to perform any query here at all, as *self* is that you need
return self.list_price
Also in this case, you might think of configuring the relationship KitItem.components to be eagerly loaded, so that the calculation of the total_price will not trigger additional SQL. But you have to decide yourself if this is beneficial for your use cases (again, analyse the SQLs generated in your scenario).