Using Mix-ins with Python
Mix-in programming is a style of software development where units of functionality are created in a class and then mixed in with other classes. This might sound like simple inheritance at first, but a mix-in differs from a traditional class in one or more of the following ways. Often a mix-in is not the “primary” superclass of any given class, does not care what class it is used with, is used with many classes scattered throughout the class hierarchy and is introduced dynamically at runtime.
There are several reasons to use mix-ins: they extend existing classes in new areas without having to edit, maintain or merge with their source code; they keep project components (such as domain frameworks and interface frameworks) separate; they ease the creation of new classes by providing a grab bag of functionalities that can be combined as needed; and they overcome a limitation of subclassing, whereby a new subclass has no effect if objects of the original class are still being created in other parts of the software.
So while mix-ins are not a distinct technical feature of Python, the benefits of this technique are worth studying.
Python provides an ideal language for mix-in development because it supports multiple inheritance, supports full-dynamic binding and allows dynamic changes to classes. Before we dive into Python, let me admit that mix-ins are old hat. The first time I saw mix-in programming by that name was when reviewing the now-defunct Taligent Project, known for its Pink operating system and CommonPoint application framework. However, since C++ does not support language feature #2, full-dynamic binding, or language feature #3, dynamic changes at runtime, I'm not surprised that the approach didn't bring to fruition all its inventors had hoped for.
I have also seen another instance of mix-in programming under a different name. Objective-C has a nifty language feature called categories that allows you to add and replace methods of existing classes, even without access to their source code.
This is great for repairing existing system classes and extending their capabilities. Also, combined with an ability to load libraries dynamically, categories are quite effective in improving the structure of applications and reducing code.
The grapevine informs me that Symbolics' object-oriented Flavors system is most likely the earliest appearance of bona fide mix-ins. The designers were inspired by Steve's Ice Cream Parlor in Cambridge, Massachusetts where customers started with a basic flavor of ice cream (vanilla, chocolate, etc.) and added any combination of mix-ins (nuts, fudge, chocolate chips, etc.). In the Symbolics system, large, standalone classes were known as flavors while smaller helper classes designed for enhancing other classes were known as mix-ins. A reference can be found on the Web at www.kirkrader.com/examples/cpp/mixin.htm.
Having paid our respects to the dead (Taligent), nearly dead (Objective-C) and legendary (Symbolics), let's start digging into the features that make Python a great language for mix-in programming. For one, Python supports multiple inheritance. That is, in Python, a class can inherit more than one class:
class Server(Object, Configurable): pass
also, Python supports full-dynamic binding. When passing a message to an object such as:
obj.load(filename)Python will determine, entirely at runtime, what method to invoke, based on the name of the message and the class inheritance of obj. This behavior works as expected and is easy to remember. It continues to work even if the class inheritance or method definitions are altered at runtime.
One thing to keep in mind is the order of searching with regard to multiple inheritance. The search order goes from left to right through the base classes, and for any given base class, goes deep into its ancestor classes.
When you create mix-ins, keep in mind the potential for method names to clash. By creating distinct mix-ins with well-named methods you can generally avoid any surprises. Lastly, Python supports dynamic changes to the class hierarchy.
Most Python “things”, whether they are lists, dictionaries, classes or instances, have a set of accessible attributes. Python classes have an attribute named __bases__, which is a tuple of their base classes. Consistent with Python design, you can play with it at runtime. In the following session with the Python interactive interpreter seen in Listing 1, we create two classes and then later change the inheritance. Our person in Listing 1 isn't very friendly so let's change it. In fact, let's change all people so that we'll never have this problem again:
<<< Person.__bases__ += (Friendly,) <<< p.hello() Hello
The first statement above changes the base classes of Person. By using += (as opposed to =) we avoid accidentally removing existing base classes, especially if a future version of the code makes Person inherit from another class. Also, the funny looking expression, (Friendly,), specifies a tuple that would normally simply be enclosed in parenthesis. However, while Python readily recognizes <If“Courier”>(x,y)<I$f$> as a tuple of two elements, it recognizes <If“Courier”>(x)<I$f$> as a parenthesized expression. Appending the comma forces tuple recognition.
Practical Task Scheduling Deployment
July 20, 2016 12:00 pm CDT
One of the best things about the UNIX environment (aside from being stable and efficient) is the vast array of software tools available to help you do your job. Traditionally, a UNIX tool does only one thing, but does that one thing very well. For example, grep is very easy to use and can search vast amounts of data quickly. The find tool can find a particular file or files based on all kinds of criteria. It's pretty easy to string these tools together to build even more powerful tools, such as a tool that finds all of the .log files in the /home directory and searches each one for a particular entry. This erector-set mentality allows UNIX system administrators to seem to always have the right tool for the job.
Cron traditionally has been considered another such a tool for job scheduling, but is it enough? This webinar considers that very question. The first part builds on a previous Geek Guide, Beyond Cron, and briefly describes how to know when it might be time to consider upgrading your job scheduling infrastructure. The second part presents an actual planning and implementation framework.
Join Linux Journal's Mike Diehl and Pat Cameron of Help Systems.
Free to Linux Journal readers.Register Now!
- Stunnel Security for Oracle
- SourceClear Open
- Murat Yener and Onur Dundar's Expert Android Studio (Wrox)
- SUSE LLC's SUSE Manager
- My +1 Sword of Productivity
- Managing Linux Using Puppet
- Google's SwiftShader Released
- Non-Linux FOSS: Caffeine!
- Parsing an RSS News Feed with a Bash Script
- Doing for User Space What We Did for Kernel Space
With all the industry talk about the benefits of Linux on Power and all the performance advantages offered by its open architecture, you may be considering a move in that direction. If you are thinking about analytics, big data and cloud computing, you would be right to evaluate Power. The idea of using commodity x86 hardware and replacing it every three years is an outdated cost model. It doesn’t consider the total cost of ownership, and it doesn’t consider the advantage of real processing power, high-availability and multithreading like a demon.
This ebook takes a look at some of the practical applications of the Linux on Power platform and ways you might bring all the performance power of this open architecture to bear for your organization. There are no smoke and mirrors here—just hard, cold, empirical evidence provided by independent sources. I also consider some innovative ways Linux on Power will be used in the future.Get the Guide