Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python can you do prototyping of string functions like in JavaScript [duplicate]

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?

like image 441
DKean Avatar asked Mar 18 '13 17:03

DKean


1 Answers

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.

like image 168
abarnert Avatar answered Oct 06 '22 01:10

abarnert