list as Python class variable - python

I want a class "Library" which has a class variable "books" which is a list of all the books in the library. So may class begins
class Library:
books = []
Now I want to add a book to my collection, but I can find no syntax
to do so. The model I have in my head is something like
def addBook(self, book):
books.append(book)
which I would expect to call with something like from the main routine with something like
lib = Library()
b = Book(author, title)
lib.addBook(b)
However, I've not been able to find any way to do this. I always get an error with the "append" where I try to add the book to the list.

You should declare books as an instance variable, not a class variable:
class Library:
def __init__(self):
self.books = []
def addBook(self, book):
self.books.append(book)
so you can create an instance of Library:
lib = Library()
b = Book(...)
lib.addBook(b)
Notes:
For further information about self , you can read this post.
This assumes your Book class is implemented correctly.

class Library():
def __init__(self):
self.books = []
def addBook(self, book):
self.books.append(book)

look at this example for the initialization and the setter:
class Library:
def __init__(self):
self.books = []
def add(self, x):
self.books.append(x)

Related

python polymorphism class and function

i am start to learn how to write python code
There is an option to write code ones onthis situation?
i want to crate class and 2 class how extend from her and i want to check if i can loop on only ones my example:
class animal:
def printDetail(self):
print(self.name)
class bird(animal):
def printDetail(self):
super(bird, self).printName()
print(self.wingsSize)
class fish(animal):
def printDetail(self):
super(fish, self).printName()
print(self.weight)
fishList = []
birdList = []
animalList = []
def main():
for a in (animalList,fishList,birdList):
a.printDetail()
main()
when i try to do it i got an error that AttributeError: 'list' object has no attribute 'printDetail' like this is an unknow function. i understand that it try to take the attribute of the list class but there is any option that i can do it more esear then:
for a in animalList:
a.printDetail()
for a in fishList:
a.printDetail()
for a in birdList:
a.printDetail()
that is work fine but to long?
The first code snippet creates a 3-tuple of lists. You're invoking .printDetail() on every list in that tuple.
To create a list that contains the elements from each list (as opposed to a list that contains the lists themselves), you can use for a in (animalList + fishList + birdList):
As others have already answered, there are a variety of quick ways to do this. I prefer the unpacking method that Wups uses in his answer.
However, I also wanted to check if we needed to add initializations to each of these classes in order for the print to work. Further, I was thinking when you called printName in some methods, you meant printDetail instead (maybe I am wrong?). Thus I also revised the class code also, I hope it may benefit you and others who may want to run the code and see a result:
class animal:
def __init__(self, name):
self.name=name
def printDetail(self):
print(self.name)
class bird(animal):
def __init__(self, name, wingsSize):
self.name=name
self.wingsSize = wingsSize
def printDetail(self):
super(bird, self).printDetail()
print(self.wingsSize)
class fish(animal):
def __init__(self, name, weight):
self.name=name
self.weight=weight
def printDetail(self):
super(fish, self).printDetail()
print(self.weight)
fishList = [fish("salmon",12)]
birdList = [bird("eagle",4)]
animalList = [animal("bear")]
def main():
for a in (*animalList, *birdList, *fishList):
a.printDetail()
main()
Output:
bear
eagle
4
salmon
12

Creating a list of class instances

