I have a class with a few methods, some of which are only valid when the object is in a particular state. I would like to have the methods simply not be bound to the objects
You can't delete a class method from an instance of that class because the instance doesn't have that method. The protocol is: if o
is an instance of class Foo
, and I call o.bar()
, first o
is examined to see if it has a method named bar
. If it doesn't, then Foo
is examined. The methods aren't bound to the instance unless they override its class.
I don't see any good that can come from the road that you're going down here, either.
If an object is in a state where calling a given method on that object doesn't make sense, having it disappear from the object's interface seems like the wrong way to handle the problem. More explicit error handling gives you the ability to explain the problem more precisely to your callers, throwing NotEnoughMana instead of presenting them with a method-not-found error.
If you're worried about having a bunch of function prefixes that look like this:
if self.StateNotValid():
raise NotEnoughMana()
...then you could use a decorator on each function. It's shorter, and gives you an easy way to grep for all special-state-requiring functions.
This isn't directly answering your question, but I think a better approach to solving this problem would be to not add/remove the member method domagic
on your wiz
object:
What I would do instead is within the domagic
method, add a condition that checks for the relevant state of the wiz
object, and then only perform the rest of the domagic
method for a valid state, otherwise outputting an error message of your choosing.
def domagic():
if (state != desired_state):
print "You cannot do any magic now!"
return
print "Doing some magic"
[some more commands]
As an additional possibility (twisting the question a little bit), if it makes more sense to only have certain methods on certain instances, you can always add those methods in the __init__
of the class to those instances for which it makes sense. Ex: say we have your Wizard
class, and the only time a Wizard
instance should have the domagic()
method is if a magic
parameter passed to __init__()
is True
. We could then do something like:
class Wizard(object):
def __init__(self, magic = False):
if magic:
def _domagic():
print "DOING MAGIC!"
self.domagic = _domagic
def main():
mage = Wizard(magic = True)
nomage = Wizard(magic = False)
mage.domagic() # prints "DOING MAGIC!"
nomage.domagic() # throws an AttributeError
Having said that, this code does have a bit of smell to it -- now before you call domagic() on a Wizard, you need to know if the method is defined or not. I wonder if the inheritance heirarchy could be refined a bit to make this a bit more elegant.
There seem to be some pretty good ideas to address the explicit question of how to hide/remove a method from a python object, so I'd like to address a higher level question.
Specifically, the problem statement from the original question:
I have a class with a few methods, some of which are only valid when the object is in a particular state.
This situation is a classic example of the problem solved via the State Design Pattern:
This pattern is used in computer programming to represent the state of an object. This is a clean way for an object to partially change its type at runtime.
I would consider using this pattern if your Wizard has the following properties:
While I agree that this is the wrong solution, my way to "remove" a method would be to overwrite the function with a property that raises an AttributeError
. This way hasattr
gives the correct result, but it is not as much hassle as using dir
.