Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 575
sdobz Avatar asked May 27 '12 10:05

sdobz


1 Answers

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
like image 139
Ignacio Vazquez-Abrams Avatar answered Nov 05 '22 23:11

Ignacio Vazquez-Abrams