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?

Ian
  • 50,146
  • 13
  • 101
  • 111
DKean
  • 2,017
  • 6
  • 19
  • 28
  • You can't. You'll have to subclass – Ian Mar 18 '13 at 17:37
  • And how do you subclass in python? – DKean Mar 18 '13 at 17:38
  • @DKean Create a class that inherits from `str` and specify your method – Ian Mar 18 '13 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? – DKean Mar 18 '13 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`. – abarnert Mar 18 '13 at 17:44
  • @DKean: Meanwhile, why do you want to do this in the first place? Why can't `trim` just be a method that takes a string? – abarnert Mar 18 '13 at 17:44
  • Note that the string class has a `strip` method that does what your `trim` method is supposed to do - just more efficiently. – oefe Mar 18 '13 at 20:48
  • @Abarnert, your last comment "Just list str as your (first) base class instead of object and you've subclassed str" is not helping me. What does that mean. How about a few code lines to show. I come from VFP and know enough about classes. But that is not helping me here. – DKean Mar 18 '13 at 23:51
  • @Oefe, Trim() was just a function I picked out of a hat. There are other functions like `strtranslate()` `GETWORDNUM()`, `GETWORDCOUNT()` in VFP with which I am very familiar. Such things simplify my programming rather than remembering new coding and thinking in a different language. If you do not see the point, I do. But thank you for your POV and the kindness of helping. It is very appreciated. – DKean Mar 18 '13 at 23:56

1 Answers1

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.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 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 Mar 18 '13 at 17:51
  • @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.) – abarnert Mar 18 '13 at 18:23
  • 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. – DKean Mar 19 '13 at 00:01