The other answers have done a good job at explaining duck typing and the simple answer by tzot:

Python does not have variables, like other languages where variables have a type and a value; it has names pointing to objects, which know their type.

However, one interesting thing has changed since 2010 (when the question was first asked), namely the implementation of PEP 3107 (implemented in Python 3). You can now actually specify the type of a parameter and the type of the return type of a function like this:

def pick(l: list, index: int) -> int:
    return l[index]

Here we can see that pick takes 2 parameters, a list l and an integer index. It should also return an integer.

So here it is implied that l is a list of integers which we can see without much effort, but for more complex functions it can be a bit confusing as to what the list should contain. We also want the default value of index to be 0. To solve this you may choose to write pick like this instead:

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

Note that we now put in a string as the type of l, which is syntactically allowed, but it is not good for parsing programmatically (which we'll come back to later).

It is important to note that Python won't raise a TypeError if you pass a float into index, the reason for this is one of the main points in Python's design philosophy: "We're all consenting adults here", which means you are expected to be aware of what you can pass to a function and what you can't. If you really want to write code that throws TypeErrors you can use the isinstance function to check that the passed argument is of the proper type or a subclass of it like this:

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

More on why you should rarely do this and what you should do instead is talked about in the next section and in the comments.

PEP 3107 does not only improve code readability but also has several fitting use cases which you can read about here.


Type annotation got a lot more attention in Python 3.5 with the introduction of PEP 484 which introduces a standard module typing for type hints.

These type hints came from the type checker mypy (GitHub), which is now PEP 484 compliant.

The typing module comes with a pretty comprehensive collection of type hints, including:

  • List, Tuple, Set, Dict - for list, tuple, set and dict respectively.
  • Iterable - useful for generators.
  • Any - when it could be anything.
  • Union - when it could be anything within a specified set of types, as opposed to Any.
  • Optional - when it might be None. Shorthand for Union[T, None].
  • TypeVar - used with generics.
  • Callable - used primarily for functions, but could be used for other callables.

These are the most common type hints. A complete listing can be found in the documentation for the typing module.

Here is the old example using the annotation methods introduced in the typing module:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

One powerful feature is the Callable which allows you to type annotate methods that take a function as an argument. For example:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

The above example could become more precise with the usage of TypeVar instead of Any, but this has been left as an exercise to the reader since I believe I've already filled my answer with too much information about the wonderful new features enabled by type hinting.


Previously when one documented Python code with for example Sphinx some of the above functionality could be obtained by writing docstrings formatted like this:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

As you can see, this takes a number of extra lines (the exact number depends on how explicit you want to be and how you format your docstring). But it should now be clear to you how PEP 3107 provides an alternative that is in many (all?) ways superior. This is especially true in combination with PEP 484 which, as we have seen, provides a standard module that defines a syntax for these type hints/annotations that can be used in such a way that it is unambiguous and precise yet flexible, making for a powerful combination.

In my personal opinion, this is one of the greatest features in Python ever. I can't wait for people to start harnessing the power of it. Sorry for the long answer, but this is what happens when I get excited.


An example of Python code which heavily uses type hinting can be found here.

Answer from erb on Stack Overflow
Top answer
1 of 14
1153

The other answers have done a good job at explaining duck typing and the simple answer by tzot:

Python does not have variables, like other languages where variables have a type and a value; it has names pointing to objects, which know their type.

However, one interesting thing has changed since 2010 (when the question was first asked), namely the implementation of PEP 3107 (implemented in Python 3). You can now actually specify the type of a parameter and the type of the return type of a function like this:

def pick(l: list, index: int) -> int:
    return l[index]

Here we can see that pick takes 2 parameters, a list l and an integer index. It should also return an integer.

So here it is implied that l is a list of integers which we can see without much effort, but for more complex functions it can be a bit confusing as to what the list should contain. We also want the default value of index to be 0. To solve this you may choose to write pick like this instead:

def pick(l: "list of ints", index: int = 0) -> int:
    return l[index]

Note that we now put in a string as the type of l, which is syntactically allowed, but it is not good for parsing programmatically (which we'll come back to later).

It is important to note that Python won't raise a TypeError if you pass a float into index, the reason for this is one of the main points in Python's design philosophy: "We're all consenting adults here", which means you are expected to be aware of what you can pass to a function and what you can't. If you really want to write code that throws TypeErrors you can use the isinstance function to check that the passed argument is of the proper type or a subclass of it like this:

def pick(l: list, index: int = 0) -> int:
    if not isinstance(l, list):
        raise TypeError
    return l[index]

More on why you should rarely do this and what you should do instead is talked about in the next section and in the comments.

PEP 3107 does not only improve code readability but also has several fitting use cases which you can read about here.


Type annotation got a lot more attention in Python 3.5 with the introduction of PEP 484 which introduces a standard module typing for type hints.

These type hints came from the type checker mypy (GitHub), which is now PEP 484 compliant.

The typing module comes with a pretty comprehensive collection of type hints, including:

  • List, Tuple, Set, Dict - for list, tuple, set and dict respectively.
  • Iterable - useful for generators.
  • Any - when it could be anything.
  • Union - when it could be anything within a specified set of types, as opposed to Any.
  • Optional - when it might be None. Shorthand for Union[T, None].
  • TypeVar - used with generics.
  • Callable - used primarily for functions, but could be used for other callables.

These are the most common type hints. A complete listing can be found in the documentation for the typing module.

Here is the old example using the annotation methods introduced in the typing module:

from typing import List

def pick(l: List[int], index: int) -> int:
    return l[index]

One powerful feature is the Callable which allows you to type annotate methods that take a function as an argument. For example:

from typing import Callable, Any, Iterable

def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]:
    """An immediate version of map, don't pass it any infinite iterables!"""
    return list(map(f, l))

The above example could become more precise with the usage of TypeVar instead of Any, but this has been left as an exercise to the reader since I believe I've already filled my answer with too much information about the wonderful new features enabled by type hinting.


Previously when one documented Python code with for example Sphinx some of the above functionality could be obtained by writing docstrings formatted like this:

def pick(l, index):
    """
    :param l: list of integers
    :type l: list
    :param index: index at which to pick an integer from *l*
    :type index: int
    :returns: integer at *index* in *l*
    :rtype: int
    """
    return l[index]

As you can see, this takes a number of extra lines (the exact number depends on how explicit you want to be and how you format your docstring). But it should now be clear to you how PEP 3107 provides an alternative that is in many (all?) ways superior. This is especially true in combination with PEP 484 which, as we have seen, provides a standard module that defines a syntax for these type hints/annotations that can be used in such a way that it is unambiguous and precise yet flexible, making for a powerful combination.

In my personal opinion, this is one of the greatest features in Python ever. I can't wait for people to start harnessing the power of it. Sorry for the long answer, but this is what happens when I get excited.


An example of Python code which heavily uses type hinting can be found here.

2 of 14
228

Python is strongly typed because every object has a type, every object knows its type, it's impossible to accidentally or deliberately use an object of a type "as if" it was an object of a different type, and all elementary operations on the object are delegated to its type.

This has nothing to do with names. A name in Python doesn't "have a type": if and when a name's defined, the name refers to an object, and the object does have a type (but that doesn't in fact force a type on the name: a name is a name).

A name in Python can perfectly well refer to different objects at different times (as in most programming languages, though not all) -- and there is no constraint on the name such that, if it has once referred to an object of type X, it's then forevermore constrained to refer only to other objects of type X. Constraints on names are not part of the concept of "strong typing", though some enthusiasts of static typing (where names do get constrained, and in a static, AKA compile-time, fashion, too) do misuse the term this way.

🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
The argument list must be a list of types, a ParamSpec, Concatenate, or an ellipsis (...). The return type must be a single type. If a literal ellipsis ... is given as the argument list, it indicates that a callable with any arbitrary parameter ...
Discussions

Explicit parameter list in function documentation - Documentation - Discussions on Python.org
I prefer the parameters of a function (with their documentation) to be listed explicitly in the function’s documentation. This is in contrast with man-style, which describes the positionals in prose. Compare open (what I call man-style) with numpy.linalg.norm (what I say employs an explicit list). More on discuss.python.org
🌐 discuss.python.org
7
May 31, 2022
Why isn´t the parameter of the function of type list?
You're recursively calling the function with a value of whatToPrint.append(mylist[i]). However, list.append() does not return anything, it appends to the list in-place; so you're passing None to the function on all recursive calls. You should append to the list then pass the list in as a parameter. More on reddit.com
🌐 r/learnpython
15
3
May 11, 2024
How could I use the list data type as a parameter in the Python function? - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Stack Overflow for Teams is now called Stack Internal. Bring the best of human thought and AI automation together at your work More on stackoverflow.com
🌐 stackoverflow.com
passing a list as function arguments
You should be using a dictionary and not a list. A dictionary will map keys and values. Dictionaries are written as follows: parameters = { “mode”: “RGBA”, “Prefer_horizontal”: 1 } And then to pass it as an argument you use **parameters in the function definition instead of *parameters. You do not need the “**” when calling the function, only in the function definition. To access the value associated with a key in the dictionary you will do as follows: value = parameters[mode] Where value will now be equal to “RGBA”. Hope this helped! More on reddit.com
🌐 r/learnpython
7
2
May 13, 2021
🌐
W3Schools
w3schools.com › python › gloss_python_function_passing_list.asp
Python Passing a List as an Argument
You can send any data types of argument to a function (string, number, list, dictionary etc.), and it will be treated as the same data type inside the function. E.g. if you send a List as an argument, it will still be a List when it reaches ...
🌐
Mypy
mypy.readthedocs.io › en › stable › cheat_sheet_py3.html
Type hints cheat sheet - mypy 2.3.1 documentation
See Silencing type errors for details on how to silence errors. In typical Python code, many functions that can take a list or a dict as an argument only need their argument to be somehow “list-like” or “dict-like”. A specific meaning of “list-like” or “dict-like” (or something-else-like) is called a “duck type”, and several duck types that are common in idiomatic Python are standardized.
🌐
Runestone Academy
runestone.academy › ns › books › published › thinkcspy › Lists › UsingListsasParameters.html
10.19. Using Lists as Parameters — How to Think like a Computer Scientist: Interactive Edition
Functions which take lists as arguments and change them during execution are called modifiers and the changes they make are called side effects. Passing a list as an argument actually passes a reference to the list, not a copy of the list. Since lists are mutable, changes made to the elements referenced by the parameter change the same list that the argument is referencing.
🌐
Python.org
discuss.python.org › documentation
Explicit parameter list in function documentation - Documentation - Discussions on Python.org
May 31, 2022 - I prefer the parameters of a function (with their documentation) to be listed explicitly in the function’s documentation. This is in contrast with man-style, which describes the positionals in prose. Compare open (what I call man-style) with numpy.linalg.norm (what I say employs an explicit list).
🌐
Note.nkmk.me
note.nkmk.me › home › python
Expand and Pass a List and Dictionary As Arguments in Python | note.nkmk.me
August 19, 2023 - In Python, you can expand a list, tuple, and dictionary (dict) and pass their elements as arguments by prefixing a list or tuple with an asterisk (*), and prefixing a dictionary with two asterisks (**) when calling functions.
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › why isn´t the parameter of the function of type list?
r/learnpython on Reddit: Why isn´t the parameter of the function of type list?
May 11, 2024 -

When I run the following code, I get an error the error: noneType object has no attribute 'append'

Why is this? I am handing in an empty list. How is this different from mylist = [], which works as expected.

(Damn, do I miss C already.)

def func(mylist, whatToPrint):
  if len(mylist) == 1:
    whatToPrint.append(list[0])
    print(whatToPrint)
    return 0
  for i in range(len(mylist)):
    tmp = mylist.copy()
    tmp.pop(i)
    func(tmp, whatToPrint.append(mylist[i]))
    return 0

mylist = []

while True:
  mylist.append(input())
  if input("Last input? (Y/N)") == "Y":
    break

func(mylist, [])

input("Close program with any key.")
🌐
Stack Overflow
stackoverflow.com › questions › 61967428 › how-could-i-use-the-list-data-type-as-a-parameter-in-the-python-function
How could I use the list data type as a parameter in the Python function? - Stack Overflow
Recent versions support (but don't enforce) static type annotations (see typing module). The Python interpreter itself doesn't care about the annotations but there are external tools (mypy) for checking. Your code would then look like: from typing import List def myMethod(listParam: List[str], index: int) -> str: s: str = listParam[index] return s
🌐
Bradley Schacht
bradleyschacht.com › list-parameters-for-a-python-function
List Parameters for a Python Function
May 24, 2024 - Using my new friend help, I can see this will give me a look at useful information from Python objects. Here we will look at two functions: inspect.signature() and inspect.getfullargspec(). To begin, we will import the inspect module. As you can see, running inspect.signature(msparkutils.credentials.getSecret) returns what I need in a simple output which is very similar to what we say with help(mssparkutils.credentials.getSecret) earlier. It gives me the list of inputs which are akvName, secret, and linkedService which is optional as it has a default value assigned to it.
🌐
TecAdmin
tecadmin.net › python-function-with-parameters-return-and-data-types
Python Function with Parameters, Return and Data Types – TecAdmin
April 26, 2025 - However, as of Python 3.5, you can use type hints to indicate the expected data types of function parameters and the return value. This doesn’t enforce the data types, but it can make your code easier to understand. Here’s an example: In this function, the numbers parameter is expected to be a list of integers, and the function is expected to return a tuple of two integers.
🌐
The Python Coding Book
thepythoncodingbook.com › home › blog › using type hints when defining a python function [intermediate python functions series #6]
Using type hints when defining a Python function
March 19, 2023 - Type hints indicate that the data the function returns is a list of strings. Therefore the IDE “knows” that item should be a str in the final for loop since result is a list of strings.
🌐
Built In
builtin.com › software-engineering-perspectives › arguments-in-python
5 Types of Python Function Arguments | Built In
Learn about the five different types of arguments used in python function definitions: default, keyword, positional, arbitrary positional and arbitrary keyword arguments. ... In Python, a function is defined with def.
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-functions
Python Functions - GeeksforGeeks
It can return any data type, multiple values (packed into a tuple), or None if no value is given. ... Parameters: expression is the value returned by the function. If no value is returned, it returns None by default. ... Variables refer to objects. Function behavior depends on whether the object is mutable or immutable. Mutable objects like lists can be modified inside functions.
Published: 2 weeks ago
🌐
i2tutorials
i2tutorials.com › home › python tutorial › python – functions with argument lists
Python - Functions with Argument Lists | i2tutorials
May 2, 2020 - In Python, Arguments in a function ... is treated as the same data type.If we give List as an argument to the function, it will consider the argument as List even if it is inside the function....
🌐
GeeksforGeeks
geeksforgeeks.org › how-to-get-list-of-parameters-name-from-a-function-in-python
How to get list of parameters name from a function in Python? - GeeksforGeeks
March 8, 2025 - In Python, functions are first-class objects meaning they can be assigned to variables, passed as arguments and returned from other functions. This enables higher-order functions, decorators and lambda expressions. By passing a function as an argument, we can modify a function’s behavior dynamically ... The task of getting a list of parameter names from a function in Python involves extracting the function's arguments using different techniques.
🌐
GeeksforGeeks
geeksforgeeks.org › python › specify-argument-type-for-list-of-dictionary-for-a-python
Specify Argument Type For List of Dictionary For a Python - GeeksforGeeks
July 23, 2025 - So, In general, we can write a function in Python as: ... But here, we don't know if the function 'add' accepts int or float values. PEP 3107 Function Annotations now enable us to write our code as: ... Now we can easily tell by reading the code what is the expected data type of the parameters and output. So, now for Specifying Argument Type for List ...