0

I am modifying a function which already have some parameters with default values.

I need to take in a function as a parameter, and it should have a default value which should be something like None, so that I can avoid using it when it is not set.

Below is a simple example, while actually None should not be used.

from collections.abc import Callable

def myfunc(x: int=0, metric_func: Callable=None):
    '''Type "None" cannot be assigned to type "function"'''
    ret = []
    if metric_func == None:
        return ret

    for i in range(10):
        ret.append(metric(x, i))
    return ret

def dot(x, y):
    return x * y

if __name__ == "__main__":
    myfunc(1, dot)
4
  • lambda arg0, arg1: 1? Commented Jan 8, 2023 at 9:49
  • 1
    Do you really want to return an empty list when metric_func isn't provided? That seems strange. (Also look at typing.Optional.) Commented Jan 8, 2023 at 9:49
  • 2
    Having None is actually ok, just add proper type hint like Optional[Callable] or Callable | None Commented Jan 8, 2023 at 9:51
  • @user2357112 Thank you for reminding that, but it's just a simple example so that's OK. Commented Jan 8, 2023 at 16:30

1 Answer 1

1

Just looking into the standard library, you're using the most common method.

For instance in heapq(1) (2) (3), bisect (1) (2), itertools (1):

def merge(*iterables, key=None, reverse=False):
    '''Merge multiple sorted inputs into a single sorted output.

    Similar to sorted(itertools.chain(*iterables)) but returns a generator,
    does not pull the data into memory all at once, and assumes that each of
    the input streams is already sorted (smallest to largest).

    >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25]))
    [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25]

    If *key* is not None, applies a key function to each element to determine
    its sort order.

    >>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len))
    ['dog', 'cat', 'fish', 'horse', 'kangaroo']

    '''

    # skipping some lines

    if key is None:
        ...

    # skipping the rest

If you want to type it explicitly, just create a Union with Union[Callable, None] or Callable | None if using python >= 3.10.

You should check against None with v is None not v == None.

If possible, type your Callable otherwise it defaults to Callable[..., Any].

And finally also if possible type your return value(s) where I've put <idk> markers.

def myfunc(x: int = 0, metric_func: Callable[[int, int], <idk>] | None = None) -> list[<idk>]:
    '''Type "None" cannot be assigned to type "function"'''
    ret = []
    if metric_func is None:
        return ret

    for i in range(10):
        ret.append(metric_func(x, i))
    return ret
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.