Python 3.x includes standard typing library which allows for method overloading with the use of @overload decorator. Unfortunately, this is to make the code more readable, as the @overload decorated methods will need to be followed by a non-decorated method that handles different arguments. More can be found here here but for your example:
from typing import overload
from typing import Any, Optional
class A(object):
@overload
def stackoverflow(self) -> None:
print('first method')
@overload
def stackoverflow(self, i: Any) -> None:
print('second method', i)
def stackoverflow(self, i: Optional[Any] = None) -> None:
if not i:
print('first method')
else:
print('second method', i)
ob=A()
ob.stackoverflow(2)