1

Python, being dynamically typed, has no provision for type-hinting on method parameters. However, PHP, also being dynamically typed, does have a provision for type-hinting that a method parameter is at least an instance of a class (or that it is an instance of a class that inherits from a defined class).

public class Foo()
{
    public function __construct($qux, ...)
    {
        $this->qux = qux;
        ...
    }
}

public class Bar() 
{
    // "Type Hinting" done here enforcing 
    // that $baz is an instance of Foo
    public function __construct(Foo $baz, ...)
    {
        $this->baz = $baz;
        ...
    }
}

Is there a similar way of enforcing that a method param is a specific instance in Python?

If not, is the proper convention to simply assert?

class Foo(object):
    def __init__(self, qux=None, ...):
        self.qux = qux
        ...


class Bar(object):
    def __init__(self, baz=None, ...):
        # "Type Hinting" done here as `assert`, and
        # requires catch of AssertionError elsewhere
        assert isinstance(baz, Foo)

        self.baz = baz
        ...

If this is style of using assert is incorrect/inelegant/"not pythonic", what should I do instead?

Bryson
  • 1,186
  • 2
  • 13
  • 26
  • I'd raise a `TypeError` exception, rather but your code looks good... Although be aware that `isinstance` will be `True` for all the child instances of `Foo` (you can enforce just `Foo` by doing `type(baz) == Foo` (no parenthesis on `Foo`) – Savir Apr 14 '14 at 22:08
  • 4
    Actually the Pythonic thing to do is use "duck typing"; if the value works, let it, regardless of whether it's the type you expect. That's why we talk of file like objects, sequences, etc - they're expected protocols, what Java would call interfaces, although they're not specified in the language. There is one type constraint built into the language, though; `self` on methods is type checked. – Yann Vernier Apr 14 '14 at 22:08
  • Today I would recommend using MyPy to check type annotations. – Yann Vernier Oct 14 '19 at 20:55

2 Answers2

4

Not out of the box. You can, however, combine parameter annotations with function decorators to almost effortlessly write your own.

Keep in mind, however, that the whole idea of duck typing is to avoid this kind of logic.

Community
  • 1
  • 1
salezica
  • 74,081
  • 25
  • 105
  • 166
2

There is a strong convention in Python to embrace the Duck Typing idiom, which in this case would mean that you would call the appropriate attributes from the baz object without explicitly checking its type. This has many benefits, including better support for polymorphism and arguably more readable / less verbose code.

If you tried to access an attribute which the object does not support, a AttributeError exception is raised. Therefore you could place this inside a try/except block and catch any AttributeError when appropriate - this is characteristic of another Python idiom called 'Easier to ask forgiveness than permission'

try:
    baz.foo
except AttributeError:
    # handle the exception

Some other questions that cover this topic

Community
  • 1
  • 1
dannymilsom
  • 2,386
  • 1
  • 18
  • 19