Can an operator be overloaded as a class method in python?
Asked Answered
L

1

6

In order to make an extension really clean looking I'm trying to implement the ">>" operator in python as a class method. I'm not sure how to go about it though. I don't want to have to create an instance since I am really operating on the class itself.

>>> class C:
...     @classmethod
...     def __rshift__(cls, other):
...         print("%s got %s" % (cls, other))
...
>>> C.__rshift__("input")
__main__.C got input
>>> C() >> "input"
__main__.C got input
>>> C >> "input"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'classobj' and 'str'

Background information:

I am trying to implement views in the peewee ORM (Similar to Django). Peewee allows you to define database tables and their relations as classes, like so:

class Track(Model):
    title = CharField()
    artist = ForeignKeyField(Artist)

class Artist(Model):
    name = CharField(unique = True)
    location = ForeignKeyField(Location)

class Location(Model):
    state = CharField(size = 2)
    city = CharField()

Note: For clarity's sake the order is reversed.

I'm trying to extend this with an implementation of views. One of the most difficult parts is setting on a clean way to indicate the joins. So far I have implemented the following:

class Song(View):
    title = Track.title
    artist = Track.artist >> "name"
    state = Track.artist >> "location" >> "state"

This is ok, but I would really like to eliminate the "." to further simplify:

class Song(View):
    title = Track >> "title"
    artist = Track >> "artist" >> "name"
    state = Track >> "artist" >> "location" >> "state"

Which would you rather use? Or both?

As a side note, can anyone think of a good way to indicate a backwards join? Something like the following is a bit awkward for me:

class LocWithSong(View):
    state = Location >> "state"
    title = Location >> Track.title
Legislation answered 27/5, 2012 at 10:21 Comment(1)
Author of peewee here, I like the API you've come up with! Feel free to fork and contribute back your changes on GitHub: github.com/coleifer/peewee or join the mailing list, groups.google.com/group/peewee-ormFigwort
K
9

Define the method on the metaclass.

class MC(type):
  def __rshift__(self, other):
    return something(self, other)

class C(object):
  __metaclass__ = MC

print C >> None
Keith answered 27/5, 2012 at 10:24 Comment(2)
Thank you, I would have never thought of that. It is tremendously hard to search for, everything I saw pulled up irrelevant information in regards to standard overloading. Thank you for the prompt response.Legislation
Note that in Python3 the syntax is bit different: class C(metaclass=MC)Apiarist

© 2022 - 2024 — McMap. All rights reserved.