Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict type of elements of list

Tags:

python

I am new to python, but I have some knowledge of Java. Here I have my first python code :

class Movie(object):
    def __init__(self, name, year):
        self.name = name
        self.year = year

    def tostring(self):
        return "%s (%s)" % (self.name,self.year)

    def __str__(self):
        return self.tostring()


class MoviesCollection(object):
    def __init__(self):
        self.colection = []

    def add_movie(self, movie):
        self.colection.append(movie)

    def __iter__(self):
        return iter(self.colection)

    def __str__(self):
        return '\n'.join(map(str, self.colection))


filmy = MoviesCollection()
a = Movie('A', 256)
b = Movie('B', 512)
c = Movie('C', 1024)

filmy.add_movie(a)
filmy.add_movie(b)
filmy.add_movie(c)
filmy.add_movie(c)
filmy.add_movie(c)
filmy.add_movie(c)
#filmy.add_movie('Aloha')

for m in filmy:
    print m.tostring()

print filmy

Now this works well, but as I uncoment the line from the bottom I will have some runtime errors as I am calling a tostring() method on str type object. And here is the question. How can I prevent inserting such object of different type than Movie into colection ? The Java guy in me would make that list colection like this:

List<Movie>

Also I could put a condition there to add_movie function like this :

if isinstance(movie, Movie): 

but isn't there any other way ?

like image 487
Lubos Mudrak Avatar asked Feb 11 '23 07:02

Lubos Mudrak


2 Answers

In Python - you are expected to behave appropriately and don't do things that don't make sense. This is part of the flexibility of a language that was designed for teaching and scientists, and doesn't put too much emphasis on types, or "object contracts" and other such fluff.

The way you would write your code by taking all the "Java" out of it is:

class Movie(object):
    """ A movie, thing to spend a few hours
        watching, then a few hours hating yourself
        over watching it. """

    def __init__(self, name, year):
        self.name = name
        self.year = year

    def __str__(self):
        return '{} ({})'.format(self.name, self.year)

movie_collection = [Movie('Titanic', 1997), Movie('Showgirls', 1995)]
for movie in movie_collection:
     print(movie)
like image 104
Burhan Khalid Avatar answered Feb 13 '23 21:02

Burhan Khalid


In the Python world Java is sometimes affectionately referred to as a "bondage" language. There are two fundamentally different programming language philosophies: one group seeks to make it harder to write bad programs (Java), the other strives to make it easier to write good programs (Python). Neither is completely successful, because it is possible to write bad programs in any language.

Overall, in Python we prefer to write our code so that only Movie objects are added to the list, rather than take the time to verify that every element put on the list is a Movie. Unit tests can be used to verify this in a given number of cases, but this will never give you the assurance you seek.

Type checking of the nature you suggest is possible, but generally held to be unnecessary or even "unPythonic".

like image 28
holdenweb Avatar answered Feb 13 '23 21:02

holdenweb