I am confused with a concept in python - base class overriding. I learned that you can have two different functions with the same name in different classes, and the correct function will be called on an object depending on which class the object is from.
However, I have just learned about the super call, and I learned that you can use it if you overrode (correct past tense?) a function that you need back. I'm confused because the overridden function isn't gone in the first place, is it? Why do I need to "restore" it using the super call?
The child's type is first in MRO, so its method will get called even if any of its parents have the same method. super "restarts" MRO at the next link in the inheritance chain, and allows discovery of attributes belonging to parent classes.
Related
Functions in a python class can be either instance methods, class methods or static methods.
The former is characterised by the self as its first (implicit) argument, acts directly on the instance of the class, and does not require any decorators to be treated as such.
The other two, however, need decorators #classmethod and #staticmethod before the name of the method - this is why I refer to the instance method as the "default" one, i.e. the one for which a wrapper is not needed.
My question is: suppose I am in a class, and I am breaking up my calculation into several functions for readibility. Only one of these methods will need access to the self.something variables that I share instance-wise, but most of the others do not need to know about the class they belong to - they are just there for "housekeeping".
Should make these functions (the ones that do not need any self.something knowledge) all #staticmethod? Doing so would require a decorator and hence an extra step. It would be easier (not requiring the extra step of using a decotrator) for every method to just be an instance method, thus inheritig a lot of potential but also waisting it since it is not needed for the scope of the functions in question.
Why is the instance method the "default"? Why not have every method a static method by default, and give it the extra functionality associated with being a instance method with a wrapper?
The reason to default to instance methods is because that's usually what you want when you're doing object oriented programming. I can't think of a single language that claims to support OOP and has methods default to anything but instance methods. Classes are templates for "data with behaviors", so the default is to make methods that provide behaviors to each instantiation of the class. If you just want a collection of functions, you can just define them at the top level of a module and save the unnecessary class after all.
In general, #staticmethod is used to mean "I know this isn't a behavior of the class or its instances, but it helps implement the real behaviors and isn't very useful outside the class, so I'll namespace it inside it." If the features are useful outside the class, you'd just make it a plain top-level function rather putting it inside the class at all. It is advantageous to use #staticmethod where appropriate; it's a little faster to call than an instance method, so if you don't need the instance, #staticmethod will speed up your code a bit (note: This may not be true in 3.7+, where they added an optimization to avoid the creation of bound methods, which may speed up instance/class methods).
#classmethod basically has two use cases:
(Primary) Defining alternate constructors in a subclass friendly way (the cls it receives is the actual subclass, if applicable, not just the class it was defined in)
(Mostly unnecessary) As an alternative to #staticmethod when the method needs to call other static methods and you'd rather not have to refer to the class by name over and over
Point is, #staticmethod is mostly for when you're opting out of OOP, and #classmethods are for niche use cases; instance methods are just more useful, so they're the default. Beyond that, as a historical note, static and class methods were introduced later, so making them the default would have broken all existing Python code, for no real benefit.
The main reason to use #staticmethod over instance methods with an ignored self (when self isn't needed) is that it will continue to work when called on the class itself, not just on instances of the class; if you tried to call MyClass.notreallystatic(), it would die for lack of a self, while MyClass.actuallystatic() would work.
Using WTForms form definition classes as an example:
class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35)])
accept_rules = BooleanField('I accept the site rules', [validators.InputRequired()])
and looking at the source of the library it seems WTForms allows a user to define a very simple class of a customised form structure (as above), which in turn then gets used to construct a new field class which is not instantiated when the class is generated.
I've read a number of tutorials about class factories and metaclasses and the general consensus is to avoid metaclasses and use things like class decorators instead. The problem is the tutorials either start importing extra libraries eg: import six, mix explanations of different Python versions together, use overly complex examples or advise not to use metaclasses at all.
Please can somebody provide a very simple explanation (for Python 3) of how to use a simple class definition (like the WTForms example above) along with metaclasses to customise a brand new construction of a class without actually instantiating the class when it's constructed.
Edit: Apologies for finding it difficult to explain what my end goal is but as I have gone through tutorials it has been unclear as to whether class decorators, metaclasses, magic methods (call, new, init) or a combination of such are what I needed to achieve what I visualised, or if what I was visualising was the wrong way of doing things. Unfortunately it seems impossible to judge if my goal was wrong without being able to understand the mechanisms needed to achieve it. I've realised metaclasses are the way to go and just need pointing in the right direction for a very simple metaclass example done the Python 3.x way.
You can create classes dynamically - with no custom metaclasses and no decorators with what looks to the programmer as simple function call.
Just make a call to Python's builtin type with three parameters:
the name of the class, a tuple with its bases, and a mapping object with its namespace (i.e. a dictionary containing the attributes and methods you would ordinarily define on the class body).
def __init__(self):
...
namespace = {
'__init__': init,
'name': 'default name'
}
MyClass = type("MyClass", (object,), namespace)
You loose some features that are only possible due to the compiler doing a couple special things during building functions declared within a class body - mostly the ability to use paramterless super and name mangling of attributes starting with __, but that is it.
That said it should be noted this is not with "no metaclasses". "type" is itself a metaclass - the default Python metaclass for all objects - and is calling a metaclass that create a class. There is no other way to create a class. A "class decorator" is just a method that can makes changes to a class object after it is created.
Any function or method that yields a new, dynamic class, will have inside it to, at some point, call type or other metaclass. In the same mood, a "metaclass" does not create dynamic classes by itself - it needs do be either used in a class body declaration, or called with (at least) the same parameters used for calling type.
As for the recommendations for "class decorators" instead of metaclasses, I am not sure is that true (beyond the fact there is no way a "class decorator" can create classes dynamically by itself): their main drawback is that there is no ordinary way for subclasses of decorated classes to have the parent's class decorators applied to themselves automatically, while metaclasses are inherited.
In Python 3.6 you have the __init_subclass__ protocol which, yes, can avoid a lot of the traditional uses for a metaclass (but still, it won't "create classes dynamically" - calling type does that).
My IDE keeps suggesting I convert my instance methods to static methods. I guess because I haven't referenced any self within these methods.
An example is :
class NotificationViewSet(NSViewSet):
def pre_create_processing(self, request, obj):
log.debug(" creating messages ")
# Ensure data is consistent and belongs to the sending bot.
obj['user_id'] = request.auth.owner.id
obj['bot_id'] = request.auth.id
So my question would be: do I lose anything by just ignoring the IDE suggestions, or is there more to it?
This is a matter of workflow, intentions with your design, and also a somewhat subjective decision.
First of all, you are right, your IDE suggests converting the method to a static method because the method does not use the instance. It is most likely a good idea to follow this suggestion, but you might have a few reasons to ignore it.
Possible reasons to ignore it:
The code is soon to be changed to use the instance (on the other hand, the idea of soon is subjective, so be careful)
The code is legacy and not entirely understood/known
The interface is used in a polymorphic/duck typed way (e.g. you have a collection of objects with this method and you want to call them in a uniform way, but the implementation in this class happens to not need to use the instance - which is a bit of a code smell)
The interface is specified externally and cannot be changed (this is analog to the previous reason)
The AST of the code is read/manipulated either by itself or something that uses it and expects this method to be an instance method (this again is an external dependency on the interface)
I'm sure there can be more, but failing these types of reasons I would follow the suggestion. However, if the method does not belong to the class (e.g. factory method or something similar), I would refactor it to not be part of the class.
I think that you might be mixing up some terminology - the example is not a class method. Class methods receive the class as the first argument, they do not receive the instance. In this case you have a normal instance method that is not using its instance.
If the method does not belong in the class, you can move it out of the class and make it a standard function. Otherwise, if it should be bundled as part of the class, e.g. it's a factory function, then you should probably make it a static method as this (at a minimum) serves as useful documentation to users of your class that the method is coupled to the class, but not dependent on it's state.
Making the method static also has the advantage this it can be overridden in subclasses of the class. If the method was moved outside of the class as a regular function then subclassing is not possible.
Python will resolve a method name in the class of the method and all parent classes of that class until it resolves.
Does this apply to the constructor as well. I.e., if a class does not define __init__() but its parent does, will the parent constructor automatically be called?
The short answer is: yes. This is how inheritance works.
This is also the reason why you should call the parent constructor explicitly most of the time (unless you want to do otherwise for some reason), when you are overriding method within child class.
It is also worth learning about Method Resolution Order in Python: Method Resolution Order (MRO) in new style Python classes. It defines the order with which the methods are resolved (especially important in case of multiple inheritance).
I'm trying to learn how to make GUI with Traits. I'm new in object oriented programming and I'm new in Python. Most of the examples I could find on the net do not use any constructor in the Hastraits subclass. Should I forget about the def init(self, *arg) constructor? Or should I force myself to use it ?
For example, taking the example from :
Change property parameter from within class constructor [Python / Traits]
the code from DrSAR is to me the most simple and elegant of all the examples; and yet it doesn't use constructor. Did I miss something?
Short answer: no, don't write __init__() initializers when subclassing from HasTraits.
The HasTraits class defines a generic and very flexible __init__() that takes the keyword arguments given to it and assigns the values to the corresponding attributes. Your subclass will inherit this initializer. Given that the trait definitions usually provide sensible defaults for each attribute, there is usually no reason to need another initializer. There are cases where one does want to override this initializer, but they are relatively rare. I might only do so once every 100 or so classes that I write.
If you wanted practice writing initializers for standard subclassing-from-object Python, sorry. Traits has its own set of conventions and best practices that you will be learning in addition to the general OO and Python principles; some of the former will moot the latter.