Should I use python magic methods directly?
Asked Answered
S

3

9

I heard from one guy that you should not use magic methods directly. and I think in some use cases I would have to use magic methods directly. So experienced devs, should I use python magic methods directly?

Showalter answered 5/4, 2020 at 5:16 Comment(3)
No you shouldn't. All "magic" methods have an equivalent built-in function or syntax for calling themEmotionality
You should when you need the specific job they do, but most magic methods are only responsible for part of what you might think their job is. For example, __add__ is not responsible for the entirety of a + operation, __getattribute__ is not the whole attribute access protocol, and not all iterables have an __iter__ method.Ralline
One of those relatively rare times when the thing you "heard from one guy" was actually right. Now might be a good time to play the lottery.Aalborg
E
12

I intended to show some benefits of not using magic methods directly:

1- Readability:

Using built-in functions like len() is much more readable than its relevant magic/special method __len__(). Imagine a source code full of only magic methods instead of built-in function... thousands of underscores...


2- Comparison operators:

class C:
    def __lt__(self, other):
        print('__lt__ called')

class D:
    pass

c = C()
d = D()

d > c
d.__gt__(c)

I haven't implemented __gt__ for neither of those classes, but in d > c when Python sees that class D doesn't have __gt__, it checks to see if class C implements __lt__. It does, so we get '__lt__ called' in output which isn't the case with d.__gt__(c).


3- Extra checks:

class C:
    def __len__(self):
        return 'boo'

obj = C()
print(obj.__len__())  # fine
print(len(obj))       # error

or:

class C:
    def __str__(self):
        return 10

obj = C()
print(obj.__str__())  # fine
print(str(obj))       # error

As you see, when Python calls that magic methods implicitly, it does some extra checks as well.


4- This is the least important but using let's say len() on built-in data types such as str gives a little bit of speed as compared to __len__():

from timeit import timeit

string = 'abcdefghijklmn'

print(timeit("len(string)", globals=globals(), number=10_000_000))
print(timeit("string.__len__()", globals=globals(), number=10_000_000))

output:

0.5442426
0.8312854999999999

It's because of the lookup process(__len__ in the namespace), If you create a bound method before timing, it's gonna be faster.

bound_method = string.__len__
print(timeit("bound_method()", globals=globals(), number=10_000_000))
Emptyhanded answered 9/8, 2021 at 11:28 Comment(0)
P
2

I'm not a senior developer, but my experience says that you shouldn't call magic methods directly.

Magic methods should be used to override a behavior on your object. For example, if you want to define how does your object is built, you override __init__. Afterwards when you want to initialize it, you use MyNewObject() instead of MyNewObject.__init__().

For me, I tend to appreciate the answer given by Alex Martelli here:

When you see a call to the len built-in, you're sure that, if the program continues after that rather than raising an exception, the call has returned an integer, non-negative, and less than 2**31 -- when you see a call to xxx.__len__(), you have no certainty (except that the code's author is either unfamiliar with Python or up to no good;-).

If you want to know more about Python's magic methods, I strongly recommend taking a look on this documentation made by Rafe Kettler: https://rszalski.github.io/magicmethods/

Pledgee answered 18/11, 2020 at 22:59 Comment(0)
S
1

No you shouldn't.

it's ok to be used in quick code problems like in hackerrank but not in production code. when I asked this question I used them as first class functions. what I mean is, I used xlen = x.__mod__ instead of xlen = lamda y: x % y which was more convenient. it's ok to use these kinda snippets in simple programs but not in any other case.

Showalter answered 19/11, 2020 at 6:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.