解决Python 函数声明先后顺序出现的问题

在 Python 中如果把函数定义写在调用的下方可能会出错,例如下面的代码

foo()

def foo():
 print("hello")

执行时会报出错误

NameError: name 'foo' is not defined

这时候要把 foo() 调用代码放到该函数的声明后面

def foo():
 print("hello")

foo()

这样执行就一切正常了。这仿佛像是 C 语言中的函数调用需要提前声明一般,例如在 C 语言中要调用后头的定义的函数要写成

void foo();

int main() {
 foo();
}

void foo() {
 printf("Hello");
}

实际上 Python 中并不存在函数提前声明一说,也不能像 Java 那样函数可以写在任意位置,因为 Java 是编译型的语言,Python 是解释型的。

而且也不是一定要求被调用的函数一定要在源代码层面上定义在调用者前方。

Python 中函数声明的顺序据我理解有两条规则

  • Python 源代码是由上往下解释的
  • 找到程序入口(未包含在函数中的代码) 即开始执行,执行到的函数未被先行解释到即报错

分析下面两段代码

def foo():
 bar()

if __name__ == '__main__':
 foo()

def bar():
 print("hello")

Python 从第 1 行一直解释到第 4 行的入口,进而往回跳,调用到第 1 行的 foo() 函数,而其中的 bar() 函数还未及被解释到,所以会提示

NameError: name 'bar' is not define

有一个很好的分析工具 http://pythontutor.com/live.html#mode=edit,我们来看上面的代码

解释到第二行 bar() 的时候,Global frame 里只有 foo, bar 还不存在

如果把程序入口往后调

def foo():
 bar()

def bar():
 print("hello")

if __name__ == '__main__':
 foo()

上面代码执行无误,输出

hello

foo() 调用的 bar() 不也是在它下方声明的吗?所以这一点与 C 是有区别的。

也用http://pythontutor.com/live.html#mode=edit来看看

解释到第 8 行的时候在 Global frame 中 foo, bar 都有了,所以能成功调用。

这时候的理解是这样的,Python 从第 1 行自上往下解释到第 7 行的程序入口时,foo() 并未实际调用 bar(),但 foo() 和 bar() 函数都已解释到了,所以回过头来 foo() 与 bar() 之间怎么调用都无妨。

因此,最好的实践方法就是把程序的入口放到代码的最下方,那么它前面的函数不管如何的声明顺序都没有关系。

以上就是解决Python 函数声明先后顺序的问题的详细内容,更多关于python 函数声明顺序的资料请关注我们其它相关文章!

(0)

