views:

204

answers:

8

I want to do something like this...

def helloWorld():
  print "Hello world!"
string.helloWorld = helloWorld
"foo".helloWorld()

Which would print out "Hello world!"

+2  A: 

In short, you can't. The Python Way would be to subclass String and work from there.

sczizzo
Subclassing builtins is rarely useful. It is almost always better to make functions that operate on them or, in the case of adding some state, make classes with an instance whatever builtin as an attribute.
Mike Graham
Subclassing dict to implement a OrderedDict, MultiDict, ImmutableDict or combinations of those is very common. On the other side dict is a collection str is not.
DasIch
+1  A: 

Python does not support that feature.

joeforker
A: 

You don't. Use separate dictionaries to "attach" (logically speaking) information to immutable values like strings or numbers (the string or number value as key, the information as corresponding value in the dict).

Alex Martelli
A: 

You can make inheritance from string like this :

class myString( str ) :

    def helloWorld( self ) :
         return helloWorld()
uhbif19
This is kinda' the simplicity of what I was going for here, but I can't get this to work. Is there something important you're missing? I even tried putting in __metaclass__ = type, but when I try to print out x.helloWorld() it says NameError: global name 'helloWorld' is not defined, even though when I print x.helloWorld it says <bound method myString.helloWorld of 'hurro'>
sfjedi
the above comment makes metaclass bold because it's surrounded by two underscores on both sides.
sfjedi
A: 

You can't, it isn't Pythonic. Monkey-patching isn't a commonly used feature of Python, so for performance -- I believe -- reasons you can't do it on the built it classes or instances thereof.

In fact, it has its own name in Python: duck-punching.

chpwn
+1  A: 

To do that you can subclass str.

However, while technically possible, most of the time you are subclassing builtins (such as str) you are looking at a 'has-a' kind of relationship, not 'is-a', therefore composition should be used, not inheritance (meaning you should create a class with a string as an instance attribute, rather than subclass string).

shylent
I'll have to look more into what the hell an instance attribute is, but this sounds very wise.
sfjedi
+2  A: 

Ruby way:

"1".to_i
"1".to_roman 

Python way:

int("1")
Roman("1") # or 
Roman.fromstring("1") 

Where Roman will work on a fixed list of built-in types or anything with a __int__ method.

It is an implementation limitation of CPython that you can't set attributes of built-in/extension types. It is accompanied by cultural preference to avoid monkey-patching in favor of stand-alone functions, custom classes that have as an attribute desired object (or even subclassing in rare cases).

J.F. Sebastian
+1  A: 

On CPython you can use ctypes to access the C-API of the interpreter, this way you can change builtin types at runtime.

import ctypes as c


class PyObject_HEAD(c.Structure):
    _fields_ = [
        ('HEAD', c.c_ubyte * (object.__basicsize__ -
                              c.sizeof(c.c_void_p))),
        ('ob_type', c.c_void_p)
    ]

_get_dict = c.pythonapi._PyObject_GetDictPtr
_get_dict.restype = c.POINTER(c.py_object)
_get_dict.argtypes = [c.py_object]

def get_dict(object):
    return _get_dict(object).contents.value

def my_method(self):
    print 'tada'
get_dict(str)['my_method'] = my_method

print ''.my_method()

Although this is interesting to look at and may be quite interesting to figure out... don't ever use it in productive code. Just subclass the builtin type or try to figure out if there is another, may be more pythonic, approach to your problem.

DasIch