Overriding methods on a per instance basis

Nathan Ernst nathan.ernst at gmail.com
Tue May 16 00:00:21 EDT 2017


There is another way to do it, but it's not pretty, and I don't recommend
it:
>>> class Foo:
...     pass
...
>>> from functools import partial
>>> f = Foo()
>>> def hello(self, arg):
...     print("hello", arg)
...
>>> f.hello = partial(hello, f)
>>> f.hello("world")
hello world

This basically relies upon binding in a closure. It's close, but not quite
right. i.e. if you copy the instance, the function will remember the
original and not know about the copy.

On Sun, May 14, 2017 at 11:01 AM, Steve D'Aprano <steve+python at pearwood.info
> wrote:

> It is common to add an attribute to a class, then over-ride it in the
> instance:
>
>
> class Document:
>     pagesize = "A4"
>
>     def __init__(self, pagesize):
>         self.pagesize = pagesize
>
>
> A little-known fact, not appreciated by users of less powerful OOP
> languages: Python supports per-instance customized methods too, since
> methods are just attributes.
>
>
> py> class Parrot:
> ...     name = "Polly"
> ...     def speak(self):
> ...         return "%s wants a cracker!" % self.name
> ...
> py> petey = Parrot()
> py> petey.speak()
> 'Polly wants a cracker!'
>
>
> We can shadow petey's "speak" method with a callable:
>
> py> petey.speak = lambda: "Who's a cheeky boy then!"
> py> petey.speak()
> "Who's a cheeky boy then!"
>
>
> Notice that using a regular function means that we cannot access "self".
> But
> all is not lost! We can do so by using a method object bound to the
> instance:
>
> py> from types import MethodType
> py> petey.speak = MethodType(
> ...     lambda self: "%s is a cheeky boy!" % self.name,
> ...     petey)
> py> petey.speak()
> 'Polly is a cheeky boy!'
>
>
>
>
> This can be considered a form of the Strategy design pattern. From
> Wikipedia:
>
>     ... the strategy pattern (also known as the policy pattern)
>     is a behavioural software design pattern that enables an
>     algorithm's behavior to be selected at runtime. The strategy
>     pattern:
>
>     - defines a family of algorithms,
>     - encapsulates each algorithm, and
>     - makes the algorithms interchangeable within that family.
>
> https://en.wikipedia.org/wiki/Strategy_pattern
>
> the major difference being is that in the Strategy pattern there is not
> necessarily a default implementation provided by the class:
>
> class Dog:
>     pass
>
> rover = Dog()
> butch = Dog()
> laddie = Dog()
>
> rover.do_trick = fetch_stick
> butch.do_trick = play_dead
> laddie.do_trick = solve_world_hunger
>
>
>
>
> --
> Steve
> Emoji: a small, fuzzy, indistinct picture used to replace a clear and
> perfectly comprehensible word.
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>



More information about the Python-list mailing list