Wednesday, April 20, 2011

making dict(myobject) do something useful

>>> class T(object):
...    def __iter__(self):
...       return self.__dict__.items().__iter__()
...
>>> t = T()
>>> t.a = "cat"; t.b = "dog"
>>> dict(t)
{'a': 'cat', 'b': 'dog'}

Thursday, March 31, 2011

every string is an iterable of strings

>>> 'a'[0][0][0][0][0]
'a'
Python does not actually create a bunch of string objects when you do this.

>>> a = 'a'
>>> id(a) == id(a[0][0][0][0])
True

Thursday, March 17, 2011

Negative Integer Gotchas (mod and div)

Quick!  What are the values of these expressions: -5%100, -5/100?
If you said -5 and 0, you'd be right... if this was C or Java.
>>> print -5%100, -5/100
95 -1
Some more fun with negative modulos.
>>> 3%-1
0
>>> 3%-2
-1
>>> 3%-3
0
>>> 3%-4
-1
>>> 3%-5
-2
>>> 3%-6
-3
>>> 3%-7
-4
Why does Python have a different behavior than C, Java, Fortran et al?
The decree of the Benevolent Dictator For Life!

Monday, March 14, 2011

Local Variable Performance & dis

Local variables are faster in python.  They are accessed as offsets from a stack, rather than looked up in a hashmap.

Here is an example showing the use of local variables as a performance optimization.  http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Local_Variables

Using the dis module, we can investigate this behavior.  Note LOAD_FAST versus LOAD_DEREF.

>>> import dis
>>> def foo():
...   a = 1
...   def bar():
...      return a
...   return bar
...
>>> b = foo()
>>> dis.dis(b)
  4           0 LOAD_DEREF               0 (a)
              3 RETURN_VALUE
>>> def loc():
...    a = 1
...    return a
...
>>> dis.dis(loc)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)


  3           6 LOAD_FAST                0 (a)
              9 RETURN_VALUE

Monday, February 28, 2011

PHP-like string concatenation (almost)

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.

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 :-)

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