如何定义不带括号的函数?

12 投票
3 回答
10283 浏览
提问于 2025-04-17 03:56

我知道我的问题可能听起来有点傻,而且可能在语言的定义里有明确的规定禁止这种做法,但我并不知道这个规定是什么,所以想请教一下。简单来说,我想定义一个Python函数,可以在Python命令行中调用,但我希望能省略掉括号。有些情况下,函数不需要任何参数,这时候括号似乎只是用来表示我们在调用一个函数。例如,如果想打印当前的工作目录,我可以这样定义一个函数:

def pwd():
    print os.getcwd()

然后我可以在命令行中这样调用它:

pwd()

但是如果我想要一个函数,可以这样调用:

pwd

这样做可能吗?

3 个回答

4

这是不可能的。单纯提到一个变量(比如 pwd)并不会有什么特别的作用,它只是获取存储在那个变量中的引用。如果这个变量指向一个函数,那么这个引用就是指向一个函数,但无论如何,它只是一个引用,仅此而已。要真正调用任何东西,你必须使用函数调用的语法 - expression '(' arglist ')'

不过,这种情况不适用于对象的属性(也就是任何东西),因为获取一个成员在技术上已经算是一个函数调用,并且可以被重写。实际上,有很多方法可以影响 obj.member 的结果,其中最重要的有 __getattr____getattribute__ 和描述符中的 __get__。后面两个有类似于设置属性的功能(是的,这是一种不同的操作)。所有这些内容在 语言参考 中都有详细说明。

不过,使用这种方式来隐式调用一个过程(而不是获取器)仍然是个很糟糕的主意,因为这不符合直觉,会让代码变得不那么明显,而且除了省去两个括号外没有任何好处。这样做还会让你无法获取函数的引用,这样在进行函数式编程或受其启发的编程时会非常不方便(你 可以 使用 lambda: obj.pwd,但这显得更不明显且更难看)。

11

你不能在不修改语言或命令行的情况下做到这一点。

如果你想把Python当作命令行来用,建议你试试IPython。它允许你定义一些快捷方式,这样你就不用敲那么多键了。比如,你可以用!pwd来查看当前目录,并且可以把这个结果赋值给一个变量,比如x = !pwd。它甚至允许你用f x来调用只需要一个参数的函数,而不是f(x)

顺便提一下,Haskell是一种使用空格来传递参数的语言,比如在Python中写f(1,2,3),在Haskell中就写成f 1 2 3。在命令行中,任何输入输出操作只需要输入action就可以执行。

我忘了提还有一个小技巧:

class Pwd(object):
    def __repr__(self):
        # do pwd command
        # return result in string form
pwd = Pwd()

现在当你在命令行输入pwd时,它会调用__repr__来获取对象的字符串表示。不过不幸的是,你只能返回一个字符串(而不能返回一个表示当前目录下文件/文件夹的字符串列表,比如如果你在实现ls命令的话),这是因为Python语言的限制。

11

你可能会在这里遇到一些语法问题。你可以试试下面这样的写法:

import os
class Shell(object):
    @property
    def pwd(self):
        print os.getcwd()

然后在你的解释器中运行:

>>> s = Shell()
>>> s.pwd
/tmp

撰写回答