python函数中的变量_为什么在Python中定义变量之前就可以在函数...

本文详细介绍了Python中函数的定义与执行的区别。在Python中,函数定义时仅编译为代码对象,不会立即执行。只有在调用函数时,才会执行其代码。这种延迟执行允许在函数定义时引用尚未定义的变量,只要在调用时这些变量已存在。类定义也类似,但类定义期间的命名空间会被执行。未在类定义中定义的变量在后续方法中使用时,Python会像处理函数一样处理它们。
摘要由CSDN通过智能技术生成

要了解正在发生的事情,必须了解Python在定义函数和执行函数之间的区别.

定义与执行

当Python遇到函数定义时,它将函数编译为代码对象.

然后,将代码对象用于构造功能对象.然后,在以后调用该函数时,将使用该函数对象的代码对象来执行该函数. Python不会执行该函数,它只会将该函数编译成一个对象,以后可以用于执行. Python唯一执行函数的时间就是该函数被调用的时间.

A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object (a wrapper around the executable code for the function). This function object contains a reference to the current global namespace as the global namespace to be used when the function is called.

The function definition does not execute the function body; this gets executed only when the function is called.

由于这种区别,Python在调用函数之前无法验证名称是否已实际定义.因此,允许您在函数主体中使用当前不存在的名称.只要在调用函数时定义了名称,Python就不会引发错误.

这是一个例子.我们定义了一个将两个变量加在一起的函数func. a和b:

>>> def func():

... return a + b

如您所见,Python没有引发任何错误.这是因为它只是编译了func.它没有尝试执行该函数,因此看不到未定义a和b.

我们可以反汇编func的代码对象,并使用dis模块查看字节码的外观.这将告诉我们有关Python正在做什么的更多信息:

>>> from dis import dis

>>> dis(func)

2 0 LOAD_GLOBAL 0 (a)

2 LOAD_GLOBAL 1 (b)

4 BINARY_ADD

6 RETURN_VALUE

Python用字节码编码了两个LOAD_GLOBAL指令.指令的参数分别是变量名a和b.

这表明Python确实看到我们在编译函数时尝试引用两个变量,并创建了字节码指令来这样做.但是,在调用该函数之前,它不会尝试实际执行指令.

让我们看看当尝试通过调用func的字节码时会发生什么:

>>> func()

Traceback (most recent call last):

File "", line 1, in

func()

File "", line 2, in func

return a + b

NameError: name 'a' is not defined

如您所见,Python引发了NameError.这是因为它试图执行两个LOAD_GLOBAL指令,但是发现该名称在全局范围中未定义.

现在让我们看看如果在调用func之前定义两个变量a和b会发生什么:

>>> a = 1

>>> b = 2

>>>

>>> func()

3

上面的方法起作用的原因是因为当Python执行func的字节码时,它能够找到全局变量a和b,并使用它们来执行函数.

同样适用于示例的问题.编译main时,Python“看到”了我们试图调用一个名为cube的变量并生成一条指令以获取cube的值.但是在执行指令之前,它没有尝试找到名为多维数据集的可调用对象.并且在执行main的字节码时(例如调用main),定义了一个名为cube的函数,因此Python不会引发错误.

但是,如果尝试在定义多维数据集之前调用main,则由于上述示例中的相同原因,我们将收到名称错误:

>>> def main():

... number = int(input('Enter a number: '))

... cubed_number = cube(number)

... print("The number cubed is: ", cubed_number)

...

>>> main()

Enter a number: 23

Traceback (most recent call last):

File "", line 1, in

main()

File "", line 3, in main

cubed_number = cube(number)

NameError: name 'cube' is not defined

那班呢?

Python处理类定义与处理函数定义有些不同.

当Python遇到类定义时,它将与该函数一样为该类创建一个代码对象.但是,Python还允许类具有在类定义期间执行的名称空间. Python不会等待执行类名称空间,因为定义的任何变量都应该属于该类.因此,必须定义在类名称空间内使用的任何名称,以便在类定义期间使用.

The class’s suite is then executed in a new execution frame (see Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved.

但是,这不适用于方法. Python将方法中的未定义名称与函数一样对待,并允许您在定义方法时使用它们:

>>> class Class:

... def method(self):

... return var

...

>>> var = 10

>>> cls = Class()

>>> cls.method()

10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值