相关推荐

  • python函数声明和调用定义及原理详解

    这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前面文章接触到的type()/len()等等都是函数,这些函数是python的内置函数,python底层封装后用于实现某些功能. 一.函数的定义 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回:

  • Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作示例

    本文实例讲述了Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作.分享给大家供大家参考,具体如下: 实例对象也可以实现闭包的功能,不过实例对象消耗的资源(内存)比闭包多. demo.py(闭包): # 闭包,分割作用域. 外层函数内部嵌套内部函数,外层函数分割变量作用域,并返回内部函数的引用. # 外层函数负责分割作用域,内层函数才是闭包提供的功能. 外层函数返回内层函数的引用,供外部使用. def my_line(k, b): # k,b只在my_line函数以及creat

  • 举例讲解Python的lambda语句声明匿名函数的用法

    所谓匿名函数,即是不需要定义函数,像表达式一样使用,不需要函数名(很多时候名字让我很困扰),一些简单的函数简单化, 举个例子 我需要两个整数相加的函数,通常是这么定义的 def add(x, y): return x + y 很好的完成了我需要的功能, 但是我现在需要一个数字与字符串相加的函数 def addstr(x, y): return x + str(y) 又一次完成了我的需求,但是 我突然需要两个整数相减,相除的功能这样函数就得 一直写下去, 但是使用lambda 匿名函数可以直接使用

  • 解决Python 函数声明先后顺序出现的问题

    在 Python 中如果把函数定义写在调用的下方可能会出错,例如下面的代码 foo() def foo(): print("hello") 执行时会报出错误 NameError: name 'foo' is not defined 这时候要把 foo() 调用代码放到该函数的声明后面 def foo(): print("hello") foo() 这样执行就一切正常了.这仿佛像是 C 语言中的函数调用需要提前声明一般,例如在 C 语言中要调用后头的定义的函数要写成

  • 解决python super()调用多重继承函数的问题

    当类间继承关系很简单时,super()的使用很简单. class A(object): def __init__(self): print('a') class B(A): def __init__(self): super(B, self).__init__() print('b') b = B() 输出结果: a b 当一个类继承多个类时,问题就复杂起来了,请看下例: class A(object): def __init__(self): print('a') class B(object

  • 解决python中os.listdir()函数读取文件夹下文件的乱序和排序问题

    1. os.listdir()概述 os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表. 例如: dir ='F:/Home_01/img'#当前目录 filenames=os.listdir(dir)#filenames存储dir下的所有文件名. 注意:os.listdir()返回的文件名不一定是顺序的,也就是说结果是不固定的,如下图,则filenames[0]有可能为'22.jpg',而不是我们所希望的'11.jpg'. 解决办法: filenames=os.l

  • 详解Python函数作用域的LEGB顺序

    本文为大家介绍了Python函数作用域的查找顺序,供大家参考,具体内容如下 1.什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 2.LEGB是作什么用的? 为什么非要介绍这个呢?或者说它们的作用是什么? 原因是因为我们的在学习Python函数的时候,经常会遇到很多定义域的问题,全部变量,内部变量,内部嵌入的函数,等等,Python是如何查找的呢?以及Python又是按照什么顺序来查找

  • 解决python调用自己文件函数/执行函数找不到包问题

    写python程序的时候很多人习惯创建一个utils.py文件,存放一些经常使用的函数,方便其他文件调用,同时也更好的管理一些通用函数,方便今后使用.或是两个文件之间的class或是函数调用情况. 就像下面的工程目录一样: 工程目录 Project\ ... src\ main.py utils.py test.py ... python调用其他文件中的函数 在main.py文件中加入一下语句即可调用utils.py下面的函数:'' import src.utils as utils X, y

  • 详细介绍Python函数中的默认参数

    import datetime as dt def log_time(message, time=None): if time is None: time=dt.datetime.now() print("{0}: {1}".format(time.isoformat(), message)) 最近我在一段Python代码中发现了一个因为错误的使用默认参数而产生的非常恶心的bug.如果您已经知道关于默认参数的全部内容了,只是想嘲笑一下我这可笑的错误,请直接跳到本文末尾.哎,这段代码是我

  • Python函数的定义方式与函数参数问题实例分析

    本文实例讲述了Python函数的定义方式与函数参数问题.分享给大家供大家参考,具体如下: 涉及内容: 函数的定义方式 函数的文字描述 空操作语句 位置参数 默认参数 关键参数 可变长度参数 函数的定义方式: 函数的文字说明: 为了让别人了解函数的意义,或者避免自己遗忘,可以使用 字符串(不需要赋值,单引号,双引号,多引号都行).#注释 将文字说明写在函数最开始的位置 def function1() : """ 这是这个程序的说明文字 """ pr

  • Python函数参数类型*、**的区别

    刚开始学习python,python相对于java确实要简洁易用得多.内存回收类似hotspot的可达性分析, 不可变对象也如同java得Integer类型,with函数类似新版本C++的特性,总体来说理解起来比较轻松.只是函数部分参数的"*"与"**",闭包等问题,着实令人迷糊了一把,弄清概念后写下此文记录下来,也希望本文能够帮助其他初学者. 所以本文是一篇学习笔记,着重于使用的细节和理解上,首先分别介绍了函数各种参数类型在调用和声明时的区别,及其在混用时需要注意

  • 布同自制Python函数帮助查询小工具

    比如在学习list.tuple.dict.str.os.sys等模组的时候,利用Python的自带文档可以很快速的全面的学到那些处理的函数.所以这个自带文档功能能够给出学者带来很大的方便之处,进行简短的开发是再好不过的. 但是,当你离开CMD,要利用IDLE或者要用Komodo Edit等软件进行"段式编程"的时候,就有些捉襟见肘了.例如,wx库非常之大,帮助文件有10MB之多,如果你在CMD中打开,你可以想想你需要多少时间才能够查看到你想要的帮助信息.大规模的熟悉Python的各种A

随机推荐