Python默认参数的函数

4

我如何在方法内访问qux?我真的需要在foo()的主体内重新定义它吗,还是有一种从self导入它的方法?

class Baz(object):

    qux = lambda x : x + '_quux'

    def foo(self, bar=qux('fred')):
        print bar

        print qux('waldo')
        # NameError: global name 'qux' is not defined

        print Baz.qux('waldo')
        # TypeError: unbound method <lambda>() must be called with Baz instance as first argument (got str instance instead)

        print Baz.qux(self, 'waldo')
        # TypeError: <lambda>() takes exactly 1 argument (2 given)

        print self.qux('waldo')
        # TypeError: <lambda>() takes exactly 1 argument (2 given)                
3个回答

7

如果你不是因为互操作性原因而实现现有的XML标准,创建某种导入/导出格式或创建某种XML编辑器或处理工具,那么请不要这样做。根本不要这样做。永远都不要这样做。甚至不要将其用于新的导入/导出格式;在Python中使用JSON更容易。 - Karl Knechtel
谢谢,我的实际用例是这样的 from os.path import expanduser; def foo(self, bar=expanduser('~/default')),你能推荐一种优雅的方法来实现吗? - wim
2
在方法体中使用 bar=None 并检查 bar is None - Ignacio Vazquez-Abrams

1

一个解决方案是使用

qux = staticmethod(lambda x : x + '_quux')

并访问它作为

Baz.qux('waldo')

我会将它移出这个类。

谢谢,我的实际用例类似于 from os.path import abspath, dirname, join, realpath, expanduser; psd = lambda s : realpath(join(dirname(abspath(__file__)), s)) .. 但我不想用那么多垃圾污染全局命名空间。 - wim
@wim,你的代码正在污染类命名空间,这非常糟糕。在模块级别导入即可。 - Winston Ewert
哦,这对沃尔多起作用了,但却破坏了弗雷德..现在我在第5行得到了“TypeError:'staticmethod'对象不可调用”的错误。 - wim

1

qux 被视为实例方法,因为对于看起来像函数的类成员,默认处理方式是如此(更具体地说,当您通过实例查找时,Baz.qux 具有隐式调用的 __get__ 来“绑定”第一个参数到实例)。但是,您没有在开头提供 self 参数。因此,baz 绑定到 x lambda 参数。

'self' 这个名称在 Python 中并没有什么神奇之处; 这只是一个约定。 方法绑定总是通过将函数绑定到第一个参数来工作。

如果您聪明的话,可以自己看到这一点:

class Baz(object):
    qux = lambda x: x + '_quux'
    def foo(self): return self.qux()

Baz().foo() # TypeError: unsupported operand type(s) for +: 'Baz' and 'str'
# because after binding Baz() to 'x', we get Baz() + '_quux'

一种解决方案是将qux显式地设置为staticmethod,就像Sven Marnach的答案中所示。 (您还可以将其设置为classmethod,这是Python特有的概念,更加强大; staticmethod更接近于Java等语言中static关键字的行为。)请注意,与Java一样,您也可以在foo内部使用self.qux访问staticmethod。这通过用staticmethod安装的新机制替换函数的正常__get__机制来实现。
另一种解决方案是在lambda参数中提供self参数。如果您实际上不想要“静态”行为(即需要实际对self进行操作),则这很有用-但看起来您确实需要这样做。仅为完整起见,这将如下所示:
qux = lambda self, x: x + '_quux'
def foo(self):
    return self.qux('foo')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接