I'm running the following code and cannot understand why python thinks that I'm not passing an argument to the endswith
method:
filtered_list = list(filter(str.endswith("mp4"), my_files))
This is the error that I'm getting:
TypeError: endswith() takes at least 1 argument (0 given)
I know I can do the same thing with a lambda
function instead of using the method with the class name, or to use the methodcaller, but I think this way it is shorter and cooler and I don't understand why it doesn't work. Maybe when using a class.method notation I can't pass any arguments and have to use it without paranthases?
CodePudding user response:
It doesn't work because you're immediately calling str.endswith
, but with one argument too few. (Try replacing str.endswith("mp4")
with input("Hello?")
, so you see it's evaluated immediately.)
>>> str.endswith("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: endswith() takes at least 1 argument (0 given)
>>> str.endswith("foo", "oo")
True
This has to do with how "foo".endswith
is a bound method, i.e. the "generic" str.endswith
, but with the first "self" argument already bound to the string instance "foo"
.
(The error message is a bit cryptic, or "off-by-one", even, because you are indeed supposed to pass one argument in addition to "self").
This is how methods work for user-created classes too; for an instance inst
of class MyClass
, inst.somefunc(x)
is equivalent to MyClass.somefunc(inst, x)
.
Anyway, the Pythonic, i.e. way cool, way to say what you want is
filtered_list = [f for f in my_files if f.endswith(".mp4")]
CodePudding user response:
filter
requires a callable that returns a Boolean value; str.endswith("mp4")
does not evaluate to such a callable. You have to use a lambda expression or methodcaller
because those do evaluate to callables.