Python: definiowanie własnych operatorów?

80

Chciałbym zdefiniować własnego operatora. Czy Python obsługuje coś takiego?

cwj
źródło
Cóż, możesz mieć operator, który nie jest zdefiniowany (jak $), a następnie użyć kodu Pythona do edycji (z open) i zmienić wszystko a $ bnafunction(a,b)
whackamadoodle3000

Odpowiedzi:

40

Nie, nie możesz tworzyć nowych operatorów. Jeśli jednak oceniasz tylko wyrażenia, możesz samodzielnie przetworzyć ciąg i obliczyć wyniki nowych operatorów.

Zifre
źródło
1
Zobacz poniżej zestaw predefiniowanych, nadających się do zastąpienia operatorów w Pythonie.
Palimondo
179

Chociaż z technicznego punktu widzenia nie można zdefiniować nowych operatorów w Pythonie, ten sprytny hack pozwala obejść to ograniczenie. Pozwala zdefiniować operatory wrostkowe w ten sposób:

# 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
źródło
2
+1 Ten hack jest całkiem fajny, ale nie sądzę, żeby zadziałał w tej sytuacji.
Zifre
9
To może być interesujący hack, ale nie sądzę, że jest to dobre rozwiązanie. Python nie pozwala na tworzenie własnych operatorów, co jest decyzją projektową, która została podjęta z dobrego powodu i powinieneś ją zaakceptować zamiast postrzegać to jako problem i wymyślać sposoby na obejście tego problemu. Nie jest dobrym pomysłem walka z językiem, w którym piszesz kod. Jeśli naprawdę chcesz, powinieneś użyć innego języka.
DasIch
79
@DasIch Nie mogę się bardziej nie zgodzić. Nie wszyscy jesteśmy wolni, aby celowo wybrać język. Z drugiej strony nie rozumiem, dlaczego miałbym się godzić na decyzje projektowe innych osób, jeśli nie jestem zadowolony. - Naprawdę świetny hack!
ThomasH,
+1 To bardzo fajny hack, ale moje pytanie dotyczyło bardziej tego, czy definiowanie własnych operatorów jest funkcją w Pythonie, czy nie, a nie, czy można udawać, że masz nowych operatorów, i wydaje się, że odpowiedź brzmi: nie, nie możesz zdefiniować nowe operatory. Chociaż to jest cholernie blisko.
ArtOfWarfare
2
Właśnie połączyłem to z pipefrom toolz. pip = Infix(lambda x,y: pipe(x,y)). wtedy 8 |pip| range |pip| sum |pip| range. wydaje się działać.
cantdutchthis
44

Nie, Python zawiera predefiniowany, ale nadający się do zastąpienia zestaw operatorów .

dfa
źródło
1
Jestem ciekawy, jak dfplyużywa -->operatora: directiondatascience.com/…
Max Candocia
1
@MaxCandocia O ile wiem, nie (patrz dokumentacja ). Przykład w tym poście, który używa, -->wydaje się być psuedocode. Sama biblioteka po prostu się przeciąża >>.
Andrew Marshall,
11

Sage zapewnia tę funkcjonalność, zasadniczo używając „sprytnego hacka” opisanego przez @Ayman Hourieh, ale włączonego do modułu jako dekorator, aby nadać bardziej przejrzysty wygląd i dodatkową funkcjonalność - możesz wybrać operatora do przeciążenia, a tym samym kolejność oceny.

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

Zobacz dokumentację Sage i ten raport śledzenia ulepszeń, aby uzyskać więcej informacji.

billyjmc
źródło
10

Jeśli zamierzasz zastosować operację na określonej klasie obiektów, możesz po prostu nadpisać operator, który jest najbliższy twojej funkcji ... na przykład, przesłanianie __eq__()przesłoni ==operator, aby zwrócił cokolwiek chcesz. Działa to dla prawie wszystkich operatorów.

Sudhir Jonathan
źródło
9

Python 3.5 wprowadza symbol @dodatkowego operatora.

PEP465 wprowadził ten nowy operator mnożenia macierzy, aby uprościć zapis wielu kodów numerycznych. Operator nie zostanie zaimplementowany dla wszystkich typów, ale tylko dla obiektów typu tablice.

Możesz wspierać operatora dla swoich klas / obiektów poprzez implementację __matmul__().

PEP pozostawia miejsce na inne użycie operatora dla obiektów innych niż tablice.

Oczywiście możesz zaimplementować @dowolną operację inną niż mnożenie macierzy również dla obiektów przypominających tablice, ale wpłynie to na wrażenia użytkownika, ponieważ każdy będzie oczekiwał, że Twój typ danych będzie zachowywał się w inny sposób.

gg349
źródło
Czy masz na myśli tylko to, że @jest to nowy symbol operatora? Albo że możemy jakoś go użyć do zdefiniowania nowych własnych operatorów?
Addem
Tak, @ to nowy symbol operatora. Tak, możesz go używać do definiowania operacji na swoich obiektach. Rozważ przeczytanie PEP465.
gg349,
5
@Addem Miał na myśli tylko, że @jest to nowy operator. Otóż ​​to. Fakt pozostaje faktem: w Pythonie nie można definiować własnych operatorów.
John Red