views:

185

answers:

5

Is there any such equivalent of Java

String myMethod (MyClass argument) {...}

in Python?

Thank you, Tomas

+12  A: 

No. (And more stuff to round this up to 15 characters...)

hughdbrown
And can I tell anyhow that such method only works with instances of MyClass, in other words, how can I tell anyone using myMethod that he has to pass an argument which is an instance of MyClass?
Tomas Novotny
@Tomas, you can document it.
matt b
Tomas, in debugging environments, you can use isinstance() and issubclass() methods to alert by raising an exception or a simple print message.
dheerosaur
And `type()`. As noted below, not recommended practice -- unpythonic.
hughdbrown
They don't have to pass an instance of MyClass, unless the code specifically checks for it. They can pass any object that has the methods and attributes the code requires regardless of said object's provenance.
kindall
+1 @kindall. Here's to duck typing!
Just Some Guy
+12  A: 

No, there is not.

In fact, checking types is considered "un-Pythonic", because an object of any type that looks enough like the expected type should be treated equally.

Matti Virkkunen
"looks enough like the expected type" --- means "supports enough of the requisite interface and semantics of" (search Google on "Python" and "duck typing" for related discussions).
Jim Dennis
Because of Python's late binding it's actually impossible to tell the type of *anything* (beside literals) before executing the code. So even if you could specify types, it would do you not much good.
THC4k
+1  A: 

No.

In Python, it's the program's responsibility to use built-in functions like isinstance() and issubclass() to test variable types and correct usage. Python tries to stay out of your way while giving you all you need to implement strong type checking.

from Why is Python a dynamic language and also a strongly typed language. Also

In a dynamically typed language, a variable is simply a value bound to a name; the value has a type -- like "integer" or "string" or "list" -- but the variable itself doesn't. You could have a variable which, right now, holds a number, and later assign a string to it if you need it to change.

Further, isinstance() and issubclass() can be used to do type-checking. If you want to make sure that argument is of MyClass type, you can have a check inside the function. You can even type-cast the value of the argument (if you have a constructor accepting such value) and assign it to my_object.

dheerosaur
+6  A: 

Python 3.x has function annotations where you can declare argument and return types:

def myMethod(argument: MyClass) -> str:
   ...

But currently Python does nothing with them, they serve as documentation only.

Don O'Donnell
Upvoted for learning something new about Python 3!
kindall
+3  A: 

I just want to say that I'm in full agreement that type checking is evil. But python is also incredibly flexible and I'm in the mood to be evil. This code will take effect at runtime and not compile time. You could do something similar for return type. Something like this could be useful for debugging and, because it's a decorator, it's easy enough to remove.

For it to be useful for debugging you would have to have a situation where two types had all the same attributes that were getting accessed but with different semantics. So that's a pretty limited case. Other than that, you're about to get a typerror anyways when this code runs. The good news is that this is almost never a problem. I really don't know why people from statically typed languages make such a big deal over it.

def types(*args, **kwargs):
    arg_types = args
    kwarg_types = kwargs
    def decorator(f):
        def func(*args, **kwargs):
            for arg, arg_type in zip(args, arg_types):
                if not isinstance(arg, arg_type):
                    raise TypeError("Wrong type suckah")
            for kw, arg in kwargs.items():
                if not isinstance(arg, kwarg_types[kw]):
                    raise TypeError("this is a bad error message")
            return f(*args, **kwargs)
        return func
    return decorator

@types(int, str, bool, flag=bool)
def demo(i, strng, flag=False):
    print i, strng, flag

demo(1, "foo", True)

try:
    demo("foo", "bar", flag="foobar")
except TypeError:
    print "busted on posargs"

try:
    demo(1, "foo", flag=2)
except TypeError:
    print "busted on keyargs"

try:
    demo(1, "foo", 3)
except TypeError:
    print "no use sneaking it through"
aaronasterling
I love creative (ab)use of decorators.
kindall