# HG changeset patch # User Paul Boddie # Date 1275508829 -7200 # Node ID 58b093e67a2eeabc6f9738ac63f4451337dd3408 # Parent 7fa0f8a72b494aa2dd55df02cf3ed39f54eea977 Removed usage of getattr by introducing lambda functions providing the methods specific to each operation. diff -r 7fa0f8a72b49 -r 58b093e67a2e lib/operator.py --- a/lib/operator.py Sun May 30 21:09:08 2010 +0200 +++ b/lib/operator.py Wed Jun 02 22:00:29 2010 +0200 @@ -19,19 +19,19 @@ this program. If not, see . """ -def binary_op(a, b, left_name, right_name): +def binary_op(a, b, left_accessor, right_accessor): """ A single parameterised function providing the binary operator mechanism for - arguments 'a' and 'b' using methods of the given 'left_name' and - 'right_name'. + arguments 'a' and 'b' using accessors given as 'left_accessor' and + 'right_accessor' which provide the methods for the operands. """ # First, try and get a method for the left argument, and then call it with # the right argument. try: - fn = getattr(a, left_name) + fn = left_accessor(a) except AttributeError: pass else: @@ -43,7 +43,7 @@ # with the left argument. try: - fn = getattr(b, right_name) + fn = right_accessor(b) except AttributeError: pass else: @@ -56,40 +56,48 @@ raise TypeError +# Concrete operator functions. +# These functions defer method lookup by wrapping the attribute access in +# lambda functions. Thus, the appropriate methods are defined locally, but no +# attempt to obtain them is made until the generic function is called. + +# NOTE: The compiler should make it possible for these to call the generic +# NOTE: operator implementation with no additional call overhead. + def add(a, b): - return binary_op(a, b, "__add__", "__radd__") + return binary_op(a, b, lambda a: a.__add__, lambda b: b.__radd__) def and_(a, b): - return binary_op(a, b, "__and__", "__rand__") + return binary_op(a, b, lambda a: a.__and__, lambda b: b.__rand__) def div(a, b): - return binary_op(a, b, "__div__", "__rdiv__") + return binary_op(a, b, lambda a: a.__div__, lambda b: b.__rdiv__) def floordiv(a, b): - return binary_op(a, b, "__floordiv__", "__rfloordiv__") + return binary_op(a, b, lambda a: a.__floordiv__, lambda b: b.__rfloordiv__) def lshift(a, b): - return binary_op(a, b, "__lshift__", "__rlshift__") + return binary_op(a, b, lambda a: a.__lshift__, lambda b: b.__rlshift__) def mod(a, b): - return binary_op(a, b, "__mod__", "__rmod__") + return binary_op(a, b, lambda a: a.__mod__, lambda b: b.__rmod__) def mul(a, b): - return binary_op(a, b, "__mul__", "__rmul__") + return binary_op(a, b, lambda a: a.__mul__, lambda b: b.__rmul__) def or(a, b): - return binary_op(a, b, "__or__", "__ror__") + return binary_op(a, b, lambda a: a.__or__, lambda b: b.__ror__) def pow(a, b): - return binary_op(a, b, "__pow__", "__rpow__") + return binary_op(a, b, lambda a: a.__pow__, lambda b: b.__rpow__) def rshift(a, b): - return binary_op(a, b, "__rshift__", "__rrshift__") + return binary_op(a, b, lambda a: a.__rshift__, lambda b: b.__rrshift__) def sub(a, b): - return binary_op(a, b, "__sub__", "__rsub__") + return binary_op(a, b, lambda a: a.__sub__, lambda b: b.__rsub__) def xor(a, b): - return binary_op(a, b, "__xor__", "__rxor__") + return binary_op(a, b, lambda a: a.__xor__, lambda b: b.__rxor__) # vim: tabstop=4 expandtab shiftwidth=4