Python library functions taking no keyword arguments

你。 提交于 2019-12-10 13:54:55

问题


This problem originated when I tried to apply a more functional approach to problems in python. What I tried to do is simply square a list of numbers, no biggie.

from operator import pow
from functools import partial 

squared = list(map(partial(pow, b=2), range(10))

As it turns out, this didn't work. TypeError: pow() takes no keyword arguments

Confused I checked if pow(b=2, a=3) did. It didn't.

I've checked the operator source code, nothing suspicious.

Confused, I've begun to doubt my own python knowledge, I made a pow function myself.

def pow(a, b):
  return a ** b

Then I tried doing the same thing with my function and surprisingly, everything worked.

I'm not going to guess what is the cause of the problem, what I'm asking is simply why is this a thing and if there exists a workaround.


回答1:


If you check the signature of the built-in pow() or operator.pow() using the help() function in the interactive shell, you'll see that they require positional-only parameters (note the trailing slashes):

pow(x, y, z=None, /)
pow(a, b, /)

The reason is that both functions are implemented in C and don't have names for their arguments. You have to provide the arguments positionally. As a workaround, you can create a pure Python pow() function:

def pow(a, b):
    return a ** b

See also What does the slash(/) in the parameter list of a function mean? in the FAQ.




回答2:


In current versions of Python, many CPython "builtin" and standard library functions only accept positional-only parameters. The resulting semantics can be easily observed by calling the help method.

>>>>help(pow)

Help on built-in function pow in module builtins:

pow(x, y, z=None, /) Equivalent to x**y (with two arguments) or x**y % z (with three arguments)

Some types, such as ints, are able to use a more efficient algorithm when
invoked using the three argument form.

The operator source code mentioned in your question may not be matching with that of the python version in which you are trying.




回答3:


The error is coming from the b=2 statement.

squared = list(map(partial(pow, b=2), range(10))

The partial function is passing the keyword parameter 'b' to the pow function, which results in an error since the pow() function takes positional arguments only. See help(pow) for more info.

However, another issue I see with this call is that the partial function is operating in an unexpected way:

map(partial(pow, 2), range(10))

results in this sequence being generated:

[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

which shows that the partial function is actually computing 2^range(10)

If what you are trying to do is square each value in a list, I would recommend simplifying the code by using a lambda function:

b=2
test = map(lambda x: x**b, range(10))
print(list(test))

which results in:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

with no imports required.




回答4:


pow as a library function accepts positional-only parameters. So here's how you could do the above:

squared = list(map(partial(pow,2), range(10)))

As for your other question, by default user defined functions' parameters are positional-or-keyword parameters, so will work both as regular or kw arguments. Of course defining a new function pow may cause confusion later down the road though so be careful.



来源:https://stackoverflow.com/questions/55970072/python-library-functions-taking-no-keyword-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!