Using Mix-ins with Python
The most straightforward way to apply mix-ins is at design time within the construction of a module. One of the more famous third-party modules for Python, MySQLdb, does exactly this.
Python defines a standard programmatic interface for database access named DB API (http://www.python.org/topics/database/). Andy Dustman's MySQLdb module implements this interface so that Python programmers can make connections and send queries to a MySQL server. It can be found at http://dustman.net/andy/python/MySQLdb/.
MySQLdb provides three major features for the cursor objects it creates. It reports warnings when necessary; it stores result sets on the client side or uses them on the server side as needed, and it returns results as tuples (e.g., immutable lists) or dictionaries.
Rather than combining all of these into one monolithic class, MySQLdb defines mix-in classes for each of them:
class CursorWarningMixIn: class CursorStoreResultMixIn: class CursorUseResultMixIn class CursorTupleRowsMixIn: class CursorDictRowsMixIn(CursorTupleRowsMixIn):
Remember that mix-ins are classes, so they can take advantage of inheritance, as we see with CursorDictRowsMixIn, which inherits CursorTupleRowsMixIn.
None of the mix-ins above can stand on their own: a BaseCursor class provides the required core functionality for any type of cursor. Using these mix-ins in combination with BaseCursor, MySQLdb offers every combination of warnings, storage and result types (eight in all). When creating a database connection, you can pass the cursor class you desire:
conn = MySQLdb.connection (cursorclass=MySQLdb.DictCursor)
Mix-ins don't only help in the creation of MySQLdb itself. They also make it more extensible by allowing you to pick and choose features for your own custom cursor classes.
Note that these class names are suffixed with MixIn to emphasize their nature. Another common convention is to append “-able” or “-ible” to the end of the name as in Configurable or NamedValueAccessible.
Let's use that last one as an example. The NamedValueAccessible mix-in adds the method valueForKey( ) to whatever class with which it is joined. For obj.valueForKey(name), this method will return one of the following:
obj.name( )
obj._name( )
obj.name
obj._name
In other words, valueForKey( ) looks for methods or attributes, either public or private, in order to return a value for the given key. The design of this method reflects the fact that Python objects often provide information through both attributes and methods. See Listing 2 for the implementation.
Listing 2. A Mix-in for Uniform Value Access
A useful application of this mix-in is to implement generic code for writing logs (see Listing 3).
Listing 3. Applying the NamedValueAccessible Mix-in for Logging
By simply adding new keys to the logColumns( ) method, the log can be expanded without having to modify the code that generates it, which is found in logEntry( ). More importantly, you can imagine that logColumns( ) could read its list of fields from a simple configuration file.
The transaction object itself is free to provide the given values via either methods or attributes, due to the flexibility of the valueForKey( ) method. Making mix-ins flexible increases their utility and is an art that can be developed over time.
So far we have seen examples of using mix-ins during the construction of classes. However, Python's dynamic nature also allows us to mix in functionality at runtime. The simplest technique for doing so is to modify the base classes of the given class, as described earlier. A function allows us to keep this operation opaque and enhance it later if need be:
def MixIn(pyClass, mixInClass):
pyClass.__bases__ += mixInClass
Let's consider a situation that makes the utility of MixIn( ) obvious. In the construction of internet applications, keeping domain classes separate from interface classes is generally a good idea. Domain classes represent the concepts, data and operations of a specific application. They are independent of operating system, user interface, database, etc. Some writers refer to domain objects as business objects, model objects or problem space objects.
Keeping the domain and interface separate makes sense for various reasons. An individual focus is created for two key areas that are largely independent: What is the subject material of the problem? And, how should that be presented? New interfaces can be constructed without modifying or rewriting the domain classes. In fact, multiple interfaces can be provided.
Domain classes for a story publishing system might include Story, Author and Site. These classes contain essential attributes (such as title, body, name, e-mail, etc.) and various operations (save, load, publish, etc.).
One interface for such a system could be a web site that allows users to create, edit, delete and publish these stories. When developing such a site, it would be useful if our domain classes, such as Story, have the methods renderView( ) and renderForm( ), which write HTML for either displaying the story or editing it with a form.
Using mix-ins, we can develop such functionality outside of the domain classes:
class StoryInterface:
def renderView(self):
# write the HTML representation of the story
pass
def renderForm(self):
# write the HTML form to edit the story
pass
And within the code that backs the web site, mix it in like so:
from MixIn import MixIn from Domain.Story import Story MixIn(Story, StoryInterface)If you decide to create a GUI interface for the publishing system, you don't have to take the HTML machinery with you (or vice versa). The domain classes focus on providing necessary data and operations, ensuring that when developing the GUI, you will have what you need.
One could argue that a new class might be created to bring the two together:
class StoryInterface:
...
from Domain.Story import Story
class Story(Story, StoryInterface): pass
Or one could argue that StoryInterface might be made a subclass of Story in order to achieve the same benefit. However, consider the case when Story already has other domain subclasses:
class Story: ... class Editorial(Story): ... class Feature(Story): ... class Column(Story): ...Existing subclasses of Story are in no way affected by simply creating a new Story class or subclass. But a dynamic mix-in for Story will also affect Editorial, Feature and Column. That is why many times the static approach does not work in practice, thereby making the dynamic approach not only clever, but necessary.
Also, consider the case where Story objects are created in parts of the code where Story is hard-coded. While poor practice, this is common. In this situation, creating subclasses of Story will have no effect on the code that ignores them.
One warning regarding dynamic mix-ins: they can change the behavior of existing objects (because they change the classes of those objects). This could lead to unpredictable results, as most classes are not designed with that type of change in mind. The safe way to use dynamic mix-ins is to install them when the application first starts, before any objects are created.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.
Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.
Sponsored by ActiveState
| Non-Linux FOSS: libnotify, OS X Style | Jun 18, 2013 |
| Containers—Not Virtual Machines—Are the Future Cloud | Jun 17, 2013 |
| Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer | Jun 12, 2013 |
| Weechat, Irssi's Little Brother | Jun 11, 2013 |
| One Tail Just Isn't Enough | Jun 07, 2013 |
| Introduction to MapReduce with Hadoop on Linux | Jun 05, 2013 |
- Containers—Not Virtual Machines—Are the Future Cloud
- Non-Linux FOSS: libnotify, OS X Style
- Lock-Free Multi-Producer Multi-Consumer Queue on Ring Buffer
- Linux Systems Administrator
- Introduction to MapReduce with Hadoop on Linux
- RSS Feeds
- Tech Tip: Really Simple HTTP Server with Python
- Weechat, Irssi's Little Brother
- Help with Designing or Debugging CORBA Applications
- Senior Perl Developer
- Reply to comment | Linux Journal
32 min 7 sec ago - Welcome to 1998
1 hour 20 min ago - notifier shortcomings
1 hour 44 min ago - heroku?
3 hours 21 min ago - Android User
3 hours 22 min ago - Reply to comment | Linux Journal
5 hours 15 min ago - compiling
8 hours 5 min ago - This is a good post. This
13 hours 18 min ago - Great, This is really amazing
13 hours 20 min ago - These posts are really good
13 hours 21 min ago
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
Just can't stand seeing this
Just can't stand seeing this Mixin() function. It's a prime example of pointless code; all it does is call a function on the object passed in.
"In case we want to add to it.." and what might you add to such a generic operation?
If you're going to write that kind of thing, use Java. Those guys expect it.
And mixins make more sense in a language like Java, where interface implementations must be complete. Python's duck typing means you only need as much implementation as you need, and on top of that there's no reason to not just make a runtime object with the necessary method rather then adding methods to an existing object.
Much abo about very little.
"Python supports dynamic changes to the class hierarchy."
CPython supports this, but that isn't necessarily the same as saying Python supports this. You can't just set some __class__ member variable in Jython or IronPython, for example. Tinypy also supports this sort of thing, but with more Lua-esque "metatables."