Reputation: 2730
I have a current implementation like this:
class Infix(object):
def __init__(self, func):
self.func = func
def __or__(self, other):
return self.func(other)
def __ror__(self, other):
return Infix(partial(self.func, other))
def __call__(self, v1, v2):
return self.func(v1, v2)
@Infix
def Map(data, func):
return list(map(func,data))
This is great, it works as expected, however I want to also expand this implementation to allow for a left side only solution. If somebody can showcase a solution AND explanation, that would be phenomenal.
Here is an example of what I would like to do...
valLabels['annotations'] \
|Map| (lambda x: x['category_id']) \
|Unique|
Where Unique is defined as below...
@Infix
def Unique(data):
return set(data)
Thanks!
Upvotes: 3
Views: 164
Reputation: 6566
If you don't mind dropping the final |
, you could do
class InfixR(object):
def __init__(self, func):
self.func = func
def __ror__(self, other):
return self.func(other)
def __call__(self, v1):
return self.func(v1)
@InfixR
def Unique(data):
return set(data)
Then your expression would look like
valLabels['annotations'] \
|Map| (lambda x: x['category_id']) \
|Unique
Your original Infix
class is (technically) abusing the bitwise or
operator: |Map|
is nothing special, it's just value | Map | my_lambda
, a "bitwise or" of a list, an object, and a lambda, with a couple of spaces removed, and some newlines inserted (using \
to prevent the interpretter from trying to treat each line separately).
In custom classes, you can implement many of the usual operators using __double_underscore__
methods, in the case of bitwise or, they are __or__
and __ror__
.
When the python interpreter encounters the |
operator, it first looks at the object to the right, to see if it has a __or__
method. It then calls left.__or__(right)
. If that is not defined or returns NotImplemented
, it looks at the object on the right, for __ror__
(reversed or), and calls right.__ror__(left)
.
The other part of this is the decorator notation.
When you say
@Infix
def Unique(data):
return set(data)
The interpretter expands that into
def Unique(data):
return set(data)
Unique = Infix(Unique)
So you get an Infix
instance, which has __or__
and __ror__
methods, and a __call__
method. As you might guess, my_obj.__call__()
is called when you invoke my_oby()
.
Upvotes: 2