Reputation: 317
Is it possible to change something in the init function of a class?
Lets say I have a class called "deck" which, when initialized, creates a list of 52 card objects.
Now I want to make another class called "even" which inherits from "deck" class and creates a deck of card objects BUT eliminates all cards with a number 2 (so spades, hearts, etc) from the inherited "deck".
I have been having a lot of trouble with this because when I try to modify the inherited list, regardless of what I try, python will return an error, usually with 'NoneType' being the main root of the problem. Here is the code for the "even" class init:
def __init__(self):
x = Deck.__init__(self)
for card in x:
if card.rank() == 2:
x.pop(card)
return x
It is worth noting that my card class has a method rank() which will return the rank of the card as an int.
Regardless of all the things I have tried, there is always something wrong with it. Sometimes it will say "'NoneType' object is not iterable" or "subscripable" and when I check the type() of x it is a NoneType. I have done a lot of searching around but nothing is making sense to me about NoneType or what I should do to fix it.
If I remove the for loop then the code will create a deck of 52 cards as expected, but I need to filter out the 2's for example.
Edit: this is my deck class init:
class Deck(list):
def __init__(self):
return list.__init__(self, [Card(i) for i in range(52)])
If you cant tell, Card is also a class and the init of deck creates 52 card objects
Upvotes: 1
Views: 2954
Reputation: 7842
So assuming a simple version of your Deck
baseclass, inheriting an modifying the list of cards stored in the baseclass could be done something like:
# simple baseclass that contains a list of Card objects
class Deck(object):
def __init__(self):
self.deck = [...] # some list of cards
# a class to hold only even cards
class Even(Deck)
def __init__(self):
# use super to instantiate the baseclass
super(Even,self).__init__(self)
# create a local instance of `deck` that contains only even cards
# the base set of cards can still be acessed via super(Even,self).deck
self.deck = [card for card in self.deck if card.rank() != 2]
EDIT: updating for the added information in the question:
class Deck(list):
def __init__(self):
super(Deck,self).__init__([Card(i) for i in range(52)])
class Even(Deck)
def __init__(self):
super(Even,self).__init__(self)
[self.remove(card) for card in self if card.rank()==2]
Upvotes: 5
Reputation: 251373
Given the way you're doing things in Deck
, what you would have to do in your subclass is:
def __init__(self):
Deck.__init__(self)
self[:] = [card for card in self if card.rank() != 2]
Since your object inherits from list
, it is a list, and so you can modify it by assigning directly to a slice.
However, this is probably not the best way to design your class. Instead of inheriting from list
, it is usually easier to store a list internally and modify it to do what you want.
Note that you should not return anything from __init__
. __init__
does not return the value of the object; it is supposed to modify self
to set whatever it wants, and always return None. The only reason you're getting away with returning in Deck
is that you return the value of a superclass __init__
, which itself returns None as a good __init__
should.
Upvotes: 2