Python - Inheritance of a composition class - python

I have 2 classes that are a composition. And I would need to extend the functionality of both, so I would need to make use of inheritance from those base classes. Is it possible?
class Book:
def __init__(self):
self.sheets = generate_sheets()
author = ''
def generate_sheets(self):
for index in range(20):
(some_extra code)
self.sheets.append(Sheet(index))
class Sheet:
def __init__(self, idx):
self.id = idx
And I want to create 2 children of the base, and that the composition be between them. It would only possible overwriting the method generate_sheets?
class DefinitionBook(Book):
def __init__(self):
super().__init__()
translator = ''
def generate_sheets(self):
super().__init__()
for index in range(20):
self.sheets.append(DefSheet(index)
class DefSheet(Sheet):
def __init__
super().__init__()
definition = dict()
Or it would be possible to keep part of the code of the method generate_sheets in the child class of Book, and only change the part where is called to the class Sheet/DefSheet?

You could have the class Sheet (and subclasses) you need to use, as a class variable in the class Book (and subclasses); this voids the need to override generate_sheets in the subclasses.
class Sheet:
def __init__(self, idx):
self.id = idx
def __str__(self):
return f"{self.__class__.__name__}"
class Book:
sheet = Sheet
def __init__(self):
self.sheets = []
self.generate_sheets()
def generate_sheets(self):
for index in range(20):
self.sheets.append(self.__class__.sheet(index))
def __str__(self):
return f"{self.__class__.__name__} - {self.sheet.__name__}"
class DefSheet(Sheet):
def __init__(self, idx):
super().__init__(idx)
class DefinitionBook(Book):
sheet = DefSheet
def __init__(self):
super().__init__()
b = Book()
print(b, b.sheets[0])
d = DefinitionBook()
print(d, d.sheets[0])
output:
Book - Sheet Sheet
DefinitionBook - DefSheet DefSheet

Related

Using a variable from one class to another one in python

I want to use a variable from class A for some computation in class B. I,m not sure that I use the self.out from the class A in class B appropriately?
Class A:
class A(nn.Module):
def __init__(self):
super(A, self).__init__()
self.out = func()
Class B:
class B(nn.Module):
def __init__(self):
super(A, self).__init__()
self.result = function_1() + A.self.out
Maybe this is what you need. I made a small example of what I understood.
These "prints" were placed to improve the understanding that Class "C" can fetch any function or variable from the other parent classes.
class A():
def __init__(self):
variable = None
def test(self, number):
return f'another class {number}'
class B():
def __init__(self):
self.data = None
self.out = self.print_data(5)
def print_data(self, number):
return number
def print_elem(self):
return self.data
class C(A, B):
def __init__(self):
super().__init__()
c = C()
print(c.print_data(8))
print(c.out)
c.data = 100
print(c.print_elem())
print(c.test(3))

Python: How do lists within classes work?

I've been trying to practice with classes in Python, and I've found some areas that have confused me. The main area is in the way that lists work, particularly in relation to inheritance.
Here is my Code.
class LibraryItem:
def __init__(self, book_id, name):
self.item_id = book_id
self.name = name
class Library(LibraryItem):
books=[]
def all_books(books):
bookslen = len(books)
return bookslen
def add_book(books):
books.append(self.book_id)
What I'm trying to get the program to do is allow me to store an instance of a book_id and name, which can then be added to the list books[], via the add_books method in the child class Library.
I don't think inheritance is what your looking for here
You have i library and this library contains a list of books. keep it simple.
class Library:
## creates the library
def __init__(self):
self.books = []
## returns number of books
def number_of_books(self):
return len(self.books)
## adds a book to the list of books
def add_book(self, book):
self.books.append(book)
class Book:
## creates your book
def __init__(self, item_id, name):
self.item_id = item_id
self.name = name
localLibrary = Library() # create the library
new_book = Book(1,"Harry Potter") # create the book
localLibrary.add_book(new_book) # add the book to the library
print(localLibrary.number_of_books()) # display the number of books
## output -> 1 book in the library
I think this is what you trying to achieve
class LibraryItem:
def __init__(self, book_id, name):
self.item_id = book_id
self.name = name
class Library:
def __init__(self):
self.books = []
def __len__(self):
return len(self.books)
def add_book(self, book):
self.books.append(book.book_id)
now you can create instance of book and add it to library:
book1 = LibraryItem(1,"To Kill a Mockingbird")
library = Library()
library.add_book(book1)
print(len(library ))

Passing class to class attribute

I have a Cash class (derived from the Instrument class) which has a .manager class attribute. This class attribute (an instance of the Manager class), when it is initialized, needs to receive the class to which it is attached, as per below.
class Manager:
def __init__(self, instrument):
self.instrument = instrument #instrument is a class (a type)
def get(self, *args, **kwargs):
return self.instrument(30.99) #return an instance (e.g. ORM-like operation)
class Instrument:
pass
class Cash(Instrument):
manager = Manager(Cash) #this fails... as Cash isn't defined yet
def __init__(self, amount):
self.amount = amount
How do we achieve this, i.e. pass one's class to one of its own class attributes at definition?
If you have circular class/attributes, you can use functions that you call after instantiation, in my example add_A and add_B :
class A:
def __init__(self):
self.foo = 1
def add_B(self, b):
self.b = b
class B:
def __init__(self):
self.bar = 2
def add_A(self, a):
self.a = a
a = A()
b = B()
a.add_B(b)
print(a.b.bar)
# 2
b.add_A(a)
print(b.a.foo)
# 1

Python: Is it possible to merge two __init__ after multiple inheritance?

I want my class Parents(Mom, Dad) to inheritance init attributes from two previous classes so then my input will require me to write mom_name and dad_name. Can someone suggest me how to do this?
class Mom(object):
def __init__(self, mom_name):
self.mom_name = mom_name
class Dad(object):
def __init__(self, dad_name):
self.dad_name = dad_name
class Parents(Mom, Dad):
pass
par = Parents('Mom', 'Dad')
print(par.mom_name)
print(par.dad_name)
you can implement it this way
class Mom(object):
def __init__(self, mom_name):
self.mom_name = mom_name
class Dad(object):
def __init__(self, dad_name):
self.dad_name = dad_name
class Parents(Mom, Dad):
def __init__(self, mom_name, dad_name):
Mom.__init__(self, mom_name)
Dad.__init__(self,dad_name)
par = Parents('Mom', 'Dad')
print(par.mom_name)
print(par.dad_name)
output
Mom
Dad
Like this.
class Parents(Mom, Dad):
def __init__(self, mom_name, dad_name):
super(Mom, self).__init__(mom_name)
super(Dad, self).__init__(dad_name)
Edit 1 :
The code above doesn't work, a suitable way will be to subclass Dad from Mum and then paste it to parents like this.
class Mom(object):
def __init__(self, mom_name):
self.mom_name = mom_name
class Dad(Mom):
def __init__(self, dad_name, **kw):
self.dad_name = dad_name
super(Dad, self).__init__(**kw)
class Parents(Dad):
def __init__(self, mom_name, dad_name):
super(Parents, self).__init__(mom_name=mom_name, dad_name=dad_name)
p = Parents("mumy", "dady")
print(p.mom_name)
print(p.dad_name)

Python: sharing variables between contained class

Is there a way to share member variables between a class and a nested class ?
for example
class Base(object):
class __Internal(object):
def __init__(self, parent):
self.__parent = parent
self.__parent.__private_method()
#
def __init__(self):
self.__internal = Base.__Internal(self)
return
def __private_method(self):
print "hurray"
return
if name == "main":
b = Base()`
is there a way for the __Internal class to access members of the parent class ?
iam looking for private members like parent.__vars/__methods .
I have edited the code to better explain this. running this code throws
AttributeError: 'Base' object has no attribute '_Internal__private_method'
To access privete method, instead of this:
self.__parent.__private_method()
use this:
self.__parent._Base__private_method()
Modified your example:
class Base(object):
class __Internal(object):
def __init__(self, parent):
self.__parent = parent
self.__parent._Base__private_method()
def __init__(self):
self.__internal = Base.__Internal(self)
return
def __private_method(self):
print "hurray"
return
if __name__ == "__main__":
b = Base()
It results in:
hurray
You must use BaseClassName.methodname(self, arguments) or BaseClassName.field
Example (very ugly code):
class Base(object):
some_field = "OK"
class Internal(object):
def __init__(self, parent):
self.__parent = parent
def change_some_field(self):
Base.some_field = "NOP"
def __init__(self):
self.__private = "val"
self.__internal = Base.Internal(self)
def show_field(self):
print self.some_field
def change_some_field(self):
self.__internal.change_some_field()
def main():
a = Base()
a.show_field()
a.change_some_field()
a.show_field()
return 0
if __name__ == '__main__':
main()
You can find a very useful resources at Why are Python's 'private' methods not actually private?

Categories

Resources