I used the Visitor example given here Where we have this:
.------------------------.
| Flower |
+------------------------+
| +accept(visitor) |
| +pollinate(pollinator) |
| +eat(eater) |
'------------------------'
We also have a Bug and a Bee that can pollinate a Flower, and a Predator that can eat a flower.
Using the vistor pattern I can write this:
bee = Bee()
fly = Fly()
worm = Worm()
# Using the visitor pattern:
for flower in flowerGen(10):
for object in [bee, fly, worm]:
flower.accept(object)
But the code is as readable and funcitonal without the visitor:
# Without visitor pattern
for flower in flowerGen(10):
for object in [bee, fly, worm]:
object.visit(flower)
The question is, what advantages provide the Visitor Pattern in this example?
The article you link to is pretty clear as to why you'd want to use a visitor pattern: when you can't alter the objects because they come from a third party:
The assumption is that you have a primary class hierarchy that is fixed; perhaps it’s from another vendor and you can’t make changes to that hierarchy. However, your intent is that you’d like to add new polymorphic methods to that hierarchy, which means that normally you’d have to add something to the base class interface. So the dilemma is that you need to add methods to the base class, but you can’t touch the base class. How do you get around this?
Sure, if you can just add a visit method to bees, flies and worms, then that's fine. But when you can't, using the visitor pattern is the next best option.
Note that in the article the relationship is reversed; you can't alter the Flower hierarchy:
# The Flower hierarchy cannot be changed:
but the class does support the visitor dispatch pattern via the visit method:
class Flower(object):
def accept(self, visitor):
visitor.visit(self)
That implementation could be much more complex; the example has been simplified down to a simple visitor.visit() call here, but in practice a real visitor pattern can and does do much more at this stage.
For example, there could be composite classes, which contain multiple subcomponents. The accept() method would then delegate further down to those sub-elements to then call accept on them all, as needed. Keeping with the flower theme, perhaps there's a Chrysanthemum or Dahlia class, where some visitors would eat the ray components, while others would like to visit the components in the eye to pollinate. It's up to the composite object to direct each visitor to those parts individually.
If you are looking for specific examples, take a look at the ast module, which offers a NodeVisitor class which should be subclassed to add methods to let you customise how the AST tree passed in is being processed. I've used the specific NodeTransformer subclass to alter how Python code works on several occasions. Here the visitor pattern is used to effectively filter out certain types in a larger hierarchy, greatly simplifying AST-handling code without having to alter any of the AST node classes themselves.
Related
I'm coding a desktop app with Python and Qt, using PySide. I need to display a tree view in which top-level items are objects of different type than their children. Specifically, a top-level item is a Git repository, whereas its children are directories in the work tree.
For a repository, I want to show its path and currently checked-out branch. For a directory, I just want to show its name.
Right now, I do this by having my QAbstractItemModel descendant use isinstance on the underlying model object (retrieved from internalPointer() method) and decide how to format the resulting string.
I was wondering whether there was a more Pythonic (or just less clunky) way of doing this kind of double dispatch.
What I don't want to do is define a method for this purpose in my model classes for Git repo and work tree file, because I feel this would violate SRP.
Any thoughts or ideas are most welcome. Also, if anyone can think of a less clunky title for this question, let me know ;)
If you were ok with each Model class having a function containing View code, then you could just call those functions. To separate the Model/View code without using isinstance, this sounds like a case for the Visitor pattern, as described in this SO answer, and as used in the ast module.
Basically, each Model class has an accept() method that takes a Visitor object. The accept() method for a repository calls the visit_repository() method of that Visitor object, passing self (which is the Model instance). Similarly, the accept() method for a directory calls the visit_directory() method of that Visitor object, passing self. The visit_repository() or visit_directory() method then has access to the Model instance and knows its type and can show the appropriate view. This separates the View code (in the Visitor object) from the Model code (in the Model class).
*Note: instead of using different function names (visit_repository() vs visit_directory()), you can use multimethods, e.g., this SO answer about multimethods in Python.
i'm not sure i can easily do this but i need to automatically add a filter on a field for every query related to my model. I've added a boolean property "active" to my model called Node.
For example
Node.query()
should return every node with the field Node.active set to True and ignore nodes with the active field set to false, without any other instructions.
Is it possible to override the function in any way or something similar? I'm not really good with neither python nor with app engine so i'm not sure i can actually do this.
You should create a class method to your Node class that does the query for you, then always use that. e.g.
class Node(db.Model):
# some properties and stuff
#classmethod
def active_nodes(cls):
return cls.all().filter('active = ',True)
Then always use Node.active_nodes()
This is forms part of your formal api that you always use. I use the approach extensively rather than writing the same (and often more complex query) all over the place.
In Python, you can assign an arbitrary attribute from outside the defining class:
class Profile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=140)
p = Profile()
p.age = 42
The underlying mechanism here is __dict__ attribute that maintains a dictionary of all attributes.
We were all told not to expose our inner workings to the client code, but attaching new data doesn't have to do with encapsulation at all, right? Is this idiom common for Python code?
Just What I Mean…
Each Tweet has standard fields, like id, text, owner.
When returning tweet list for a user, you want to display if a tweet is “favorited” by this user.
Obviously, to obtain is_favorite you need to query many-to-many relationship for this user.
Would it be OK to pre-fill Tweet objects with is_favorite corresponding to current user?
Sure I could expose a method is_favorite_for(user) but I'm hitting Django template language limitations that doesn't allow to call methods with arguments from inside the template. Also, I believe a template should not be calling methods at all.
I know this will work fine, but I wonder if doing something like that in an open source project would get other developers to look on me with contempt.
Sidenote:
I come from C#/.NET background where dynamic types were introduced very recently and aren't adapted widely except for some niche areas (interoperability, IoC frameworks, REST client frameworks, etc).
My view is that it is a bad practice.
The object doesn't know that you're messing with its attributes. Consider, for example, what would happen if Profile were later expanded to have an attribute called age, unrelated to p.age in your code.
If you want to add attributes, why not subclass Profile, or have an external mapping of Profiles to an object with your custom attributes?
I think the answer is: It depends. First, if you really want to prevent it you can by defining __slots__ in the class. And it is not generally a good practice to add attributes not actually defined in the class, as it can be confusing to someone reading
the code and is rarely useful.
But at certain times, it is useful to be able to do this and Python documentation discusses this as a way to get something similar to a C struct or Pascal Record (see http://docs.python.org/tutorial/classes.html under section 9.7 Odds and Ends.)
If the attribute is only there sometimes, you risk getting an AttributeError out of nowhere for one object while the code worked fine for another object of the same class (yes, exact types aren't that important when duck-typing, but objects of the same class are frequently assumed to be of the same "duck type"). Even if it doesn't happen, you can't be sure just by looking at part of the code, and it's much harder to check in any case. So, doing this only makes your code less reliable.
Then there's the option of providing a default attribute as class attribute or property, only assigning an object attribute when it differs from the default. But for stuff that is expected to vary per object, the clarity of having every attribute ever listed in __init__ usually outweights any potential advantages of delaying instance attribute access.
That is not to say it's not acceptable, but you'd have to make a compelling argument for it to be considered a good idea.
Lets say I have three django model classes - lets call them A, B and C. If A and B are abstract, I can do something like:
class C(A,B):
pass
What if they aren't abstract and I do the same? Will everything still work correctly or no? Or have I got it wrong and this should not be done with abstract models either?
I'm having some issues which I'm attributing to the fact that the answer is probably no, but I'd still prefer to make sure about this if anyone knows :)
The specific use case I had for this is probably better served by Generic Relations (I only recently discovered their existence), so I guess it would be understandable if the Django team made a design decision like this (I can't see many people needing to do this). I'd just like to know for sure what the case is.
Edit 1 (after Dominic's answer)
Interesting... The problem we're having is a structure similar to IMDb (I think IMDb is a bit easier to understand than the topic matter we actually have, so I'll use them as an example). On IMDb they have pages for People and pages for Movies and both People and Movies have their own message boards.
We've ended up connecting message boards to the People and Movies by creating a model called MessageboardOwner (with only one attribute - the id added automatically by Django), which "owns" the message board and People and Movies inherit it. The problem is that our "People" class inherits from two other classes also. The class definition is something like:
class Person(A,B,MessageboardOwner):
Initially this seemed to work out fine, but then today something rather weird happened... I was deleting a Person in the admin and the admin asked the "Are you sure?" question and was showing me what other objects it would have to delete. It was trying to delete two message boards, not one. One of these message boards should have been owned by a Movie, not a Person.
Upon looking at what exactly was in the database, I found that this Person instance was using the same MessageboardOwner instance as the Movie was. When I played around with it, what came out was that the Movie class, which inherited only after MessageboardOwner, seemed to work ok. Saving the Person, however, only created a MessageboardOwner object if one didn't already exist (or possibly overwrote the existing one - I'm not sure). I also found that the id fields inherited from A, B and MessageboardOwner were always equal, which seemed strange to me.
Yes, you can use normal Python multiple-inheritance with models. Bear in mind this warning though:
Just as with Python's subclassing,
it's possible for a Django model to
inherit from multiple parent models.
Keep in mind that normal Python name
resolution rules apply. The first base
class that a particular name (e.g.
Meta) appears in will be the one that
is used; for example, this means that
if multiple parents contain a Meta
class, only the first one is going to
be used, and all others will be
ignored.
Generally, you won't need to inherit
from multiple parents. The main
use-case where this is useful is for
"mix-in" classes: adding a particular
extra field or method to every class
that inherits the mix-in. Try to keep
your inheritance hierarchies as simple
and straightforward as possible so
that you won't have to struggle to
work out where a particular piece of
information is coming from.
From the Django docs.
Generally, multiple inheritance is a bad idea, and there are simpler ways to do things. If you flesh out what problem you're trying to solve a bit more clearly, we might be able to help a bit better.
I have the following problem and I'm wondering if there's a nice way to model these objects without using multiple inheritance. If it makes any difference, I am using Python.
Students need contact information plus student information. Adults need contact information plus billing information. Students can be adult students, in which case I need contact/student/billing info, or they can be children, in which case I need contact/student/parent info.
Just to be clear on how the system will be used, I need to be able to ask for a list of all adults (and I will get adult students plus parents), or a list of all students (and I will get child students plus adult students).
Also, all of these objects need to have a common base class.
What you have is an example of Role -- it's a common trap to model Role by inheritance, but Roles can change, and changing an object's inheritance structure (even in languages where it's possible, like Python) is not recommended. Children grow and become adults, and some adults will also be parents of children students as well as adult students themselves -- they might then drop either role but need to keep the other (their child changes schools but they don't, or viceversa).
Just have a class Person with mandatory fields and optional ones, and the latter, representing Roles, can change. "Asking for a list" (quite independently of inheritance or otherwise) can be done either by building the list on the fly (walking through all objects to check for each whether it meets requirements) or maintaining lists corresponding to the possible requirements (or a mix of the two strategies for both frequent and ad-hoc queries). A database of some sort is likely to help here (and most DBs work much better without inheritance in the way;-).
As I'm sure someone else will comment soon (if they haven't already), one good OO principle is "Favor composition over inheritance". From your description, it sounds suspiciously like you're breaking the Single Responsibility Principle, and should be breaking down the functionality into separate objects.
It also occurs to me that Python supports duck typing, which begs the question "Why is it so important that all the classes have a common base class?"
Very simple solution: Use composition rather than inheritance. Rather than having Student inherit from Contact and Billing, make Contact a field/attribute of Person and inherit from that. Make Billing a field of Student. Make Parent a self-reference field of Person.
It doesn't sound like you really need multiple inheritance. In fact, you don't ever really need multiple inheritance. It's just a question of whether multiple inheritance simplifies things (which I couldn't see as being the case here).
I would create a Person class that has all the code that the adult and student would share. Then, you can have an Adult class that has all of the things that only the adult needs and a Child class that has the code only the child needs.
This sounds like something that could be done quite nicely and flexibly with a component architecture, like zope.components. Components are in a way a sort of super-flexible composition patterns.
In this case I'd probably end up doing something when you load the data to also set marker interfaces on it depending on some information, like if age >= 18 you set the IAdult interface, etc. You can then get the adult information by doing
adultschema = IAdultSchema(person)
or something like that.
(Edit: Actually I'd probably use
queryAdapters(person, ISchema)
to get all schemas in one go. :)
A component architecture may be overkill, but once you got used to thinking like that, many problems get trivial. :)
Check out Brandons excellent PyCon talk about it: http://www.youtube.com/watch?v=UF77e2TeeQo
And my intro blog post: http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/
I think your requirements are over-simplified, since in a real situation, you might have students with their own accounts to handle billing even if they are minors who need parent contact information. Also, you might have parental contact information be different from billing information in an actual situation. You might also have adult students with someone else to bill. BUT, that aside - looking at your requirements, here is one way:
classes: Person, BillingInfo, StudentInfo.
All people are instances of class Person...
class Person:
# Will have contact fields all people have - or you could split these off into an
# object.
parent # Will be set to None for adults or else point to their parent's
# Person object.
billing_info # Set to None for non-adults, else to their BillingInfo object.
student_info # Set to None for non-student parents, else to their StudentInfo
# object.
Checking the fields will allow you to create lists as you desire.
One solution is to create a base Info class/interface that the classes ContactInfo, StudentInfo, and BillingInfo inherit from. Have some sort of Person object that contains a list of Info objects, and then you can populate the list of Info objects with ContactInfo, StudentInfo, etc.
In pseudocode, you could do something like this:
Class Student
Inherits WhateverBase
Private m_StudentType as EnumStudentTypes 'an enum containing: Adult, Child
Private m_Billing as Billing
Private m_Contact as Contact
Private m_Parent as Parent
Public Sub Constructor(studentType, billing, contact, parent)
...logic to make sure we have the right combination depending on studentType.
...throw an exception if we try to assign a a parent to an adult, etc.
...maybe you could have seperate constructors, one for each studenttype.
End Sub
Public Property StudentType as EnumStudentTypes
Get
Return m_StudentType
End Get
End Sub
Public Property Parent
Get
...code to make sure we're using a studentType that has a parent,
...and throws an exception if not. Otherwise it returns m_Parent
End Get
End Sub
[more properties]
End Class Student
Then you could create a class called StudentManager:
Public Class StudentManager
Public Function GetAdults(studentCollection(Of Students)) as StudentCollection(Of Students)
Dim ResultCollection(Of Students)
...Loop through studentCollection, adding all students where Student.StudentType=Adult
Return ResultCollection
End Function
[Other Functions]
End Class
Public Enum StudentType
Adult=0
Child=1
End Enum