Extension methods in Python

Question:

Does Python have extension methods like C#? Is it possible to call a method like:

MyRandomMethod()

on existing types like int?

myInt.MyRandomMethod()
Asked By: Joan Venge

||

Answers:

not sure if that what you’re asking but you can extend existing types and then call whatever you like on the new thing:

class  int(int):
     def random_method(self):
           return 4                     # guaranteed to be random
v = int(5)                              # you'll have to instantiate all you variables like this
v.random_method()

class int(int):
    def xkcd(self):
        import antigravity
        print(42)

>>>v.xkcd()
Traceback (most recent call last):
  File "<pyshell#81>", line 1, in <module>
    v.xkcd()
AttributeError: 'int' object has no attribute 'xkcd'
c = int(1)
>>> c.random_method()
4
>>> c.xkcd()
42

hope that clarifies your question

Answered By: SilentGhost

You can add whatever methods you like on class objects defined in Python code (AKA monkey patching):

>>> class A(object):
>>>     pass


>>> def stuff(self):
>>>     print self

>>> A.test = stuff
>>> A().test()

This does not work on builtin types, because their __dict__ is not writable (it’s a dictproxy).

So no, there is no “real” extension method mechanism in Python.

Answered By: Torsten Marek

Another option is to override the meta-class. This allows you to, among other things, specify functions that should exist in all classes.

This article starts to discuss it:

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html

Answered By: tsellon

I’ve had great luck with the method described here:

http://mail.python.org/pipermail/python-dev/2008-January/076194.html

I have no idea if it works on builtins though.

Answered By: hernan43

It can be done with Forbidden Fruit (https://pypi.python.org/pypi/forbiddenfruit)

Install forbiddenfruit:

pip install forbiddenfruit

Then you can extend built-in types:

>>> from forbiddenfruit import curse

>>> def percent(self, delta):
...     return self * (1 + delta / 100)

>>> curse(float, 'percent', percent)
>>> 1.0.percent(5)
1.05

Forbidden Fruit is fundamentally dependent on the C API, it works only on cpython implementations and won’t work on other python implementations, such as Jython, pypy, etc.

Answered By: Rustam Ganeyev

The following context manager adds the method like Forbidden Fruit would without the limitations of it. Besides that it has the additional benefit of removing the extension method afterwards:

class extension_method:

    def __init__(self, obj, method):
        method_name = method.__name__
        setattr(obj, method_name, method)
        self.obj = obj
        self.method_name = method_name

    def __enter__(self):
        return self.obj

    def __exit__(self, type, value, traceback):
        # remove this if you want to keep the extension method after context exit
        delattr(self.obj, self.method_name)

Usage is as follows:

class C:
    pass

def get_class_name(self):
    return self.__class__.__name__

with extension_method(C, get_class_name):
    assert hasattr(C, 'get_class_name') # the method is added to C
    c = C()
    print(c.get_class_name()) # prints 'C'

assert not hasattr(C, 'get_class_name') # the method is gone from C
Answered By: mrts