5

In JavaScript you can do this to add a trim function to the existing prototype functions

String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g,"");

Then you can do stuff like this to access those functions.

trimmed = myString.trim();

And you have yourself a trimmed string.

In python I know how to list the prototype functions of a string by doing this:

print dir(myString)

But how can I add a prototype function in Python?

9
  • You can't. You'll have to subclass Commented Mar 18, 2013 at 17:37
  • And how do you subclass in python? Commented Mar 18, 2013 at 17:38
  • @DKean Create a class that inherits from str and specify your method Commented Mar 18, 2013 at 17:39
  • @lan I don't know exactly what you mean with inherit since I do not know where the code for str is to be found. Can you give an example? Commented Mar 18, 2013 at 17:43
  • @DKean: You don't need to know where the code is. Just list str as your (first) base class instead of object and you've subclassed str. Commented Mar 18, 2013 at 17:44

1 Answer 1

14

First, Python has a class-based object system, not a prototype-based system like JavaScript.

Adding methods (or other attributes) a class or an instance is pretty easy:

FooClass.method = my_method
foo_instance.method = my_method

However, it doesn't work with many "built-in" types (actual builtins, and those defines in C extensions). And str is one of them.

So, you can't do this.


However, it's very easy to build a subclass of almost any type:

class MyStringType(str):
    def trim(self):
        # your implementation here

You will probably need a custom __init__ method, and likely a custom __new__. Also make sure to change all methods that would return a str to instead return a MyStringType.


Another way to do it is through delegation:

class MyStringType(object):
    def __init__(self, *args, **kwargs):
        self.s = str(*args, **kwargs)
    def trim(self):
        # your implementation here

This way, you will be forced to explicitly forward every method you want from str, instead of getting them automatically. But often that's better anyway. Especially considering how simply you can do it, by either implementing a custom __getattr__, or programmaticaly building the forwarding methods (in __init__ or class-wide).


But the simplest solution is… just don't do it. What's wrong with having a trim function that takes a str parameter?

The nice thing about doing it that way is that your trim function can take any string-like object. For example, your trim function (written as a wrapper around r.replace on some compiled regex r) will work with both unicode and bytes (one of which is a synonym for str in 2.x, the other in 3.x… but if you can handle both, that doesn't matter), and with a PyObjC NSString wrapper or a pywin32 BSTR wrapper, and so on. A find-type method will even work on mmap regions. Why restrict it to only work on str?

That kind of "duck typing" is central to the Python way of doing things. If your code has no reason to care about the actual type of an object, you shouldn't go out of your way to care about it.

Sign up to request clarification or add additional context in comments.

3 Comments

Very interesting and exhaustive reply. I cannot claim to understand everything you said, but I will have to take a few minutes to read it over again until it sinks in. Functions are okay. The reason for asking was that I am getting exhausted with typing in several languages and I am trying to unify the code which I write to a at least look similar to a degree. But, as I said, functions are okay to me. I will take your advice on this @Abarnert. Thank you...
@DKean: Trying to write the same code in multiple languages is a bad idea. Python and JavaScript are very different languages; the best way to do something in one language is often very bad when translated line-for-line to the other language. (And it's even worse if you throw in, say, C or Lisp.)
I do not see such a big problem with it, unless it becomes an issue of speed. And in such a case I intend to use the faster method. But there is also the speed of writing code, rather than flipping through websites and trying to remember how LTRM() is really done! So, while I am very cognizant of your kindness for helping, I also reserve the right of implementing as much isomophism as I can to make my coding easier. And I am hell bent on doing it. But, thank you for all your help. You have been very helpful.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.