class PHPstr(str):
def __getattr__(self, attr):
return PHPstr(self+attr)
>>> a = PHPstr("test")
>>> a.test
'testtest'
Almost, but not quite the concatenation operator of PHP strings.
Kind of like "hey guys, check it out you can just duct tape down the dead-man's switch on this power tool and use it one handed". In Python.
Monday, February 28, 2011
Friday, January 21, 2011
custom string class
Here is how to make a subclass of string which has all the same operations available, but which returns instances of that subclass:
import inspect
import functools
class MyStr(str):
def __radd__(self, other):
return MyStr(str.__add__(other, self))
def __repr__(self):
return self.__class__.__name__ + str.__repr__(self)
def _mystr_wrap(f):
@functools.wraps(f, ('__name__','__doc__'))
def g(*a, **kw):
res = f(*a, **kw)
if res.__class__ == str:
return MyStr(res)
return res
return g
for name, f in inspect.getmembers(str, callable):
#skip some special cases
if name not in ['__class__', '__new__', '__str__', '__init__', '__repr__']:
setattr(MyStr, name, _mystr_wrap(f))
>>> MyStr("cat")
MyStr'cat'
>>> MyStr("cat")+"dog"
MyStr'catdog'
>>> MyStr("cat")[1:]
MyStr'at'
Note: if you find yourself actually doing this, it is probably a bad code smell :-)
Note: if you find yourself actually doing this, it is probably a bad code smell :-)
Wednesday, January 5, 2011
making your class work with built-in math functions
Just add __float__ and/or __int__. Then the built-in math functions, or anything that sanitizes its input via int() or float() will see your objects as a numeric type.
>>> import math
>>> class B(object):
... def __float__(self): return 0.5
...
>>> math.sin(B())
0.47942553860420301
>>> import math
>>> class B(object):
... def __float__(self): return 0.5
...
>>> math.sin(B())
0.47942553860420301
Tuesday, December 28, 2010
the confusingly named setdefault
setdefault has the same behavior as the following function:
>>> def setdefault2(my_dict, key, def):
... my_dict[key] = my_dict.get(key, def)
... return my_dict[key]
...
>>> a = {}
>>> setdefault2(a, "1", "2")
'2'
>>> a.setdefault(1, 2)
2
>>> setdefault2(a, "1", "3")
2
>>> a
{'1': '2', 1: 2}
>>> def setdefault2(my_dict, key, def):
... my_dict[key] = my_dict.get(key, def)
... return my_dict[key]
...
>>> a = {}
>>> setdefault2(a, "1", "2")
'2'
>>> a.setdefault(1, 2)
2
>>> setdefault2(a, "1", "3")
'2'
>>> a.setdefault(1, 3)2
>>> a
{'1': '2', 1: 2}
This function is useful in similar cases to a collections.defaultdict. The difference being, with this function you can choose what you want the default to be each time you fetch a key from the dictionary. With a defaultdict, the default value for a missing key must be set at construction time.
using finally to do something after return
>>> def foo():
... try:
... print "returning"
... return
... finally:
... print "after return"
...
>>> foo()
returning
after return
... try:
... print "returning"
... return
... finally:
... print "after return"
...
>>> foo()
returning
after return
sequence unpacking in argument list
>>> def foo(a, (b,c)): print a,b,c
...
>>> foo(1,(2,3))
1 2 3
>>> foo(1,())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
ValueError: need more than 0 values to unpack
This feature has probably really confused you if you ever mistakenly put parenthesis around the parameters to a lambda. In that case the lambda expression will take only one argument, and that argument will be a tuple.
>>> a = lambda (a,b): a+b
3
...
>>> foo(1,(2,3))
1 2 3
>>> foo(1,())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
ValueError: need more than 0 values to unpack
This feature has probably really confused you if you ever mistakenly put parenthesis around the parameters to a lambda. In that case the lambda expression will take only one argument, and that argument will be a tuple.
>>> a = lambda (a,b): a+b
>>> a(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes exactly 1 argument (2 given)
>>> a((1,2))3
Subscribe to:
Posts (Atom)