19

Possible Duplicate:
Can I add custom methods/attributes to built-in Python types?

In Ruby you can override any built-in object class with custom method, like this:

class String
  def sayHello
    return self+" is saying hello!"
  end
end                              

puts 'JOHN'.downcase.sayHello   # >>> 'john is saying hello!'

How can i do that in python? Is there a normally way or just hacks?

Community
  • 1
  • 1
nukl
  • 10,073
  • 15
  • 42
  • 58
  • 1
    This has just been answered in http://stackoverflow.com/questions/4698493/can-i-add-custom-methods-attributes-to-built-in-python-types/4698550#4698550 . Suggest closing. – TryPyPy Jan 15 '11 at 10:57
  • Monkeypatching is possible but has limits, as pointed out in that question (and even more). I recommend just defining a "free" function that does this. –  Jan 15 '11 at 11:09

2 Answers2

29

You can't because the builtin-types are coded in C. What you can do is subclass the type:

class string(str):
    def sayHello(self):
        print(self, "is saying 'hello'")

Test:

>>> x = string("test")
>>> x
'test'
>>> x.sayHello()
test is saying 'hello'

You could also overwrite the str-type with class str(str):, but that doesn't mean you can use the literal "test", because it is linking to the builtin str.

>>> x = "hello"
>>> x.sayHello()
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    x.sayHello()
AttributeError: 'str' object has no attribute 'sayHello'
>>> x = str("hello")
>>> x.sayHello()
hello is saying 'hello'
Joschua
  • 5,816
  • 5
  • 33
  • 44
3

The normal Python equivalent to this is to write a function that takes a string as it's first argument:

def sayhello(name):
    return "{} is saying hello".format(name)

>>> sayhello('JOHN'.lower())
'john is saying hello'

Simple clean and easy. Not everything has to be a method call.

Duncan
  • 92,073
  • 11
  • 122
  • 156
  • The disadvantage of this approach is that you can't write a mutator method. For example, today I want a method `str.startswithThenRemove(p)` that mutates `str` to remove the optional prefix `p` and then returns `True` if the prefix was found and `False` if it wasn't: `if option.startswithThenRemove("--foo="): handleFoo(option)`. You can't do that in any easy way in Python (but see http://stackoverflow.com/a/1551223/1424877). – Quuxplusone Feb 12 '14 at 18:58
  • 8
    Even if you could add a custom method to a string you still wouldn't be able to write a mutator method: Python strings are immutable. – Duncan Feb 12 '14 at 19:11
  • 2
    Except this method is neither clean not easy. Ugly af, at least compared to what OP provided – nehem Mar 18 '22 at 14:55