1

I have a subclass of the 'str' object and I need to apply it to the application domain. Since the application is full of string literal and str() casts it will take a long time to change all of them to the custom string class. I know it is possible to override 'str()' but I'm not sure about string literals.

I know it is not a good idea but the application requires it. Is it possible to do it in Python? And if not, does it require me to modify 'stringlib' which is the C implementation of the 'str' object?

I'm also aware of the fact that modifying the parser to make the application run is considered to be a very bad programming practice. Can this be achieved via an extension rather than a parser modification?

Kristina
  • 15,859
  • 29
  • 111
  • 181
  • Certainly not without hacking the implementation, which is certainly not what you want. (And shouldn't `grep` or any other search tool reveal all string literals and `str` calls?) –  Feb 13 '11 at 12:51
  • Every single string in the whole application (including the strings from extensions) has to be that type. I will have to modify the extensions too. – Kristina Feb 13 '11 at 12:58

2 Answers2

1

I ran into this question because I was trying to do something similar - str.format behavior from python >=2.7 working on python >= 2.4. FormattableString from stringformat (https://github.com/florentx/stringformat) seemed like the right thing, but it was only useful if I could make it work on literals.

Despite most comments, monkey-patching builtins and literals in python does appear to be possible using code I found here: https://gist.github.com/295200. This appears to be written by Armin Ronacher - certainly not by me.

In the end, I was able to do something like this in python 2.6 even though it normally works only in 2.7.

dx = get_class_dict(str)
dx['format'] = lambda x,*args,**kargs: FormattableString(x).format(*args,**kargs)
print "We've monkey patched {}, {}".format('str', 'with multiple parameters')

The example in the link above shows how to add a new method instead of replacing an existing one.

This little exercise prompted me to add the str and unicode monkey patching to the stringformat package, so now you can just do this:

# should work on python down to 2.4
import stringformat
print "[{0:{width}.{precision}s}]".format('hello world', width=8, precision=5)

This can be cloned from here: "https://github.com/igg/stringformat", untill/unless it gets pulled into the "official" stringformat. Ha. Only two hyperlinks for me, so no clicky for you!

iggie
  • 11
  • 2
1

You cannot modify built-in types, e.g. you cannot add new attributes at runtime1:

>>> setattr(str, "hello", lambda: "Hello custom str!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'

I would try to parse all literal strings and replace them with the constructor of your custom string subclass. This is first and foremost:

  • explicit, which makes it easier for you and other to remember, that this string is different.

Typically i18n libraries have some kind of string literal detection routines for code, which could come in handy during detection. Once these strings are gathered, it's more or less just replace.


1 This is also one reason, python isn't as flexible as ruby. You can't just write test libraries, that monkey patch core classes and add methods like should_equal to every object in the runtime. Here is an entertaining tech talk about these nuances and their consequencies: http://blog.extracheese.org/2010/02/python-vs-ruby-a-battle-to-the-death.html

Community
  • 1
  • 1
miku
  • 181,842
  • 47
  • 306
  • 310