105

I would like to define my own operator. Does python support such a thing?

Garrett
  • 4,007
  • 2
  • 41
  • 59
cwj
  • 2,473
  • 5
  • 28
  • 38
  • 1
    Well, you could have an operator which isn't defined (like `$`) and then use some python code to edit itself (with `open`) and change all `a $ b` to `function(a,b)` – whackamadoodle3000 Sep 29 '17 at 03:04

6 Answers6

215

While technically you cannot define new operators in Python, this clever hack works around this limitation. It allows you to define infix operators like this:

# simple multiplication
x=Infix(lambda x,y: x*y)
print 2 |x| 4
# => 8

# class checking
isa=Infix(lambda x,y: x.__class__==y.__class__)
print [1,2,3] |isa| []
print [1,2,3] <<isa>> []
# => True
Ayman Hourieh
  • 132,184
  • 23
  • 144
  • 116
  • 2
    +1 That hack is pretty cool, but I don't think it will work in this situation. – Zifre May 31 '09 at 18:22
  • 15
    It might be an intersting hack but i don't think that this is good solution. Python does not allow to create own operators, a design decision which was made for a good reason and you should accept it instead of seeing this as a problem and inventing ways around it. It is not a good idea to fight against the language you are writing the code in. If you really want to you should use a different language. – DasIch Jun 01 '09 at 22:24
  • 110
    @DasIch I couldn't disagree more. We're not all free to chose a language deliberately. On the other side, I don't see why I should settle with anybody else's design decisions if I'm not satisfied. - Excellent hack indeed! – ThomasH Sep 15 '10 at 17:10
  • 1
    +1 For a very cool hack, but my question was more about whether defining my own operators is a feature in Python or not, not whether it's possible to fake having new operators, and it would seem the answer is no, you can't define new operators. Although this does come pretty darn close. – ArtOfWarfare Jun 12 '14 at 14:25
  • 2
    I just combined this with `pipe` from `toolz`. `pip = Infix(lambda x,y: pipe(x,y))`. then `8 |pip| range |pip| sum |pip| range`. seems to work. – cantdutchthis Jul 31 '15 at 11:58
  • Note that this hack limits you to the hard-coded precedence and associativity of the standard operators it abuses. – chepner Mar 24 '21 at 22:06
  • 1
    Interesting solution, but perhaps what still makes it a bit inferior to actually defining an operator (which is impossible in Python without preprocessing of your code) is that you don’t have access the arguments before they’re evaluated. You can therefore not e. g. define your own assignment operator or control evaluation order like the `and` operator. – Yushin Washio May 16 '21 at 09:50
49

No, Python comes with a predefined, yet overridable, set of operators.

whackamadoodle3000
  • 6,684
  • 4
  • 27
  • 44
dfa
  • 114,442
  • 31
  • 189
  • 228
  • 1
    I'm curious to know how `dfply` uses a `-->` operator: https://towardsdatascience.com/dplyr-style-data-manipulation-with-pipes-in-python-380dcb137000 – Max Candocia Apr 30 '18 at 18:33
  • 2
    @MaxCandocia As far as I can tell, it doesn’t (see [docs](https://github.com/kieferk/dfply/blob/bec4d59ab20a9b718742af96741250d022fd12a7/README.md#overview-of-functions)). The example in that post that uses `-->` seems to be psuedocode. The library itself just overloads `>>`. – Andrew Marshall Oct 19 '18 at 01:15
42

No, you can't create new operators. However, if you are just evaluating expressions, you could process the string yourself and calculate the results of the new operators.

Zifre
  • 26,504
  • 11
  • 85
  • 105
  • 1
    See [bellow](http://stackoverflow.com/questions/932328/python-defining-my-own-operators#932333) for Python’s set of predefined overridable set of operators. – Palimondo May 20 '17 at 11:58
14

Sage provides this functionality, essentially using the "clever hack" described by @Ayman Hourieh, but incorporated into a module as a decorator to give a cleaner appearance and additional functionality – you can choose the operator to overload and therefore the order of evaluation.

from sage.misc.decorators import infix_operator

@infix_operator('multiply')
def dot(a,b):
    return a.dot_product(b)
u=vector([1,2,3])
v=vector([5,4,3])
print(u *dot* v)
# => 22

@infix_operator('or')
def plus(x,y):
    return x*y
print(2 |plus| 4)
# => 6

See the Sage documentation and this enhancement tracking ticket for more information.

billyjmc
  • 403
  • 5
  • 10
13

Python 3.5 introduces the symbol @ for an extra operator.

PEP465 introduced this new operator for matrix multiplication, to simplify the notation of many numerical code. The operator will not be implemented for all types, but just for arrays-like-objects.

You can support the operator for your classes/objects by implementing __matmul__().

The PEP leaves space for a different usage of the operator for non-arrays-like objects.

Of course you can implement with @ any sort of operation different from matrix multiplication also for arrays-like objects, but the user experience will be affected, because everybody will expect your data type to behave in a different way.

gg349
  • 21,996
  • 5
  • 54
  • 64
  • 1
    Do you just mean that `@` is a new operator symbol? Or that we can somehow use it to define new operators of our own? – Addem Feb 07 '16 at 05:09
  • Yes, @ is a new operator symbol. Yes, you can use it to define operations on your objects. Consider reading the PEP465. – gg349 Feb 07 '16 at 06:13
  • 8
    @Addem He just meant that `@` is a new operator. That's it. The fact still remains: You can't define operators of your own in Python. – John Red Mar 24 '16 at 08:21
10

If you intend to apply the operation on a particular class of objects, you could just override the operator that matches your function the closest... for instance, overriding __eq__() will override the == operator to return whatever you want. This works for almost all the operators.

Sudhir Jonathan
  • 16,998
  • 13
  • 66
  • 90