0

Is there any magic method that will invoke when I pass object as argument of function?

class Test:
    def __init__(self, a, b):
         self.a = a
         self.b = b
    def __???__(self):
         return (self.a, self.b)

test = Test(0, 1)

some_function(test) # I'd like to pass parameters (0, 1) here
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
shmnff
  • 647
  • 2
  • 15
  • 31
  • 6
    No, there isn’t. That would be super confusing. You can implement `__iter__` and call `some_function(*test)`, though. – Ry- Nov 19 '17 at 14:42
  • There is no magic in Python. You may want to see Ruby for magic. – Elis Byberi Nov 19 '17 at 14:44
  • 2
    Also see [this answer](https://stackoverflow.com/a/8601389/4014959) by Python core dev Raymond Hettinger. – PM 2Ring Nov 19 '17 at 14:57
  • @ElisByberi Methods like `__len__`, `__add__` and `__repr__` are commonly referred to as "magic methods" – Patrick Haugh Nov 19 '17 at 15:00
  • @PM2Ring Of course they call them magic. They use them to do tricks! I am still with "Explicit is better than implicit." – Elis Byberi Nov 19 '17 at 15:16
  • @ElisByberi SO veteran Ned Batchelder coined another term for such methods (and attributes): [Dunder](https://nedbatchelder.com/blog/200605/dunder.html), perhaps you'd prefer that term. – PM 2Ring Nov 19 '17 at 15:21
  • @PM2Ring I prefer 'class init', 'class constructor', 'class initialization'. – Elis Byberi Nov 19 '17 at 15:36

1 Answers1

2

No, arguments to functions are not treated special in any way. It's just another assignment (to the parameter names of the function).

If you need to treat a and b as separate arguments, make Test a sequence, then pass it in with the *sequence call syntax to expand the sequence to separate arguments. You can make it a sequence by making it an iterator type:

class Test:
    def __init__(self, a, b):
         self.a = a
         self.b = b
    def __iter__(self):
         return iter((self.a, self.b))

test = Test(0, 1)
some_function(*test)

Demo:

>>> def some_function(a, b):
...     print(f'a = {a!r}\nb = {b!r}')
...
>>> test = Test(0, 1)
>>> some_function(*test)
a = 0
b = 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Nice example of [PEP 498 f-strings](https://www.python.org/dev/peps/pep-0498/) also. – Jonathon Reinhart Nov 19 '17 at 15:18
  • I'm under the impression that f-string have to evaluate to a value. Two questions, is some_function passing the value of self.a or is it actually passing the pointer and then it gets looked up at the print statement? If a value will ultimately be passed to the f-string, what is the advantage of using !r here? – Rookie Nov 20 '17 at 00:36
  • 1
    @Rookie: yes, `f` strings specify expressions whose results are interpolated. The `str.format()` equivalent is `'a = {!r}\nb = {!r}'.format(a, b)`. `a` and `b` are just *local variables* in the `some_function()` function. You could give them different names if that helps your understanding better. – Martijn Pieters Nov 20 '17 at 08:10