Shouyu Chen
Shouyu Chen

Reputation: 655

Expected type '{__name__}', got '() -> None' instead

I have a question about my Python(3.6) code or PyCharm IDE on MacBook

I wrote a function using "timeit" to test time spent by other function

def timeit_func(func_name, num_of_round=1):
    print("start" + func_name.__name__ + "()")
    str_setup = "from __main__ import " + func_name.__name__
    print('%s() spent %f s' % (func_name.__name__,
                           timeit.timeit(func_name.__name__ + "()",
                                         setup=str_setup,
                                         number=num_of_round)))
    print(func_name.__name__ + "() finish")

parameter "func_name" is just a function need to be tested and has already been defined. and I call this function with the code

if __name__ == "__main__":
    timeit_func(func_name=another_function)

the function works well, but pycharm show the info with this code "func_name=another_function":

Expected type '{__name__}', got '() -> None' instead less... (⌃F1 ⌥T) 
This inspection detects type errors in function call expressions. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Types of function parameters can be specified in docstrings or in Python 3 function annotations

I have googled "Expected type '{name}', got '() -> None" but got nothing helpful.I am new on Python. I want to ask what it means? And how can I let this information disappear? because now it is highlighted and let me feel uncomfortable.

I use it in Python3.6 byimport time,this is what I found in the doc of timeit module()(timeit.timeit())

def timeit(stmt="pass", setup="pass", timer=default_timer, number=default_number, globals=None):
   """Convenience function to create Timer object and call timeit method."""
   return Timer(stmt, setup, timer, globals).timeit(number)

Upvotes: 1

Views: 2899

Answers (1)

Duncan
Duncan

Reputation: 95612

Your parameter func_name is badly named because you are passing it a function, not the name of a function. This probably indicates the source of your confusion.

The error message is simply saying that pycharm is expecting you to pass an object with an attribute __name__ but it was given a function instead. Functions do have that attribute but it is part of the internal detail, not something you normally need to access.

The simplest solution would be to work with the function directly. The documentation for timeit isn't very clear on this point, but you can actually give it a function (or any callable) instead of a string. So your code could be:

def timeit_func(func, num_of_round=1):
    print("start" + func.__name__ + "()")
    print('%s() spent %f s' % (func.__name__,
                           timeit.timeit(func,
                                         number=num_of_round)))
    print(func.__name__ + "() finish")

if __name__ == "__main__":
    timeit_func(func=another_function)

That at least makes the code slightly less confusing as the parameter name now matches the value rather better. I don't use pycharm so I don't know if it will still warn, that probably depends whether it knows that timeit takes a callable.

An alternative that should get rid of the error would be to make the code match your parameter name by actually passing in a function name:

def timeit_func(func_name, num_of_round=1):
    print("start" + func_name + "()")
    str_setup = "from __main__ import " + func_name
    print('%s() spent %f s' % (func_name,
                           timeit.timeit(func_name + "()",
                                         setup=str_setup,
                                         number=num_of_round)))
    print(func_name + "() finish")

if __name__ == "__main__":
    timeit_func(func_name=another_function.__name__)

This has the disadvantage that you can now only time functions defined and importable from in your main script whereas if you actually pass the function to timeit you could use a function defined anywhere.

Upvotes: 2

Related Questions