Is it possible to delete a method from an object (not class) in python?

前端 未结 8 1746
借酒劲吻你
借酒劲吻你 2020-12-31 13:24

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

相关标签:
8条回答
  • 2020-12-31 13:56

    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.

    0 讨论(0)
  • 2020-12-31 13:56

    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.

    0 讨论(0)
  • 2020-12-31 13:58

    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]
    
    0 讨论(0)
  • 2020-12-31 14:01

    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.

    0 讨论(0)
  • 2020-12-31 14:02

    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:

    1. The are a small number of well defined states that a Wizard object can be in. This pattern can be problematic if there is a quickly growing/changing set of states the object can be in. There is no hard number as to the number of states that can be too much, but I'd suggest that if you're unsure to use the pattern and then pursue an alternative if maintenance becomes too much.
    2. There are multiple methods that need to do different things depending on the state. In this case you could end up with a series of long if/elif statements for each method. This scatters the logic for each state across one monolithic class making difficult to maintain. Have a class which represents each state encapsulates the rules for each logic state in it's own unit making it easier to understand how each state functions on it's own. Additionally, you can unit test each state independent of the consumer of the state objects.
    3. The states in question are fairly concrete as well as easily distinguishable from each other. This will make it much easier to separate each state into its own class.
    0 讨论(0)
  • 2020-12-31 14:14

    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.

    0 讨论(0)
提交回复
热议问题