I have a class called House()
To make a new instance of House I can pass data like
house = House(roof = roof)
To standardize how Houses get created (and make use of type annotations) House has a .new() static method that looks like:
class House():
#staticmethod
def new(roof: Roof):
house = House(roof = roof)
# do other stuff for new method, ie may add to session, etc.
return house
However, this is kind of annoying because if house has say 10 attributes, it means there's a lot of copy and paste. For example here, to use keyword args (which is preferred), 'roof' is repeated 3 times.
Docs states that __init__ is not called when recreating, but I feel a bit strange over riding it for a .new() method or is this correct?
Also I feel like __init__ doesn't really solve the generic concern. I'm looking for the best of both worlds, where the existing defined properties are available on init, but I can also define logic that's different for each class.
Thinking along the lines of attributes from kwargs maybe but not exactly it?
An assumption is that there will always be some attributes that are not needed. Part of this is enforcing that say a house always needs a roof, but an attribute like owner doesn't need to be populated when it's first created. But if a new developer joins the team and calls House.new() they should be able to see that definition of what attributes are needed.
For example I can pass roof = Column(..., default = 1)
is there a way in Column or similar to say something like required?
Related
not sure about the proper wording for that, but essentially what I would like to ask is if it is possible in python do something like this:
class Customer:
self.name = 'Freddy'
#reportMarketing
self.surname = 'Krueger'
self.eyes = 'Blue'
#reportMarketing
self.address = 'Elm Street'
#reportAccounting
self.tax_id = '8ab9a66cf'
...
where #reportMarketing and #reportAccounting would be decorators (of sorts). The idea is that an instance like the one above could be then passed to some 'reporting class' that - based on whether the instance's attribute is decorated with #reportMarketing or a #reportAccounting, would then consider it for a specific 'reporting'. For instance, imagine you have customers database with instances like the one above, and you want data/attributes decorated with reportMarketing to be included in a report that goes to your marketing department, while the data/attributes decorated with reportAccounting to be included in a report that goes to your accounting department.
I guess conceptually, my question is can I even have decorators for attributes? I understand they are 'typically' (always?) meant for functions.
Also, to give more background, the classes I deal with have plenty of attributes (each), so going through all of them manually is quite error-prone, and so I thought dealing with it by simply decorating the couple of ones I'm after, is the cleanest and most extensible in the future.
I have a data engineering program that is grabbing some data off of Federal government websites and transforming that data. I'm a bit confused on whether I need to use the 'self' keyword or if it's a better practice to not use a class at all. This is how it's currently organized:
class GetGovtData():
def get_data_1(arg1=0, arg2=1):
df = conduct_some_operations
return df
def get_data_2(arg1=4, arg2=5):
df = conduct_some_operations_two
return df
I'm mostly using a class here for organization purposes. For instance, there might be a dozen different methods from one class that I need to use. I find it more aesthetically pleasing / easier to type out this:
from data.get_govt_data import GetGovtData
df1 = GetGovtData.get_data_1()
df2 = GetGovtData.get_data_2()
Rather than:
from data import get_govt_data
df1 = get_govt_data.get_data_1()
df2 = get_govt_data.get_data_2()
Which just has a boatload of underscores. So I'm just curious if this would be considered bad code to use a class like this, without bothering with 'self'? Or should I just eliminate the classes and use a bunch of functions in my files instead?
If you develop functions within a Python class you can two ways of defining a function: The one with a self as first parameter and the other one without self.
So, what is the different between the two?
Function with self
The first one is a method, which is able to access content within the created object. This allows you to access the internal state of an individual object, e.g., a counter of some sorts. These are methods you usually use when using object oriented programming. A short intro can be fund here [External Link]. These methods require you to create new instances of the given class.
Function without self
Functions without initialising an instance of the class. This is why you can directly call them on the imported class.
Alternative solution
This is based on the comment of Tom K. Instead of using self, you can also use the decorator #staticmethod to indicate the role of the method within your class. Some more info can be found here [External link].
Final thought
To answer you initial question: You do not need to use self. In your case you do not need self, because you do not share the internal state of an object. Nevertheless, if you are using classes you should think about an object oriented design.
I suppose you have a file called data/get_govt_data.py that contains your first code block. You can just rename that file to data/GetGovtData.py, remove the class line and not bother with classes at all, if you like. Then you can do
from data import GetGovtData
df1 = GetGovtData.get_data_1()
Depending on your setup you may need to create an empty file data/__init__.py for Python to see data as a module.
EDIT: Regarding the file naming, Python does not impose any too tight restrictions here. Note however that many projects conventionally use camelCase or CapitalCase to distinguish function, class and module names. Using CapitalCase for a module may confuse others for a second to assume it's a class. You may choose not to follow this convention if you do not want to use classes in your project.
To answer the question in the title first: The exact string 'self' is a convention (that I can see no valid reason to ignore BTW), but the first argument in a class method is always going to be a reference to the class instance.
Whether you should use a class or flat functions depends on if the functions have shared state. From your scenario it sounds like they may have a common base URL, authentication data, database names, etc. Maybe you even need to establish a connection first? All those would be best held in the class and then used in the functions.
Imagine a situation in which a large set of animal classes, which cannot be modified, all inherit from the same parent class "Animal", and each implements a method called "make_noise" each with a slightly different signature, but all with shared parameter volume:
class Cat(Animal)
def make_noise(volume, duration)
-some code here-
class Mouse(Animal)
def make_noise(volume, pitch)
-some different code here-
A different "controller" class, which also cannot be modified, is instructing a list of these animal instances (a list which I have populated) to make sounds at particular volumes (and duration/pitch/etc as appropriate). However, I need to get between the controller and animal classes to modify the behaviour of "make_noise" in all animal classes, so that I can reduce the value of volume before the sound is made.
One option would be to do something like:
def animal_monkeypatcher(animal_class, volume_reduction_factor):
class QuietAnimal(animal_class)
def make_noise(volume, **kwargs)
volume = volume * volume_reduction_factor
super(QuietAnimal, self).make_noise(volume, **kwargs)
However, I also need to pickle these objects, and that doesn't work with this approach. The next approach I thought about was a class which had an instance of the animal like so...
class QuietAnimal():
def __init__(animal_class, init_kwargs):
self.animal = animal_class(**init_kwargs)
def make_noise(volume, **kwargs)
volume = volume * volume_reduction_factor
self.animal.make_noise(volume, **kwargs)
def lots of other functions.....
However, this is also not suitable because the controller sometimes needs to create new instances of animals. It does this by getting the class of an animal (which is QuietAnimal, instead of say Mouse) and then using the same set of init_kwargs to create it, which does not match the signature of QuietAnimal, so again we're stuck...
At the moment I have a horrible hack, which basically forks the init depending on whether or not an animal_class has been passed in or not, and records some info in some class variables. It's frankly dreadful, and not useful if I need to create more than one type of animal (which in my use case I don't, but still...). It's also rubbish because I have to include all of the methods from all of the animals.
What is the appropriate way to wrap/proxy/whatever this set of classes to achieve the above? Some sample code would be greatly appreciated. I am a Python novice.
It turns out, what I needed was standard "monkey patching". Not a great idea either, but slightly cleaner than creating classes on the fly.
First of all, I am a total newbie. Thanks for your patience.
I am designing a piece of software to calculate insulation materials and amounts on different houses.
I have a class House(), which holds attributes like roof_area and wall_area.
I have a class Insulator(), which holds attributes like thickness and area (the area the packaged material covers)
Now I want to know how many packages of the insulator I should buy in order to cover the whole roof area.
So, the operation would be:
House.roof_area / Insulator.area = insulator_packages_needed_for_roof
The thing is I can't do that operation:
AttributeError: type object 'House' has no attribute 'roof_area'.
Of course I could do it a an instance scope, but I don't want to specify an instance yet, as this operation should be done for any instance of the Class that gets build in the future. Should I use inheritance? My feeling is that, given that Insulator and House are totally different things, they shouldn't be mixed by inheritance, but I am just a beginner.
It doesn't make any sense to try to compute the number of insulation packages you need to cover the roof of a house, without using any instances of your House or Insulator classes. It only makes sense if you have one instance of each.
You can, however, write the code to do the calculation before you've created the instances. Just put it in a function that takes the instances as arguments:
def roof_insulation_packages(house, insulator): # args are instances of House and Insulator
return house.roof_area / insulator.area # do the calculation and return it
It might make more sense for the function to be a method of one of the classes. I'd even suggest that Insulator instances might be a good candidates to be instance attributes of the House. That would look something like this:
class House():
def __init__(self, roof_area, roof_insulator, wall_area, wall_insulator):
self.roof_area = roof_area
self.roof_insulator = roof_insulator
self.wall_area = wall_area
self.wall_insulator = wall_insulator
def calculate_roof_insulation_packages(self):
return self.roof_area / self.roof_insulator.area
def calculate_wall_insulation_packages(self, insulator):
return self.wall_area / self.wall_insulator.area
You'd create the house instance with something like this (I'm making up the arguments to the Insulator class, so don't pay too much attention to that part):
good_roof_insulation = Insulator(4, 5) # nonsense args
cheap_wall_insulation = Insulator(5, 12)
my_house = House(100, good_roof_insulation, 87, cheap_wall_insulation)
If you want to use attributes without creating an instance you should use class attributes.
class House(object):
roof_area = 10 # Or whatever you see fit.
roof_surface = 20
class Insulator(object):
thickness = 10 # Or whatever you see fit.
surface = 20
This way you can access the attributes by typing 'House.roof_area' for example.
Although, I don't see why you cannot create an instance. It would prevent harcoding in class attributes and would in your case be much easier.
Also, your operation is not valid syntax, but maybe you just showed pseudo-code. Proper syntax would be:
insulator_packages_needed_for_roof = House.roof_area / Insulator.area
I'm getting back to programming for Google App Engine and I've found, in old, unused code, instances in which I wrote constructors for models. It seems like a good idea, but there's no mention of it online and I can't test to see if it works. Here's a contrived example, with no error-checking, etc.:
class Dog(db.Model):
name = db.StringProperty(required=True)
breeds = db.StringListProperty()
age = db.IntegerProperty(default=0)
def __init__(self, name, breed_list, **kwargs):
db.Model.__init__(**kwargs)
self.name = name
self.breeds = breed_list.split()
rufus = Dog('Rufus', 'spaniel terrier labrador')
rufus.put()
The **kwargs are passed on to the Model constructor in case the model is constructed with a specified parent or key_name, or in case other properties (like age) are specified. This constructor differs from the default in that it requires that a name and breed_list be specified (although it can't ensure that they're strings), and it parses breed_list in a way that the default constructor could not.
Is this a legitimate form of instantiation, or should I just use functions or static/class methods? And if it works, why aren't custom constructors used more often?
In your example, why not use the default syntax instead of a custom constructor:
rufus = Dog( name='Rufus', breeds=['spaniel','terrier','labrador'] )
Your version makes it less clear semantically IMHO.
As for overriding Model constructors, Google recommends against it (see for example: http://groups.google.com/group/google-appengine/browse_thread/thread/9a651f6f58875bfe/111b975da1b4b4db?lnk=gst&q=python+constructors#111b975da1b4b4db) and that's why we don't see it in Google's code.
I think it's unfortunate because constructor overriding can be useful in some cases, like creating a temporary property.
One problem I know of is with Expando, anything you define in the constructor gets auto-serialized in the protocol buffer.
But for base Models I am not sure what are the risks, and I too would be happy to learn more.
There's usually no need to do something like that; the default constructor will assign name, and when working with a list it almost always makes more sense to pass an actual list instead of a space-separated string (just imagine the fun if you passed "cocker spaniel" instead of just "spaniel" there, for one thing...).
That said, if you really need to do computation when instantiating a Model subclass instance, there's probably nothing inherently wrong with it. I think most people probably prefer to get the data into the right form and then create the entity, which is why you're not seeing a lot of examples like that.