开发者

How to know function return type and argument types?

开发者 https://www.devze.com 2023-02-17 13:59 出处:网络
While I am aware of the duck-typing concept of Python, I sometimes struggle with the type of arguments of functions, or the type of the return value of the function.

While I am aware of the duck-typing concept of Python, I sometimes struggle with the type of arguments of functions, or the type of the return value of the function.

Now, if I wrote the function myself, I DO know the types. But what if somebody wants to use and call my functions, how is he/she expected开发者_JS百科 to know the types? I usually put type information in the function's docstring (like: "...the id argument should be an integer..." and "... the function will return a (string, [integer]) tuple.")

But is looking up the information in the docstring (and putting it there, as a coder) really the way it is supposed to be done?

Edit: While the majority of answers seem to direct towards "yes, document!" I feel this is not always very easy for 'complex' types.

For example: how to describe concisely in a docstring that a function returns a list of tuples, with each tuple of the form (node_id, node_name, uptime_minutes) and that the elements are respectively a string, string and integer?

The docstring PEP documentation doesn't give any guidelines on that.

I guess the counterargument will be that in that case classes should be used, but I find python very flexible because it allows passing around these things using lists and tuples, i.e. without classes.


Well things have changed a little bit since 2011! Now there's type hints in Python 3.5 which you can use to annotate arguments and return the type of your function. For example this:

def greeting(name):
  return 'Hello, {}'.format(name)

can now be written as this:

def greeting(name: str) -> str:
  return 'Hello, {}'.format(name)

As you can now see types, there's some sort of optional static type checking which will help you and your type checker to investigate your code.

for more explanation I suggest to take a look at the blog post on type hints in PyCharm blog.


This is how dynamic languages work. It is not always a good thing though, especially if the documentation is poor - anyone tried to use a poorly documented python framework? Sometimes you have to revert to reading the source.

Here are some strategies to avoid problems with duck typing:

  • create a language for your problem domain
  • this will help you to name stuff properly
  • use types to represent concepts in your domain language
  • name function parameters using the domain language vocabulary

Also, one of the most important points:

  • keep data as local as possible!

There should only be a few well-defined and documented types being passed around. Anything else should be obvious by looking at the code: Don't have weird parameter types coming from far away that you can't figure out by looking in the vicinity of the code...

Related, (and also related to docstrings), there is a technique in python called doctests. Use that to document how your methods are expected to be used - and have nice unit test coverage at the same time!


Actually there is no need as python is a dynamic language, BUT if you want to specify a return value then do this

def foo(a) -> int: #after arrow type the return type 
       return 1 + a

But it won't really help you much. It doesn't raise exceptions in the same way like in staticly-typed language like java, c, c++. Even if you returned a string, it won't raise any exceptions.

and then for argument type do this

def foo(a: int) -> int:
      return a+ 1

after the colon (:)you can specify the argument type. This won't help either, to prove this here is an example:

def printer(a: int) -> int: print(a)

printer("hello")

The function above actually just returns None, because we didn't return anything, but we did tell it we would return int, but as I said it doesn't help. Maybe it could help in IDEs (Not all but few like pycharm or something, but not on vscode)


I attended a coursera course, there was lesson in which, we were taught about design recipe.

Below docstring format I found preety useful.

def area(base, height):
    '''(number, number ) -> number    #**TypeContract**
    Return the area of a tring with dimensions base   #**Description**
    and height

    >>>area(10,5)          #**Example **
    25.0
    >>area(2.5,3)
    3.75
    '''
    return (base * height) /2 

I think if docstrings are written in this way, it might help a lot to developers.

Link to video [Do watch the video] : https://www.youtube.com/watch?v=QAPg6Vb_LgI


Yes, you should use docstrings to make your classes and functions more friendly to other programmers:

More: http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring

Some editors allow you to see docstrings while typing, so it really makes work easier.


Yes it is.

In Python a function doesn't always have to return a variable of the same type (although your code will be more readable if your functions do always return the same type). That means that you can't specify a single return type for the function.

In the same way, the parameters don't always have to be the same type too.


For example: how to describe concisely in a docstring that a function returns a list of tuples, with each tuple of the form (node_id, node_name, uptime_minutes) and that the elements are respectively a string, string and integer?

Um... There is no "concise" description of this. It's complex. You've designed it to be complex. And it requires complex documentation in the docstring.

Sorry, but complexity is -- well -- complex.


Yes, since it's a dynamically type language ;)

Read this for reference: PEP 257


Docstrings (and documentation in general). Python 3 introduces (optional) function annotations, as described in PEP 3107 (but don't leave out docstrings)


Answering my own question >10 years later, there are now 2 things I use to manage this:

  • type hints (as already mentioned in other answers)
  • dataclasses, when parameter or return type hints become unwieldy/hard to read

As an example of the latter, say I have a function

def do_something(param:int) -> list[tuple[list, int|None]]:
   ...
   return result

I would now rewrite using a dataclass, e.g. along the lines of:

from dataclasses import dataclass

@dataclass
class Stat:
    entries: list
    value: int | None = None

 def do_something(param:int) -> list[Stat]:
   ...
   return result
0

精彩评论

暂无评论...
验证码 换一张
取 消