You're exploiting python's flexibility. The way you are calling this function might not work or might have unexpected behavior (as in the third case), but it's not invalid syntax.
Modifying the class definition to add some debug printing:
class add:
def add_me(self, *args):
print(f"self: {self}")
print(f"args: {args}")
res = 0
for x in args:
res += x
return res
When you call an instance method on an initialized object, the first argument is always the object itself. Therefore, calling add_me with an initialized instance passes the instance as self and the numbers 1 to 5 as args, resulting in a sum of 15:
In [2]: print(f"result: {add().add_me(1, 2, 3, 4, 5)}")
self: <__main__.add object at 0x10e127160>
args: (1, 2, 3, 4, 5)
result: 15
Calling the class method add.add_me using the class means no instance is passed in automatically. However, by passing in a newly initialized instance as the first argument, add() works a similar way, but the first argument self refers to a different object (0x10df28bb0, as opposed to the original instance 0x10e127160). If the method referenced an attribute or modified the state of self, the instance referenced/modified would be the one passed in in this case:
In [3]: print(f"result: {add.add_me(add(), 1, 2, 3, 4, 5)}")
self: <__main__.add object at 0x10df28bb0>
args: (1, 2, 3, 4, 5)
result: 15
Finally, simply calling the method on an un-initialized object fails to pass anything in as the first argument, and the first expliclit argument 1 is assigned to the variable self, and is excluded from the total:
In [4]: print(f"result: {add.add_me(1, 2, 3, 4, 5)}")
self: 1
args: (2, 3, 4, 5)
result: 14
See this realpython guide to instancemethods, classemethods, and staticmethods for more information.