Sometimes, you have a deeply nested set of attributes which may not be present somewhere along the chain. A try/except would be clunky.
>>> class Foo(object): pass
...
>>> f = Foo()
>>> f.a = f
>>> f.a.b = f
>>> f.a.b.c.d
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'c'
This is a simple class which allows an expression to be wrapped and unwrapped, with the result at the end being either the value obtained or None.
>>> class na(object):
... '''
... A None-Attributator object. Allows for "safe navigation",
... similar to the ?. attribute in C#, or undefined in JavaScript.
... '''
... __slots__ = ("base",)
... def __init__(self, base):
... self.base = base
... def __getattr__(self, name):
... return na(getattr(self.base, name, None))
... def __getitem__(self, key):
... try:
... return na(self.base[key])
... except (KeyError, TypeError, IndexError):
... return na(None)
... def __call__(self):
... return self.base
...
>>>
>>> na(f).a.b.c.d.e()
>>> na(f).a.b['cat']()
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.
Friday, May 2, 2014
Friday, January 10, 2014
loopdefaultdict
Simple idiom for a tree.
>>> import collections
>>>
>>> def loopdefaultdict():
... return collections.defaultdict(loopdefaultdict)
...
>>> d = loopdefaultdict()
>>> d[1][2][3]
defaultdict(<function loopdefaultdict at 0x02B249B0>, {})
>>> d[1][2][3] = "cat"
Edit: wikipedia has an even better version
http://en.wikipedia.org/wiki/Autovivification#Python
>>> import collections
>>>
>>> def loopdefaultdict():
... return collections.defaultdict(loopdefaultdict)
...
>>> d = loopdefaultdict()
>>> d[1][2][3]
defaultdict(<function loopdefaultdict at 0x02B249B0>, {})
>>> d[1][2][3] = "cat"
Edit: wikipedia has an even better version
http://en.wikipedia.org/wiki/Autovivification#Python
Tree = lambda: defaultdict(Tree)
Wednesday, December 4, 2013
fun with raise
>>> raise ValueError("wrong value")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: wrong value
>>> try:
... raise ValueError("wrong value")
... except:
... raise sys.exc_info()
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError
If you want to really re-raise the exact same message, replace sys.exc_info()[0] with the exception instance.
>>> try:
... raise ValueError("wrong value")
... except Exception as e:
... raise (e,) + sys.exc_info()[1:]
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError: wrong value
Alas, replacing the traceback object (sys.exc_info()[2]) does not seem to work:
>>> try:
... json.loads('NOT JSON')
... except:
... _, _, tb = sys.exc_info()
...
>>> try:
... 1 / 0
... except Exception as e:
... raise sys.exc_info()[:2], tb
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ZeroDivisionError: <traceback object at 0x02B752B0>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: wrong value
>>> try:
... raise ValueError("wrong value")
... except:
... raise sys.exc_info()
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError
If you want to really re-raise the exact same message, replace sys.exc_info()[0] with the exception instance.
>>> try:
... raise ValueError("wrong value")
... except Exception as e:
... raise (e,) + sys.exc_info()[1:]
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError: wrong value
Alas, replacing the traceback object (sys.exc_info()[2]) does not seem to work:
>>> try:
... json.loads('NOT JSON')
... except:
... _, _, tb = sys.exc_info()
...
>>> try:
... 1 / 0
... except Exception as e:
... raise sys.exc_info()[:2], tb
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ZeroDivisionError: <traceback object at 0x02B752B0>
Thursday, October 31, 2013
exit() is so pedestrian
C:\Users\kurose\workspace>python
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> raise SystemExit("bye")
bye
C:\Users\kurose\workspace>
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> raise SystemExit("bye")
bye
C:\Users\kurose\workspace>
Wednesday, October 30, 2013
gEvent friendly REPL
I was surprised how little code this was. The fileobject module added in gEvent 1.0 and the standard library code module make this trivial.
import sys
import code
from gevent import fileobject
_green_stdin = fileobject.FileObject(sys.stdin)
_green_stdout = fileobject.FileObject(sys.stdout)
def _green_raw_input(prompt):
_green_stdout.write(prompt)
return _green_stdin.readline()[:-1]
def run_console(local=None, prompt=">>>"):
code.interact(prompt, _green_raw_input, local=local or {})
if __name__ == "__main__":
run_console()
import sys
import code
from gevent import fileobject
_green_stdin = fileobject.FileObject(sys.stdin)
_green_stdout = fileobject.FileObject(sys.stdout)
def _green_raw_input(prompt):
_green_stdout.write(prompt)
return _green_stdin.readline()[:-1]
def run_console(local=None, prompt=">>>"):
code.interact(prompt, _green_raw_input, local=local or {})
if __name__ == "__main__":
run_console()
Tuesday, October 29, 2013
missing the __line__ macro from C?
Frame objects to the rescue!
import sys
def __line__():
f = sys._getframe().f_back
return f.f_lineno + f.f_code.co_firstlineno
import sys
def __line__():
f = sys._getframe().f_back
return f.f_lineno + f.f_code.co_firstlineno
Wednesday, October 16, 2013
sigfigs
def _sigfigs(n, sigfigs=3):
'helper function to round a number to significant figures'
if n == 0 or math.isnan(n): # avoid math domain errors
return n
return round(float(n), -int(math.floor(math.log10(abs(n))) - sigfigs + 1))
'helper function to round a number to significant figures'
if n == 0 or math.isnan(n): # avoid math domain errors
return n
return round(float(n), -int(math.floor(math.log10(abs(n))) - sigfigs + 1))
Subscribe to:
Posts (Atom)