Python class - attribute inheritance - python

I am trying to implement a project using class inheritance, where parent class is:
class radio:
def __init__(self, artist=None, track=None, genre=None):
self.artist = artist
self.track = track
self.genre = genre
then I create methods for each attribute (non working examples):
def seed_artist(self):
results = api.search(q=self.artist, type='artist')
return results
def seed_track(self):
results = api.search(q=self.track, type='track')
return results
def seed_genre(self):
results = api.search(q=self.genre, type='genre')
return results
the user is going to pick a seed above (only one), being it either artist, track, genre or mood, and that's why I initialize all arguments with None, leaving the argument value to be inserted at inheritance level.
the inherited class is:
class playlist(radio):
def __init__(self,user):
radio.__init__(self, artist, track, genre)
lets say user inputs at command line a track seed, and my script ends up starting with a global variable:
track = 'karma police'
this way, all other attributes (artist, genre) remain None.
when I create an instance, say:
jeff = playlist('Jeff Smith')
It will throw an error saying that genre and artist are not defined, and I would have to inherit only trackattribute, like so:
radio.__init__(self, track)
I know I could start the script with global variables defined:
track = None
genre = None
artist = None
and this would allow me to have:
radio.__init__(self, artist, track, genre)
but this seems to me rather redundant...
Is there a workaround this, with no need for initial values of global variables set to None, keeping all the code within class scope definitions?

Instead of using a separate global variable for each field, use a single dictionary for all fields. Then you can pass the dictionary as keyword arguments.
That is, instead of creating a global variable called artist, create a dictionary called radio_fields or something. When the user inputs their query, set a key on this dict:
radio_fields = {}
...
# when you get the user's command
radio_fields['track'] = 'Karma Police'
Now you can call radio.__init__(self, **radio_fields). This will pass as arguments whatever keys are in radio_fields. If there is only one, only that one will be passed, and the others will take their default values as you defined them when you defined radio.__init__.
There might be a better way to structure your overall program, but it's hard to say based on what you've shown here. For instance, it's unclear why playlist only accepts one user argument. If playlist accepted all the field arguments that radio accepted, it could pass them on to radio without any problem.

You don't have those variables to pass, so don't try and pass them. The parent class already has defaults for them, so just pass the one you need:
radio.__init__(self, artist=artist)

Related

Best Practice in Python: Class Object with helper variables - delete helpers after use

I want to have a Class with only one argument to it. Based on that argument a couple of calculations should take place aiming at setting a specific attribute for the Class. Other attributes won't be needed afterwards and I would like to delete them within the Class. What's the best approach?
Simplified Example:
class Sportsteam:
def __init__(self, members):
self.members = members # members will be a list
self.num_members = len(self.members) # helpler variable: how many team members are in the sportsteam?
self.rooms = math.ceil(self.num_members/2) # how many doubles will be needed in a hotel?
I want to delete the instance variable num_members because it won't be needed afterwards. I want that to be done within the class/object, so I do not need a separate line with del instance.num_members within my script for each instance.
Please note that variable assigning is more complex with a lot of conditions in the original use case. Calculation without the helper-variable would work in the example above, but would be really annoying in the use case.
As #monk pointed out, also local variables can be assigned within the __init__ statement. For above example the use of a helper variable would therefor be:
class Sportsteam:
def __init__(self, members):
self.members = members # members will be a list
num_members = len(self.members) # helper variable: how many team members are in the sportsteam?
self.rooms = math.ceil(num_members/2) # how many doubles will be needed in a hotel?
In this case instance.num_members does not exist.
I was researching for an answer to my question with different keywords for quite a while, but neither came to a solution nor to an example which showed that possibility

How to get class instanced using variable inside of the class

I am trying to access a class instance. I can't assign the class to a variable when I load it and then use it because I need to access the class based on what the user enters.
i.e: user goes to link website.com/classes/y, I need to access the instance with the name y.
I already handle the link and can get "y" or whatever the user entered by itself.
I have the class code as follows:
class LoadModel:
existing_models = []
def __init__(self, model_path):
self.name = model_path.parent.name
self.__class__.existing_models.append(self.name)
For now, I can verify if the class exists using the existing_models list, but how will I be able to access it using the self.name?
I want to access it using LoadModel.name.
It sounds like you want to keep a dictionary of model names to instances. You could do that with something like:
class LoadModel:
modelsByName = {}
def __init__(self, model_path):
self.name = model_path.parent.name
self.modelsByName[self.name] = self
Furthermore if you wanted to access an instance named name as LoadModel.name you could could add
setattr(self.__class__, self.name, self)
to __init__. Or if you were looking up by string (which it sounds like you might be) then you would just do LoadModel.modelsbyName[name].
Note also that you don't need to use self.__class__ when accessing members of the class that you have not assigned within the instance, and since you're only accessing the dictionary object defined in the class, you can use the reference inherited by the instance (self.modelsByName) instead of accessing the class explicitly (self.__class__.modelsByName).

