Last active
December 22, 2015 02:25
-
-
Save taddeimania/521811ba3672ca245229 to your computer and use it in GitHub Desktop.
__matmul__ abuse for the greater good
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# __matmul__ abuse for the greater good | |
"""One thing that caught my eye when learning more about the new Matrix / Matrix | |
multiplication operator was that it itself was not batteries included. | |
Having the wind taken out of my sails, it dawned on me I was looking | |
at the missing implentation the wrong way. What we have on our hands is an | |
operator with an ambiguously open ended realm of opportunities. | |
An operator - that to someone who has never taken a Linear Algebra course | |
opens up many new syntax choices with their programs. | |
Let's explore!""" | |
# ------------------------------------------------------------------------------ | |
class Zipper(list): | |
""" How about we start with a wrapper to `list` that can perform a zip | |
on two lists @'d together. Something we've all wished we could do before. | |
""" | |
def __matmul__(self, other): | |
return list(zip(self, other)) | |
x = Zipper([1, 2, 3, 4, 5]) | |
y = Zipper([8, 2, 23, 1, 1]) | |
print(x @ y) | |
# > [(1, 8), (2, 2), (3, 23), (4, 1), (5, 1)] | |
# ------------------------------------------------------------------------------ | |
class Laugher: | |
""" Want to have an object that just straight up laughs at something? | |
Why not, we all need more humor in our code bases. | |
""" | |
def __matmul__(self, other): | |
return "laughing @ {}".format(other) | |
print(Laugher() @ "joel") | |
# > laughing @ joel | |
# ------------------------------------------------------------------------------ | |
class SentimentHint(str): | |
""" Type annotations are gaining traction in the Python 3 core language, | |
so why leave them out of your programs string sanitizing step? | |
""" | |
def __matmul__(self, other): | |
return "{} <- {}".format(self, other) | |
print(SentimentHint("Sure, why not? I wasn't trying to be funny anyway") @ "sarcasm") | |
# > Sure, why not? I wasn't trying to be funny anyway <- sarcasm | |
# ------------------------------------------------------------------------------ | |
import smtplib | |
from email.mime.text import MIMEText | |
class Emailer: | |
""" Sending an email can be a tedious adventure, why adhere to someone elses' | |
boring old convention of calling functions to send an email. | |
That's right! Let's send an email by just creating an emailer object | |
and pointing it right @ our target. | |
""" | |
def __init__(self, subject, body): | |
self.msg = MIMEText(body) | |
self.msg['From'] = "[email protected]" | |
self.msg['Subject'] = subject | |
def __matmul__(self, other): | |
self.msg['To'] = other | |
print("sure why not, lets send an email to {}".format(other)) | |
s = smtplib.SMTP('localhost') | |
s.send_message(self.msg) | |
s.quit() | |
pizza_emailer = Emailer("lets get pizza", "no seriously, i'm hungry call me") | |
pizza_emailer @ "[email protected]" | |
# > sure why not, lets send an email to [email protected] | |
# and somewhere an email is sent | |
# ------------------------------------------------------------------------------ | |
import operator | |
from functools import reduce | |
class vector(list): | |
""" Last but certainly not least you can implement other strange forms | |
of it's intended purpose. Dot product or Scalar / Vector multiplication? | |
Easy | |
""" | |
def _zip_math(self, other, op): | |
return self.__class__([op(left, right) for left, right in zip(self, other)]) | |
def __matmul__(self, other): | |
if isinstance(other, int): | |
return self._zip_math([other for _ in range(len(self))], operator.mul) | |
elif isinstance(other, self.__class__): | |
return reduce(lambda x, y: x + y, self._zip_math(other, operator.mul)) | |
v_1 = vector([4, 6, 2, 1]) | |
v_2 = vector([0, 2, 1, 1]) | |
print(v_1 @ v_2) | |
# > 15 | |
print(v_2 @ 8) | |
# > [0, 16, 8, 8] | |
print(v_2 @ 8 @ v_2) | |
# > 48 | |
# Just be careful you don't put an operation containing an @ too close to a function, | |
# a team member with no sense of humor may think they've discovered a new way to | |
# decorate a function. | |
v_1@v_2 | |
def ima_decorated_function(): | |
return "proudly decorated!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Do one where
__matmul__
returns a function suitable for using as a decorator...