看起来很简单:
# builtins work fine:
>>> map (str, [(), (), ()])
['()', '()', '()']
# but no luck for class methods:
>>> class C (object):
... def m(self):
... return 42
...
>>> c = C()
>>> map(c.m, [(), (), ()])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: m() takes exactly 1 argument (2 given)
答案 0 :(得分:4)
您需要在m方法中添加一个参数,其中将传递地图的参数。
class C (object):
def m(self, x):
return 42
>>> c = C()
>>> map(c.m, [(), (), ()])
[42, 42, 42]
参见,c.m是一个绑定方法,就像调用m(c)一样,你需要一个占位符来为map传递的附加参数
c
和map传递的参数是你的堆栈跟踪抱怨的m
的2个参数:
TypeError: m() takes exactly 1 argument (2 given)
答案 1 :(得分:4)
map(f, L)
始终使用单个参数调用f
,其值取自L
。它总是一个参数,永远不会为零。列表中的()
不是参数列表,它们是空元组。在函数调用之外,括号中的内容不是函数的参数,它们是称为“元组”的对象(将它们视为不可变列表)。检查str()
和str(())
- str
之间的区别,不带任何参数,''
和不 '()'
。
如果你有参数元组并希望用这些参数调用可调用的(函数或方法),你可以使用itertools.starmap
。特别是,如果传递空元组,则将调用函数而不使用参数。它返回一个迭代器,所以如果你需要一个列表,你需要在结果上明确使用list()
>>> import itertools
>>> f = lambda: 42
>>> L = [(), (), ()]
>>> values = itertools.starmap(f, L)
>>> print list(values)
[42, 42, 42]
在一般情况下,它适用于任何参数元组:
>>> f = lambda *x: sum(x)
>>> L = [(1,2), (4, ), (5,6)]
>>> values = itertools.starmap(f, L)
>>> print list(values)
[3, 4, 11]
如果您想简单地多次调用函数并获得结果,您可以考虑使用列表推导或生成器表达式。
>>> f = lambda: 42
>>> [f() for _ in xrange(3)]
[42, 42, 42]
>>> values = (f() for _ in xrange(3))
>>> print list(values)
[42, 42, 42]
如果您的示例中包含空元组列表,则可以在xrange(len(L))
的位置使用xrange(3)
。
答案 2 :(得分:2)
这不是一个类方法,它缺少classmethod
装饰器而self
应该是cls
。但是你不需要这里的类方法,因为类方法是对类进行操作的方法(当然,你可以传递其他对象,但这不是预期的用例 - @classmethod
会产生严重误导)
您正在寻找术语“未绑定方法”,您可以通过引用类的成员而不是其实例来获取该术语。使用C.m
。请注意,该方法将使用self
作为(在您的示例中)调用元组,而不是C
的实例。通常,应该限制这种欺骗以避免这种情况(例如str.lower
并且一串字符串是O.K。)。
答案 3 :(得分:1)
你忘了装饰器使它成为一个类方法,但你可能想要一个静态方法:
静态:
class C(object):
@staticmethod
def m(arg):
return 42
类:
class C(object):
@classmethod
def m(cls, arg):
#cls is a reference to the actual "C" type, not an instance of the "C" class.
return 42
答案 4 :(得分:1)
首先,这不是一种类方法。类方法将类作为它的第一个参数,并在类上调用,而不是它的实例:
class C(object):
@classmethod
def m(cls):
return 42
map(C.m, range(10))
然而,由于map
将每个项目从iterable传递给函数,因此仍会中断,并且您的方法只接受一个参数,即类。
如果您更改方法以接受额外参数(def m(cls, arg)
),它将起作用。您也可以使用实例方法而不是类方法:
class C(object):
def m(self, *args): # or def m(self, n)
return 42
c = C()
map(c.m, range(10))
答案 5 :(得分:0)
m是一个1参数方法,它接受C类型的对象。语法“cm”实际上等同于“m(c)”,它只是42.但是42不是一个可以映射到的函数列表如[(),(),()]。
以下内容应该有效:
class C (object):
def f(self): return lambda x: x+1
two,three,four = map(C().f(), [1,2,3])
现在C()。 * 返回一个函数,而不是常量。