I'm trying to make a simple library system as part of an intro to OOP in Python. I became stuck trying to fit books into my library class. I have made a first simple class, called Book, which makes books, can show their ID, name and price etc.
Now im trying to create the actual class called Library. I want to make a list of all the books in the library with their ID, cost and name. Here I encountered an isseu. I have no idea how to add the instances of the class Book to the list I made in Library, my code can be found down here.
class Library(object):
def __init__(self, book):
self.book = book
def add_item(self, book):
mylist.append(book)
return mylist
if __name__ == '__main__':
booklist = []
Book1 = Book(1, 'Bookname1', "$30")
Book2 = Book(2, 'Bookname2', "$10")
Book1.show()
Book1.get_attribute_string()
and the code for the books, which I would rather keep the same. Ofcourse im open to suggestions, but im not that well versed in OOP in Python yet so don't suggest things to complicated! Thanks.
class Book(object):
def __init__(self, ID, name, price):
self.ID = ID
self.name = name
self.price = price
def show(self):
print(self.ID, self.name, self.price)
def get_attribute_string(self):
print(str(self.ID) + '_' + str(self.name) + '_' + str(self.price))
def get_id(self):
print(self.ID)
def get_name(self):
print(self.name)
def get_price(self):
print(self.price)
The class Library needs an attribute e.g. books. In this list, all books are stored. You need to define it in the __init__method, so you can have multiple libraries with different books.
class Library:
def __init__():
self.books = []
def add_book(book):
self.books.append(book)
def get_books(self):
return self.books
def show_books(self):
# This is one possible example how you can print all books
for book in self.books:
print(str(book))
class Book:
pass # Your Book code
def __str__(self):
return f"{self.name}, {self.id}, {self.price}"
# Returns a string with all attributes of the string.
# Note that is a f-string, but you can use any string
# This function is called, when you call str(book1)
if __name__ == "__main__":
book1 = Book()
book2 = Book()
lib = Library()
lib.add_book(book1)
lib.add_book(book2)
lib.show_books()
all_books = lib.get_books()
also_all_books = lib.books
Your library class should probably contain a collection of books (or something more specific, depends on the details of your task). Here is an example:
class Library(object):
def __init__(self, book):
# collection of library books. This is the library state
self.books = tuple()
def add_item(self, book):
# add an item to the collection
self.books += (book, )
return self.books
I preferred to use an immutable collection so that others can't change the library state outside the class. But you can use a list. You just have to be careful.

Question for the code required to make the def update func in python to actually update something

I'm supposed to make a code for a class called employee, in the class I have: def __init__ (self, iD="", N="", etc..) later on I have to use a method I believe that is called def update and I'm supposed to write a code for that to work to update any information changed on the first one but I have no idea how to write the code in order for the def update to actually work, so could someone please tell me how to do it or guide me through?
class Employee(object):
def __init__(self, iD="", sN="", sL="", sA="", sCity=""):
# missing code
def update(self, iD="", sN="", sL="", sA="", sCity=""):
# what do i code in order for this to work???
The most likable is that your __init__() method contained this:
class Employee(object):
def __init__(self, iD="", sN="", sL="", sA="", sCity=""):
self.iD = iD
self.sN = sN
self.sL = sL
self.sA = sA
self.sCity = sCity
And surely your update() method should go like this:
def update(self, iD="", sN="", sL="", sA="", sCity=""):
self.iD = iD
self.sN = sN
self.sL = sL
self.sA = sA
self.sCity = sCity

python - setting property of class on module loading

I'm working on a code dealing with dict data on python.
While implementing such class, I have to define a lot of properties. It's not that hard, but recently I thought it would be much better if I could use something like helper function.
For example, let's assume that I have a class like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
#property
def version(self):
return self.data["version"]
If I could write this class in something like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
define_own_property("data", "version")
It looks trivial, but if I can do that, I think I can reuse a lot of validation/exception handling cases.
Any idea? :D
You can achieve something like that by just writing a function to return the accessor you want:
def define_own_property(attr, key):
def prop(self):
return getattr(self, attr)[key]
return property(prop)
class MyClass(object):
def __init__(self, data):
self.data = data
version = define_own_property("data", "version")
Note that you must do version = ... There is no way to make a simple function call define_own_property add a property to the class being defined, because that class doesn't yet exist so you can't reference it.
Another possibility is to give your class an attribute that is a list or dict or something containing the relevant parameters ("data", "version", etc.), then write a class decorator that reads these parameters and auto-creates the series of properties. This would remove the need to define the properties inside the class at all; you would just give a list of the things you wanted the properties to access, and use the decorator once on the class.
It seems like you could use a descriptor:
class Descr(object):
def __init__(self,attr,key):
self.attr = attr
self.key = key
def __get__(self,obj,type=None):
return getattr(obj,self.attr)[self.key]
def __set__(self,obj,value):
getattr(obj,self.attr)[self.key] = value
def __delete__(self,obj):
del getattr(obj,self.attr)[self.key]
class MyClass(object):
def __init__(self, data):
self.data = data
version = Descr("data","version")
foobar = Descr("data","foobar")
a = MyClass({})
a.version = 1
print a.version
a.foobar = 'string'
print a.data

