简体   繁体   中英

How to return with a python method A NEW class object?

I have some questions with respect to the not working code below:

  1. How to make a method search return a New Database object?
  2. Can __init__ take as an argument a schema and a list (which is a list of dictionaries - where I do my search)?
  3. How to avoid writing similar function in search method again and again, cause there are a lot of field names in the database.

Thanks in advance for your help.

class DataBase():  
# Searches Movies by title and gives its entire info :( (stupid)
def __init__(self, movies, schema):
    pass


def search(self, field_name, field_value1, field_value2=None):
    if field_name=='title':
        mov=[]
        for movie in movies:
            if field_value1 == movie['movie_title']:
                mov.append(movie)
        return mov

    if field_name=='year':
        for movie in movies:
            if field_value2:
                if movie['title_year'] in range (field_value1, field_value2+1):
                     return movie['movie_title'],movie['title_year']

            else:
                if movie['title_year']==field_value1:
                     return movie['movie_title'],movie['title_year']

    if field_name=='actor_1_name':
        mov=[]
        for movie in movies:
            if field_value1 == movie['actor_1_name']:
                mov.append(movie)
        return mov
        **strong text**

It isn't really clear what you are trying to do, and it is hard to interpret without an example of the inputs and the desired result but this might be close.

class DataBase():  
    def __init__(self, movies, schema):
        self.movies = movies
        self.schema = schema

    def search(self, field_name, field_value1, field_value2=None):
        search_result = []
        for movie in self.movies:
            if field_value2:
                if movie[field_name] in range((field_value1, field_value2+1)):
                    search_results.append(movie)
            else:
                if movie[field_name] == field_value1:
                    search_results.append(movie)

        return DataBase(search_results, self.schema)

You might even want to simplify the comparisons in the search. you could define helper functions for the (two) different types of comparisons; choose which comparison to use based on the arguments; then use the chosen function in the search.

...

    def search(self, field_name, field_value1, field_value2=None):

        # comparison types    
        def range_comparison(movie, start=field_value1, end=field_value2):
            return movie[field_name] in range(start, end+1)
        def equality_comparison(movie, name=field_value1):
            return movie[field_name] == name

        # which comparison to use    
        comparison = range_comparison if field_value2 else equality_comparison

        search_result = []
        for movie in self.movies:
            if comparison(movie):
                search_results.append(movie)
        # or
        # search_results = [movie for movie in movies if comparison(movie)]
        return DataBase(search_results, self.schema)

For some reason that appeals to me because it separates the logic of the type of comparison from the actual search.


It doesn't account for search_results being empty - no movies found.

  1. To return a DataBase object call DataBase(movies, schema) , where movies and schema are the parameters of the __init__() method of the class.
  2. __init__() can take as many positional parameters as you want, but remember to assign their object to appropriate names inside the __init__() body, so that you can use them later (see the __init__() method on my class).
  3. To avoid repeating the search pattern all over the search() method, just use the field parameter as a key for matching each record on the database, and split the problem in two cases: one for the range search, the other for the plain search (see search() method below). Remember to address the no-match case: in my implementation I just return an empty DataBase object. You should also address the case of invalid search key: in my implementation I return None .

The test() function below provides a database and three searches, both simple and within a range.

You should consider collections.namedtuple as an alternative representation for database records.

class DataBase():

    def __init__(self, movies, schema):
        self.movies, self.schema = movies, schema

    def __str__(self):
        return str(self.movies)

    def search(self, field, from_value, to_value=None):
        if field in self.schema:
            matches = []
            if to_value:
                for movie in self.movies:
                    if movie[field] in range(from_value, to_value):
                        matches.append(movie)
            else:
                for movie in self.movies:
                    if movie[field] == from_value:
                        matches.append(movie)
            return DataBase(matches, self.schema)
        else:
            return None

def test():
    schema = [ "title", "year", "rating" ]
    movies = [
        { "title":"Star Wars: The Empire Strikes Back",       "year":1980, "rating":3 },
        { "title":"Serenity",                                 "year":2005, "rating":5 },
        { "title":"Scarface",                                 "year":1983, "rating":4 },
        { "title":"Harry Potter and the Philosopher's Stone", "year":2001, "rating":2 },
        ]

    db = DataBase(movies, schema)
    print(db.search("title", "Scarface"))
    print(db.search("year", 2000, 2008))
    print(db.search("rating", 4, 6))
    print(db.search("title", "The Last Emperor"))
    print(db.search("invalid", "value"))

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