Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dunder Methods
#1
I'm trying to get a basic understanding of dunder methods. Using the example below. How do I return the msg?
I'm thinking it just doesn't automatically pick the correct method then return the message.
Any help understanding would be great.

class Match:
    def __init__(self, guess, number):
        self.number = number
        self.guess = guess
        self.msg = ''

    def __lt__(self):
        if self.guess < self.number:
            self.msg = f'{self.guess} is too low'

    def __gt__(self):
        if self.guess > self.number:
            self.msg = f'{self.guess} is too high'

    def __eq__(self):
        if self.guess == self.number:
            self.msg = f'Great! You match the number with {self.guess}.'

    def __str__(self):
        return self.msg

print(Match(5, 3))
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#2
I'm not sure what you're really trying to do. The methods for less than, etc. are supposed to be implemented when you want your class to be used with those comparisons. It wouldn't make sense to return a message from them. The Python docs should tell you what the contract for those should be (I'm unable to find them at the moment).
Reply
#3
I'm trying to get a basic understanding of how they work and how to use them. I'm trying to compare two numbers and return if guess is higher, lower, or equal to the other number. Then return the correct message. I've read some examples on the __lt__ and __gt__ but, don't really understand the use. Thanks
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#4
__lt__(), __gt__(), and __eq__() should return True or False when comparing two objects. Yours return None. The functions should also take an argument (other than self). Your's don't. You are not using these functions the way they are meant to be used. Same goes for __str__(). This correctly implements the dunder comparisons. Normally "value" would be another object of the same type:
class Number:
    def __init__(self, value):
        self.value = value

    def __lt__(self, value):
        return self.value < value

    def __gt__(self, value):
        return self.value > value

    def __eq__(self, value):
        return self.value == value

number = Number(3)

while True:
    guess = int(input("Enter guess: "))
    if  number > guess:
        print(f"{guess} is too low")
    if number < guess:
        print(f"{guess} is too high")
    if number == guess:
        print("Good guess")
        break
Reply
#5
Thanks guys. This gives me something to play around with and study.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#6
You need objects that you can sort based on an attribute. If you implement the dunder methods lt, gt and eq, you will be able to sort these objects without having to provide a sorting key. You will also be able to use comparison operators and get meaningful results.

When looking for examples think "Does sorting this make sense?" If not, continue looking. This is something I wrote a while back for how to make a "card" model for playing card games. You need to sort cards, and you need to compare cards, so I implemented comparison dunders.

https://python-forum.io/thread-35860-pos...#pid151062
Reply
#7
An other approach that you can look at.
from dataclasses import dataclass
from random import randint

@dataclass(order=True)
class Number:
    secret_number: int = randint(1, 10)

secret_number = Number()
So now see no dunder methods and can not mess🔨 with them in wrong way as you did in your first post.
Usage test:
>>> secret_number
Number(secret_number=5)
>>> secret_number == Number(2)
False
>>> secret_number == Number(5)
True
>>> secret_number <= Number(2)
False
>>> lst = [secret_number, Number(2), Number(100)]
>>> lst
[Number(secret_number=5), Number(secret_number=2), Number(secret_number=100)]
>>> 
>>> sorted(lst)
[Number(secret_number=2), Number(secret_number=5), Number(secret_number=100)]
When i can do this with the object a lot dunder methods has had to be auto generated.
This code generate about 40 lines of code.
Here some __init__(), __repr__(), __eq__(), __lt__(), __le__(), __gt__(), _ge__()
So this is dataclasses if not heard about it,also look at attrs.
Example of one dunder method generated code.
def __gt__(self, other):
  if other.__class__ is self.__class__:
   return (self.x,self.y,)>(other.x,other.y,)
  return NotImplemented 
If i gone use deanhystad guess code,it will be like this.
dataclass check that object most be of same type in dunder methods(see example) as that what wanted in most cases,
so can not compare against int type.
from dataclasses import dataclass
from random import randint
from rich import print

@dataclass(order=True)
class Number:
    secret_number: int = randint(1, 10)

secret_number = Number()
while True:
    guess = int(input("Enter guess: "))
    if  secret_number > Number(guess):
        print(f"{guess} [green]is too low[/green]")
    if secret_number < Number(guess):
        print(f"{guess} [red]is too high[/red]")
    if secret_number == Number(guess):
        print("[bold magenta]Good Guess![/bold magenta]")
        break
[Image: DA9mMh.png]
menator01 likes this post
Reply
#8
After playing around with the dunder methods a little, it seems to be an overkill for my little program. Guessing it's more suited for complex programs. Snappsat I like your example. First time I have seen the classes module. As for my little number guessing program, it appears a direct comparison would seem reasonable. Thanks again for the insight.
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#9
Making good use of the dunder methods goes a long way to reducing complexity. You'll be able to do a lot more before things become "complex". I usually include __repr__() and __str__() methods in the classes I write. For any class that I might want to sort or rank I also write __lt__(), __gt__() and __eq__() methods. In a recent project I made extensive use of __getattr__() and __setattr__().

By including dunders in a class you make that class compatible with a lot of existing Python code, and the best way to be productive is used as much from the Python built-ins and standard libraries as you can.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Hi, looking for "dunder" tutorials. AlluminumFoil 3 2,052 Mar-02-2020, 08:37 PM
Last Post: jefsummers

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020