Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python和C中声明函数的区别_Python_C - Fatal编程技术网

在Python和C中声明函数的区别

在Python和C中声明函数的区别,python,c,Python,C,我现在正在同时阅读和学习Python和C。(别问我为什么,这很有趣!:-) 我使用马克·卢茨的“学习Python”。以下是他用Python编写的函数: 与C等编译语言不同,Python函数不需要 在程序运行之前完全定义。更一般地说,DEF是 直到到达并运行它们,并且DEF中的代码 在以后调用函数之前不会计算 我不太明白,因为在我的第二本书K.N.King中说,可以先声明一个函数,然后再创建一个定义 英语不是我的母语,所以我缺少什么 我只能猜测,它与程序运行时有关。在C语言中,编译器运行程序并找到

我现在正在同时阅读和学习Python和C。(别问我为什么,这很有趣!:-) 我使用马克·卢茨的“学习Python”。以下是他用Python编写的函数:

与C等编译语言不同,Python函数不需要 在程序运行之前完全定义。更一般地说,DEF是 直到到达并运行它们,并且DEF中的代码 在以后调用函数之前不会计算

我不太明白,因为在我的第二本书K.N.King中说,可以先声明一个函数,然后再创建一个定义

英语不是我的母语,所以我缺少什么

我只能猜测,它与程序运行时有关。在C语言中,编译器运行程序并找到函数声明。即使未定义函数,编译器也会继续,并在以后查找函数定义。C中的函数声明有助于避免函数返回类型的问题(因为它默认为int)。另一方面,在Python中,只有在运行时到达函数时才会对其求值。当到达它时,它不会计算函数体,直到有一个函数调用。但这一猜测并不能解释上面的一句话


那么卢茨先生在说什么?我有点困惑…

Python函数在源代码中被“执行”:

def foo():
    return bar

def bar():
    return 'spam'
这里的
foo
取决于
bar
,但是在声明
foo
之前不执行
bar
函数定义并不重要。只有在随后调用
foo()
时,名称
bar
才需要存在

但是,在C中,如果没有附加的原型声明,则无法执行上述操作:

char*bar(无效);
char*foo(无效){
返回杆();
}
字符*条(无效){
返回“垃圾邮件”;
}
因此,是的,您可以推迟
bar
的完整声明,但编译器要求您仍然提前声明函数签名


因此,Python在运行时之前并不关心是否定义了
bar
,C要求在编译时声明函数。

在下面的示例中,当我们第一次开始执行时,没有定义
text\u func
。在python中,当我们执行def行时,函数是在运行时定义的

print ('Entry point. No custom functions/methods are defined at this point')

print ('Defining test_func')
# We defined a function here.
# The function is defined at runtime since python when we run this line
def test_func():
    # Obviously, the body of the function is executed only when we call the function.
    # Not when we define it
    print ('evaluating test_func now')


print ('test_func is now defined.')

test_func()

在C语言中,您可以编译而无需声明,编译器采用函数 如果您的程序编译并运行时是int。
如果你的函数是另一种类型,你会遇到问题,你必须声明。通常,不将声明从代码声明到h文件并在需要时包含声明会更快。您可以将它留给程序来编写程序的这一部分。就像你可以留下缩进一样,写一堆乱七八糟的东西,让缩进替你做

在python中,没有转发声明之类的东西。函数(代码)中引用的符号在函数被调用之前不会被查找。这就是为什么不需要按顺序定义函数。比如说

def foo():
    return bar()

def bar():
    return 42

foo()
首先,这些都是经过编译的,但我将跳过这些细节。执行代码时,将首先定义一个名为
foo
的函数,其主体/代码为“查找名为
bar
的对象并调用它,然后返回返回值”。类似的情况也发生在
条上。最后在
foo()
处,解释器运行代码说“找到名为
foo的东西并调用它”。这里定义了
foo
,因此它被调用,它的主体被执行,但是上面说“找到一个叫做
bar
的东西并调用它”,但是在这一点上,我们已经通过了定义
bar
的点

现在让我们看看C:

int foo() {
    return bar();
}

int bar() {
    return 42;
}
现在我们这里有一些小问题,因为名称查找必须在构建时完成,这在这里不是一个大问题,但是请记住,C编译器按顺序处理源代码,所以它不会向前看。因此,在编译
foo
时,它会看到您试图调用一个名为
bar
的函数,而编译器不知道它是什么-因此它假设您正确使用了
bar
,并指出它是一个不带参数的函数,并返回
int
(没有传递参数,默认情况下,它假定返回int)。然后,当您达到
bar
的定义时,幸运的是,您的假设是正确的(因为编译器已经下定决心,并在
foo
中生成代码,假设是正确的-否则您将得到奇怪的行为)。最后(链接时)它将解析所有符号(无论您将声明的顺序如何),名称的占位符将只是名称所指内容的引用。此时,实现可能会删除名称,因为它们对程序没有任何用途(但可能会选择保留它们,因为如果需要调试程序,它可能会有所帮助)

现在,如果您想更安全一点,您可以使用前向声明的
bar
,以便编译器可以检查您是否使用正确类型的参数调用它(并将返回值解释为正确类型)。然后您可以:

int bar(void);

int foo(void) {
    return bar();
}

int bar(void) {
    return 42;
} 

如果你在C++中做了这个程序,那么以后的方法是强制性的,因为C++不允许猜测参数类型,但是你也建议在C中这样做(在第一个C示例中有编译器警告,编译器必须猜测什么是代码> Bar < /Cord>)。“在到达并运行DEF之前不会对其进行计算”对我来说意味着(也学习Python:-),您甚至可以在函数体中出现错误,但在执行未到达对该函数的调用之前,错误是错误的unnoticed@rolika,取决于错误。语法错误将在程序开始执行之前导致崩溃。其他错误将等待