Can I iterate over a class in Python?

I have a class that keeps track of its instances in a class variable, something like this:
class Foo:
by_id = {}
def __init__(self, id):
self.id = id
self.by_id[id] = self
What I'd like to be able to do is iterate over the existing instances of the class. I can do this with:
for foo in Foo.by_id.values():
foo.do_something()
but it would look neater like this:
for foo in Foo:
foo.do_something()
is this possible? I tried defining a classmethod __iter__, but that didn't work.
If you want to iterate over the class, you have to define a metaclass which supports iteration.
x.py:
class it(type):
def __iter__(self):
# Wanna iterate over a class? Then ask that class for iterator.
return self.classiter()
class Foo:
__metaclass__ = it # We need that meta class...
by_id = {} # Store the stuff here...
def __init__(self, id): # new isntance of class
self.id = id # do we need that?
self.by_id[id] = self # register istance
#classmethod
def classiter(cls): # iterate over class by giving all instances which have been instantiated
return iter(cls.by_id.values())
if __name__ == '__main__':
a = Foo(123)
print list(Foo)
del a
print list(Foo)
As you can see in the end, deleting an instance will not have any effect on the object itself, because it stays in the by_id dict. You can cope with that using weakrefs when you
import weakref
and then do
by_id = weakref.WeakValueDictionary()
. This way the values will only kept as long as there is a "strong" reference keeping it, such as a in this case. After del a, there are only weak references pointing to the object, so they can be gc'ed.
Due to the warning concerning WeakValueDictionary()s, I suggest to use the following:
[...]
self.by_id[id] = weakref.ref(self)
[...]
#classmethod
def classiter(cls):
# return all class instances which are still alive according to their weakref pointing to them
return (i for i in (i() for i in cls.by_id.values()) if i is not None)
Looks a bit complicated, but makes sure that you get the objects and not a weakref object.
Magic methods are always looked up on the class, so adding __iter__ to the class won't make it iterable. However the class is an instance of its metaclass, so the metaclass is the correct place to define the __iter__ method.
class FooMeta(type):
def __iter__(self):
return self.by_id.iteritems()
class Foo:
__metaclass__ = FooMeta
...
Try this:
You can create a list with a global scope, define a list in the main module as follows:
fooList = []
Then add:
class Foo:
def __init__(self):
fooList.append(self)
to the init of the foo class
Then everytime you create an instance of the Foo class it will be added to the fooList list.
Now all you have to do is iterate through the array of objects like this
for f in fooList:
f.doSomething()
You can create a comprehension list and then call member methods as follows:
class PeopleManager:
def __init__(self):
self.People = []
def Add(self, person):
self.People.append(person)
class Person:
def __init__(self,name,age):
self.Name = name
self.Age = age
m = PeopleManager()
[[t.Name,t.Age] for t in m.People]
call to fill the object list:
m = PeopleManager()
m.Add( Person("Andy",38))
m.Add( Person("Brian",76))
You can create a class list and then call append in the init method as follows:
class Planet:
planets_list = []
def __init__(self, name):
self.name = name
self.planets_list.append(self)
Usage:
p1 = Planet("earth")
p2 = Planet("uranus")
for i in Planet.planets_list:
print(i.name)

Categories

Resources