Readers, meet X. X is a class I wrote in Python as an alternative to using lambda. It has two main features:

It acts as an identity function ( so X(3) == 3, etc. ) When performing operations on it, it returns a new class that acts as a corresponding function.

Let me explain. Doing X+2 will return a new class that whenever called with an argument, will return that argument added with 2. So:

>>> map( X+2, [1, 2, 3] )

[3, 4, 5]

>>> filter( X>0, [5, -3, 2, -1, 0, 13] )

[5, 2, 13]

>>> l = ["oh", "brave", "new", "world"]

>>> sorted(l,key=X[-1])

['world', 'brave', 'oh', 'new']

These operations can be chained:

>>> map(2**(X+1), range(10))

[2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

>>> map( "P" + X[3:]*2 + "!", ["Hello", "Suzzy"] )

['Plolo!', 'Pzyzy!']

Caveats

X has a few limitations.

Using X twice in the same expression probably won’t work (this can be solved)

Since calling X evaluates it, it can’t emulate method calls. For that you have to do use call, like: X.upper.call() (‘hello’) –> ‘HELLO’.

Not all operations can be “captured”. For example, the “in” operator. For that you have to use X.in_( … ), like: X.in_(range(10)) (5) –> True

Not all attributes will be accessible

More problems? Likely.

Conclusion

While not innovative nor a complete solution, I believe X can be a useful replacement for some uses of anonymous functions, providing a shorter and simpler syntax which is easier to read and understand.

It is provided here in full, in hope that it will be useful to my readers (Improvements and fixes are welcome):

class _X(object): def __init__(self, func): self.__func = func def __call__(self, arg): return self.__func(arg) def __getattr__(self, attr): return _X(lambda x: getattr(self(x), attr)) def call(self, *args, **kwargs): return _X(lambda x: self(x)(*args,**kwargs)) # Containers def __getitem__(self, other): return _X(lambda x: self(x)[other]) def __getslice__(self, a,b=None,c=None): return _X(lambda x: self(x)[a:b:c]) def in_(self, other): return _X(lambda x: self(x) in other) # Arith def __add__(self, other): return _X(lambda x: self(x) + other) def __sub__(self, other): return _X(lambda x: self(x) - other) def __mul__(self, other): return _X(lambda x: self(x) * other) def __div__(self, other): return _X(lambda x: self(x) / other) def __floordiv__(self, other): return _X(lambda x: self(x) // other) def __mod__(self, other): return _X(lambda x: self(x) % other) def __pow__(self, other): return _X(lambda x: self(x) ** other) def __radd__(self, other): return _X(lambda x: other + self(x)) def __rsub__(self, other): return _X(lambda x: other - self(x)) def __rmul__(self, other): return _X(lambda x: other * self(x)) def __rdiv__(self, other): return _X(lambda x: other / self(x)) def __rfloordiv__(self, other): return _X(lambda x: other // self(x)) def __rmod__(self, other): return _X(lambda x: other % self(x)) def __rpow__(self, other): return _X(lambda x: other ** self(x)) # bitwise def __and__(self, other): return _X(lambda x: self(x) & other) def __or__(self, other): return _X(lambda x: self(x) | other) def __xor__(self, other): return _X(lambda x: self(x) ^ other) def __rand__(self, other): return _X(lambda x: other & self(x)) def __ror__(self, other): return _X(lambda x: other | self(x)) def __rxor__(self, other): return _X(lambda x: other ^ self(x)) def __rshift__(self, other): return _X(lambda x: self(x) >> other) def __lshift__(self, other): return _X(lambda x: self(x) << other) # Comparison def __lt__(self, other): return _X(lambda x: self(x) < other) def __le__(self, other): return _X(lambda x: self(x) <= other) def __eq__(self, other): return _X(lambda x: self(x) == other) def __ne__(self, other): return _X(lambda x: self(x) != other) def __ge__(self, other): return _X(lambda x: self(x) >= other) def __gt__(self, other): return _X(lambda x: self(x) > other) def __abs__(self): return _X(lambda x: abs(self(x))) X = _X(lambda x:x)

Put it in x.py and import as:

from x import X

Share this: Twitter

Facebook

Like this: Like Loading... Related