简体   繁体   中英

Can I turn these two almost identical functions into one in python?

I have these two functions which are nearly identical apart from the if statement in search_genre, is there any way to combine them into one?

The books variable is a dictionary where each value is a list of dictionaries, ie:

books = {'Genre1':[{name:value, author:value}, {dict}], 'Genre2':[{dict}], and so on}

view_library() prints all the books and search_genre() takes a user input to print all books of a specific genre

def view_library():
    for genre in books:
        print(f'Genre: {genre}')
        for book in books[genre]:
            for key, value in book.items():
                print(f"{key.title()} : {value.title()}")
            print()


def search_genre(genre_type):
    for genre in books:
        if genre_type == genre:
            print(f'{genre_type}:')
            for book in books[genre_type]:
                for key, value in book.items():
                    print(f"{key.title()} : {value.title()}")
                print()

Try:

def search_genre(genre_type=None):
    for genre in books:
        if genre_type is None or genre_type == genre:
            print(f'{genre_type}:')
            for book in books[genre_type]:
                for key, value in book.items():
                    print(f"{key.title()} : {value.title()}")
                print()

The difference between the 2 functions is that in the first, all genres are processed, while in the second only the chosen on is.

The key is the if statement that determines whether the genre is printed: right now, it only fires if the genre matches the provided genre. We can add an or so that it also fires if no genre_type is provided. Now, if we call the function without a genre_type argument, it will print all genres:

def search_genre(genre_type=None):
    for genre in books:
        if not genre_type or genre_type == genre:
            print(f'{genre_type}:')
            for book in books[genre_type]:
                for key, value in book.items():
                    print(f"{key.title()} : {value.title()}")
                print()

Since you don't provide a MCVE of data, here's a simplified example with data to show how it works:

def test(x=None):
    for y in z:
        if not x or x == y:
            print(y)

z = [1,2,3,4,5,6]

test()
1
2
3
4
5
6

test(5)
5

Start by implementing filter_by_genre using a filter. It's basically the same as search_genre .

def filter_by_genre(genre_type):
    for genre in filter(lambda x: x == genre_type, books):
        print(f'{genre_type}:')
        for book in books[genre]:
            for key, value in book.items():
                print(f"{key.title()} : {value.title()}")
            print()

filter_by_genre("mystery")

Now, instead of passing a genre as an argument, pass a predicate:

def filter_by_genre(p):
    for genre in filter(p, books):
        print(f'{genre_type}:')
        for book in books[genre]:
            for key, value in book.items():
                print(f"{key.title()} : {value.title()}")
            print()

filter_by_genre(lambda x: x == "mystery")

Both view_library and search_genre can then be implemented in terms of filter_by_genre :

def view_library():
    return filter_by_genre(lambda x: True)


def search_genre(genre_type):
    return filter_by_genre(lambda x: x == genre_type)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM