我最近一直在用Python学习编程,并且得到了在OOP中对库进行编程的任务。您可以将图书添加到图书馆,根据ISBN,作者姓名或价格便宜的图书搜索特定的图书。一切似乎都还可以,但是我是OOP的新手,所以我想听听关于是否将其编程为“好方法”的一些建议。

#1 楼


您的设计没有遵循最佳实践。当您使用Library时,您的__init__类应该创建一个库,而不是一本书。
所以我将代码分成两半,创建了两个类。一个用于书籍,另一个用于图书馆。
您不应该对Library上的数据进行突变。这是因为它是在类上而不是在实例上对其进行突变。因此,如果创建一个新实例,则它将与所有其他实例绑定。

制作book类时。使用collections.namedtuple可以大大简化此操作。例如:

Book = namedtuple('Book', 'name author ISBN price')



所以我将您的代码更改为:

from collections import namedtuple


class Library(object):
    def __init__(self):
        self.books = []

    def addBook(self, book):
        self.books.append(book)

    def searchBookISBN(self, ISBN):
        for book in self.books:
            if book.ISBN == ISBN:
                return book

    def searchBookAuthor(self, author):
        written_by_author = []
        for book in self.books:
            if book.author == author:
                written_by_author.append(book)
        return written_by_author

    def searchUnderPrice(self, price):
        books_under_price = []
        for book in self.books:
            if book.price < price:
                books_under_price.append(book)
        return books_under_price


Book = namedtuple('Book', 'name author ISBN price')

library = Library()
library.addBook(Book('Geometry', 'Jeff Potter', '0596805888', 22))
library.addBook(Book('Math', 'George Harr', '0594805888', 15))
library.addBook(Book('English', 'James Odd', '0596225888', 10))
library.addBook(Book('Physics', 'Jeff Potter', '0597884512', 18))
print(library.searchBookISBN('0594805888'))
print(library.searchBookAuthor('George Harr'))
print(library.searchUnderPrice(20))



之后,我建议:


您阅读并遵循PEP 8,以便您的代码更易于阅读。
您将学习列表理解


可以进一步改善您的代码,以:

class Library(object):
    def __init__(self):
        self.books = []

    def add_book(self, book):
        self.books.append(book)

    def book_with_ISBN(self, ISBN):
        for book in self.books:
            if book.ISBN == ISBN:
                return book

    def books_by_author(self, author):
        return [book for book in self.books if book.author == author]

    def books_under_price(self, price):
        return [book for book in self.books if book.price < price]


评论


\ $ \ begingroup \ $
通过保留字典以通过ISBN或作者进行搜索来进行O(1)查找也很方便。
\ $ \ endgroup \ $
–地狱
17年11月24日在13:11

\ $ \ begingroup \ $
@Graipher是的,您可以随时提出答案。 🙂我觉得我们不知道如何使用代码,所以过早的优化可能不是一个好主意
\ $ \ endgroup \ $
– Peilonrayz
17年11月24日在13:21

\ $ \ begingroup \ $
完成。我同意过早的优化,但是总的来说,我希望图书馆有三本以上的书:)
\ $ \ endgroup \ $
–地狱
17年11月24日在13:55

\ $ \ begingroup \ $
@Graipher我也是,但是这听起来像是一个作业问题。里面只有四本书。因此,IMO的维护成本将超过速度收益。否则,我会完全同意,也对您的答案+1。
\ $ \ endgroup \ $
– Peilonrayz
17年11月24日14:18



\ $ \ begingroup \ $
您还可以使books_by_author和books_under_price生成器函数或返回filter()。
\ $ \ endgroup \ $
–理查德·诺伊曼(Richard Neumann)
17年11月24日14:29



#2 楼

这是Peilonrayz出色答案的附录。

根据您的图书馆规模的增长,可以线性搜索书籍以找到特定的作者或ISBN(甚至是价格较低的书籍)。很长一段时间(显然它会增长\ $ \ mathcal {O}(n)\ $)。

所以您可以为ISBN和周围的作者保留一本字典,以快速找到合适的书:

from collections import defaultdict

class Library(object):
    def __init__(self):
        self.books = []
        self.index_from_author = defaultdict(list)
        self.index_from_isbn = {}

    def add_book(self, book):
        self.books.append(book)
        index = len(self.books) - 1
        self.index_from_author[book.author].append(index)
        self.index_from_isbn[book.ISBN] = index

    def book_with_ISBN(self, ISBN):
        return self.books[self.index_from_isbn[ISBN]]

    def books_by_author(self, author):
        return [self.books[i] for i in self.index_from_author[author]]

    ...


这是假定每个ISBN仅存在一本书(不是不合理的假设),但是一个作者可以拥有多本书(也是合理的)。 br />
请注意,如果您要从图书馆中删除一本书,则该代码还需要处理从这两个词典中删除它。棘手的。您可以使用线性时间,也可以将书堆放在堆中,堆按价格排序。然后,您可以将书插入正确的位置,并可以对所有低于某个价格的书进行二进制搜索。但这要涉及更多一点,我现在没有时间为此编写示例解决方案。

#3 楼

由于缺乏面向对象风格的想象力,因此实现存在问题。有了更多的经验,您将有更好的想法。 ;)

OOP主要是关于对象的。您创建的内容看起来就像是图书馆。我不认为Book正在扩展Library。相反,(从我的角度来看)库包含许多Books。

建议该应用程序可以包含两个类。图书馆和书。

让我们迭代创建该应用程序。

第一次迭代为您提供对象


创建类包含名称,作者,ISBN,价格
创建类库,其中包含书籍集合(集合,列表)或数组

现在拥有的-您可以从图书馆中获取书籍(如果知道要购买哪本书)。

第二次迭代带来了新方法

想要的方法是add bookssearch for ISBNsearch by authors namefinding lower priced books。好吧,这些可能是不同集合上的其他功能。

由于我的首选语言是Java,所以我只给出建议:



放在图书馆的图书集中之首

Add books可以很好地用于地图(ISBN,书)

search for ISBN可以很好地用于MultiMap(作者名,书)


参数:名字和姓氏,甚至出生的年份。.




(价格,书)

第三次迭代将用于优化

基本上可以找到实现的更好想法。无需将Book添加到3个不同的馆藏中。相反,最好将Book添加到一个集合中并从不同的集合中进行查询。在bookMap上(以获取Book而不只是ISBN)。

我使用这些Maps的原因:

HashMap是search for authors name(又称即时),同时具有良好的哈希函数和大小。

TreeMap使用合理的finding books with lower price对键进行了排序,因此仅遍历书籍,直到可以解决问题为止。最后一步,我选择了最简单的情况。

#4 楼

就我个人而言,我将对其进行更多的抽象,并从一个书籍类开始,该类具有有关该特定书籍的所有信息,然后是一个图书馆类,该类将所有书籍集中在一起并进行处理。甚至可能有一个用户类,其中包含每个用户的信息