how to combine singleton and factory design pattern with python?

Suppose there are several presses, each one published many books
I am going to handle many records like 'press name, book name'
I want create the class 'Press' by a unique name(string), but only different string can produce different instances of class 'Press'.
so, I need a class work like 'factory', create a new instance when a record contains a new press, but it also work as singleton if there are already exists which has the same names.
You could create a dict with the unique names as keys and Press objects as values. This doesn't need to be a global dict. You can wrap it in some class like that:
class Press:
def __init__(self, name):
self.name = name
self.books = []
class PressManager:
presses = {}
#classmethod
def get_press(cls, name):
if name not in cls.presses:
cls.presses[name] = Press(name)
return cls.presses[name]
example_press = PressManager.get_press("Test")
I implemented get_press() as a class method, because I think this is what you had in mind.

Why Assign Class Fields Outside Constructor

I recently saw code that assigns a list to an object's field after the constructor is invoked.
# Inside the "Block" class definition
def __init__(self, name, access, address=None):
ModuleBS.__init__(self, name, address)
self.access = access
self.mem_list = []
# Calling the constructor
tmp_blk = Block(block_name, name, access, sys_addr)
tmp_blk.mem_list = memory_list ## assignment occurs after constructor invoked
Is there a reason for this? Why would this be preferred over initializing mem_list inside the constructor instead, passing memory_list as a constructor argument?
Thanks
First things first, mem_list IS being initialised in class' __init__:
# Inside the "Block" class definition
def __init__(self, name, access, address=None):
...
self.mem_list = []
Later call was just an value change - some would just use append() or insert(), some would just pass existing list.
As for your second question, it's perfectly okay to do it both way - I'm mostly writing my classes that way I can initialise some variable with class call, with a simple check to see if data passed is valid, and later change that variable on demand - as long as I my init method's doesn't have a bunch of parameters.
In that case it may be just simpler to initialise a class with only necessary fields (with some 'default' values for other) and later just change those values directly.

Calling type(dict) functions within classes on class variables (Python 3.4)

I am creating a class and trying to define class variables that correspond to a function like .keys() or .values() that are called on another class variable.
For example:
class DATA(object):
def __init__(self, id, database = {}):
self.id = id
self.database = database
self.addresses = database.keys()
self.data = database.values()
This does not seem to work, as when I create an instance of the class
foo = DATA(0,{"a":1,"b":2})
and then ask for:
print(foo.addresses)
>>> []
and it gives back an empty list.
Note:
On my actual program I start out with an empty dictionary for any class instance, then later on I use a function to add to the dictionary. In this case calling the ".database" still works but ".addresses" does not.
Can anyone help me with this problem?
I'm not sure that this is the problem, but using a mutable such as {} as a default argument often leads to bugs. See: "Least Astonishment" and the Mutable Default Argument
This is safer:
def __init__(self, id, database=None):
if database is None:
self.database = {}
else:
self.database = database
I don't understand the purpose of DATA.addresses and DATA.data. Could you use functions with the property decorator instead, to avoid redundancy?
#property:
def addresses(self):
return self.database.keys()
#property:
def data(self):
return self.database.values()
The issue is that you're calling keys right in your __init__ method, and saving the result. What you want to do instead is to call keys only when you want to access it.
Now, depending on the requirements of your class, you may be able to do this in a few different ways.
If you don't mind exposing changing the calling code quite a bit, you could make it very simple, just use foo.database.keys() rather than foo.addresses. The latter doesn't need to exist, since all the information it contains is already available via the methods of the databases attribute.
Another approach is to save the bound instance method database.keys to an instance variable of your DATA object (without calling it):
class DATA(object)
def __init__(self, database=None):
if database is None:
database = {}
self.database = database
self.addresses = database.keys # don't call keys here!
In the calling code, instead of foo.addresses you'd use foo.addresses() (a function call, rather than just an attribute lookup). This looks like a method call on the DATA instance, though it isn't really. It's calling the already bound method on the database dictionary. This might break if other code might replace the database dictionary completely (rather than just mutating it in place).
A final approach is to use a property to request the keys from the database dict when a user tries to access the addresses attribute of a DATA instance:
class DATA(object)
def __init__(self, database=None):
if database is None:
database = {}
self.database = database
# don't save anything as "addresses" here
#property
def addresses(self):
return self.database.keys()
This may be best, since it lets the calling code treat addresses just like an attribute. It will also work properly if you completely replace the database object in some other code (e.g. foo.database = {"foo":"bar"}). It may be a bit slower though, since there'll be an extra function call that the other approaches don't need.

Categories

Resources