返回顶部
首页 > 资讯 > 后端开发 > Python >Python函数属性和PyCodeObj
  • 245
分享到

Python函数属性和PyCodeObj

函数属性Python 2023-01-30 22:01:07 245人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。注意,属性是和对象相关的,和作用域无关。 自定义属性 自定义函数自己的属性方式很简单。假设函数名称为myfunc,那么为这个函数添加一个属性var

python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。注意,属性是和对象相关的,和作用域无关。

自定义属性

自定义函数自己的属性方式很简单。假设函数名称为myfunc,那么为这个函数添加一个属性var1:

myfunc.var1="abc"

那么这个属性var1就像是全局变量一样被访问、修改。但它并不是全局变量。

可以跨模块自定义函数的属性。例如,在b.py中有一个函数b_func(),然后在a.py中导入这个b.py模块,可以直接在a.py中设置并访问来自b.py中的b_func()的属性。

import b
b.b_func.var1="hello"
print(b.b_func.var1)  # 输出hello

查看函数对象属性

Python函数是一种对象,是对象就会有对象的属性。可以通过如下方式查看函数对象的属性:

dir(func_name)

例如,有一个属性__name__,它表示函数的名称:

def f(x):
    y=10
    def g(z):
        return x+y+z
    return g

print(f.__name__)   # 输出f

还有一个属性__code__,这个属性是本文的重点,它表示函数代码对象:

print(f.__code__)

输出:

<code object f at 0x0335B180, file "a.py", line 2>

上面的输出结果已经指明了__code__也是对象,既然是对象,它就有自己的属性:

print( dir(f.__code__) )

现在,就可以看到函数代码对象相关的属性,其中有一类属性都以co_开头,表示字节码的意思,后文会详细解释这些属性的意义。实际上,并非只有函数具有这些属性,所有的代码块(code block)都有这些属性。

[...省略其它非co_属性...
'co_arGCount', 'co_cellvars',
'co_code', 'co_consts',
'co_filename', 'co_firstlineno',
'co_flags', 'co_freevars',
'co_kwonlyargcount', 'co_lnotab',
'co_name', 'co_names', 'co_nlocals',
'co_stacksize', 'co_varnames']

如何查看这些__code__的属性?使用f.__code__.co_XXX即可。由于dir()返回的是属性列表,所以下面使用循环将co_开头的属性都输出出来:

for i in dir(f.__code__):
    if i.startswith("co"):
        print(i+":",eval("f.__code__."+i))

输出结果:

co_argcount: 1
co_cellvars: ('x', 'y')
co_code: b'd\x01\x89\x01\x87\x00\x87\x01f\x02d\x02d\x03\x84\x08}\x01|\x01S\x00'
co_consts: (None, 10, <code object g at 0x02FB7338, file "g:/pycode/b.py", line 3>, 'f.<locals>.g')
co_filename: g:/pycode/b.py
co_firstlineno: 1
co_flags: 3
co_freevars: ()
co_kwonlyargcount: 0
co_lnotab: b'\x00\x01\x04\x01\x0e\x02'
co_name: f
co_names: ()
co_nlocals: 2
co_stacksize: 3
co_varnames: ('x', 'g')

此外,还可以使用dis模块的show_code()函数来输出这些信息的整理:

import dis
def f(x):
    y=10
    def g(z):
        return x+y+z
    return g

print(dis.show_code(f))

输出结果:

Name:              f
Filename:          g:/pycode/b.py
Argument count:    1
Kw-only arguments: 0
Number of locals:  2
Stack size:        3
Flags:             OPTIMIZED, NEWLOCALS
Constants:
   0: None
   1: 10
   2: <code object g at 0x00A89338, file "g:/pycode/b.py", line 4>
   3: 'f.<locals>.g'
Variable names:
   0: x
   1: g
Cell variables:
   0: x
   1: y
None

__code__属性的解释

这些属性定义在python源码包的Include/code.h文件中,如有需要,可自行去查看。

另外,这些属性是代码块(code block)的,不限于函数。但此处以函数为例进行说明。

由于这些属性中涉及到了闭包属性(或者嵌套函数的属性),所以以下面这个a.py文件中的嵌套函数为例:

import dis
x=3
def f(a,b,*args,c):
    a=3
    y=10
    print(a,b,c,x,y)
    def g(z):
        return a+b+c+x+z
    return g

以下是查看函数f()和闭包函数g()的方式:

# f()的show_code结果
dis.show_code(f)

# f()的co_XXX属性
for i in dir(f.__code__):
    if i.startswith("co"):
        print(i+":",eval("f.__code__."+i))

# 闭包函数,注意,传递了*args参数
f1=f(3,4,"arg1","arg2",c=5)

# f1()的show_code结果
dis.show_code(f1)

# f1()的co_XXX属性
for i in dir(f1.__code__):
    if i.startswith("co"):
        print(i+":",eval("f1.__code__."+i))

下面将根据上面查看的结果解释各属性:

co_name
函数的名称。

上例中该属性的值为外层函数f和闭包函数g,注意不是f1。

co_filename
函数定义在哪个文件名中。

上例中为a.py

co_firstlineno
函数声明语句在文件中的第几行。即def关键字所在的行号。

上例中f()的行号为3,g()的行号为7。

co_consts
该函数中使用的常量有哪些。python中并没有专门的常量概念,所有字面意义的数据都是常量。

以下是show_code()得到的f()中的常量:

Constants:
   0: None
   1: 3
   2: 10
   3: <code object g at 0x0326B7B0, file "a.py", line 7>
   4: 'f.<locals>.g'

而内层函数g()中没有常量。

co_kwonlyargcount
keyWord-only的参数个数。

f()的keyword-only的参数只有c,所以个数为1
g()中没有keyword-only类的参数,所以为0

co_argcount
除去*args之外的变量总数。实际上是除去***所收集的参数以及keyword-only类的参数之后剩余的参数个数。换句话说,是***前面的位置参数个数。

f()中属于此类参数的有a和b,所以co_argcount数值为2
g()中只有一个位置参数,所以co_argcount数值为1

co_nlocals
co_varnames
本地变量个数和它们的名称,变量名称收集在元组中。

f()的本地变量个数为6,元组的内容为:('a', 'b', 'c', 'args', 'y', 'g')
g()的本地变量个数为1,元组的内容为:('z',)

co_stacksize
本段函数需要在栈空间评估的记录个数。换句话说,就是栈空间个数。

这个怎么计算的,我也不知道。以下是本示例的结果:
f()的栈空间个数为6
g()的栈空间个数为2

co_names
函数中保存的名称符号,一般除了本地变量外,其它需要查找的变量(如其它文件中的函数名,全局变量等)都需要保存起来。

f()的co_names:

Names:
   0: print
   1: x

g()的co_names:

Names:
   0: x

co_cellvars
co_freevars
这两个属性和嵌套函数(或者闭包有关),它们是互相对应的,所以内容完全相同,它们以元组形式存在。

co_cellvars是外层函数的哪些本地变量被内层函数所引用
co_freevars是内层函数引用了哪些外层函数的本地变量

对外层函数来说,co_freevars一定是空元组,对内层函数来说,co_cellvars则一定是空元组。

如果知道自由变量的概念,这个很容易理解。

f()的co_cellvars内容: ('a', 'b', 'c')
g()的co_freevars内容: ('a', 'b', 'c')

co_code
co_flags
co_lnotab
这3个属性和python函数的源代码编译成字节码有关,本文不解释它们。

属性和字节码对象PyCodeObject

对于python,通常都认为它是一种解释型语言。但实际上它在进行解释之前,会先进行编译,会将python源代码编译成python的字节码(bytecode),然后在python virtual Machine(PVM)中运行这段字节码,就像Java一样。但是PVM相比JVM而言,要更"高级"一些,这个高级的意思和高级语言的意思一样:离物理机(处理机器码)的距离更远,或者说要更加抽象。

源代码被python编译器编译的结果会保存在内存中一个名为PyCodeObject的对象中,当需要运行时,python解释器开始将其放进PVM中解释执行,执行完毕后解释器会"根据需要"将这个编译的结果对象持久化到二进制文件*.pyc中。下次如果再执行,将首先从文件中加载(如果存在的话)。

所谓"根据需要"是指该py文件是否只运行一次,如果不是,则写入pyc文件。至少,对于那些模块文件,都会生成pyc二进制文件。另外,使用compileall模块,可以强制让py文件编译后生成pyc文件。

但需要注意,pyc虽然是字节码文件,但并不意味着比py文件执行效率更高,它们是一样的,都是一行行地读取、解释、执行。pyc唯一比py快的地方在导入,因为它无需编译的过程,而是直接从文件中加载对象。

py文件中的每一个代码块(code block)都有一个属于自己的PyCodeObject对象。每个代码块除了被编译得到的字节码数据,还包含这个代码块中的常量、变量、栈空间等内容,也就是前面解释的各种co_XXX属性信息。

pyc文件包含3部分:

  • 4字节的Magic int,表示pyc的版本信息
  • 4字节的int,是pyc的产生时间,如果与py文件修改时间不同,则会重新生成
  • PycodeObject对象序列化的内容

参考文章:https://blog.csdn.net/efeics/article/details/9255193

--结束END--

本文标题: Python函数属性和PyCodeObj

本文链接: https://lsjlt.com/news/180184.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python函数属性和PyCodeObj
    python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。注意,属性是和对象相关的,和作用域无关。 自定义属性 自定义函数自己的属性方式很简单。假设函数名称为myfunc,那么为这个函数添加一个属性var...
    99+
    2023-01-30
    函数 属性 Python
  • Python函数属性和PyC详解
    目录函数属性自定义属性查看函数对象属性属性和字节码对象PyCodeObject总结函数属性 python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。...
    99+
    2024-04-02
  • Python 语言学习函数(参数、lamdba和函数属性)
       函数的参数是参数暴露给外部的接口,向函数传递参数,可以控制函数的流程,函数可以0个、1个或多个参数;在Python中向函数传参,使用的是赋值方式。  一,传递参数  参数是通过赋值来传递的,传递参数的特点是:  参数的传递是...
    99+
    2023-06-02
  • Python-VTK隐式函数属性选择和剪切数据
    前言: VTK,(visualizationtoolkit)是一个开放资源的免费软件系统,主要用于三维计算机图形学、图像处理和可视化。Vtk是在面向对象原理的基础上设计和实现的,它的...
    99+
    2024-04-02
  • python类属性和实例属性
        python中的类属性只是存储与类相关的数据,和该类的实例无关。类属性和java中的静态成员变量类似。访问python的类属性可使用类名+“.”+属性名的方式,如果类的实例没有同名变量也可以使用实例来访问。如果实例含有与类属性同名的...
    99+
    2023-01-31
    实例 属性 类属
  • Python中os.path函数有哪些属性
    本篇文章为大家展示了Python中os.path函数有哪些属性,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。获取当前时间# -*- coding: gbk -...
    99+
    2023-06-17
  • Python的dir()函数:查看对象的属性和方法
    Python的dir()函数:查看对象的属性和方法,需要具体代码示例摘要:Python是一种强大而灵活的编程语言,其内置函数和工具为开发人员提供了许多方便的功能。其中一个非常有用的函数是dir()函数,它允许我们查看一个对象的属性和方法。本...
    99+
    2023-11-18
    方法 属性 dir()
  • python 公有属性和私有属性
    十三、python 公有属性和私有属性 属性: 方法: class Chinese(Person): nation = 'China' def __init__(self,name): self.__name = name def m...
    99+
    2023-01-31
    属性 python
  • Python-VTK隐式函数属性选择和剪切的方法
    这篇文章主要介绍“Python-VTK隐式函数属性选择和剪切的方法”,在日常操作中,相信很多人在Python-VTK隐式函数属性选择和剪切的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python-VT...
    99+
    2023-06-30
  • python基础之类属性和实例属性
    属性:类属性和实例属性 类属性:就是类对象所有的属性 小结 '类属性 是可以 被 类对象和实例对象共同访问的 实例属性只能由实例对象访问 class Student: ...
    99+
    2024-04-02
  • python类的私有属性和公共属性说明
    目录python类私有属性和公共属性python私有属性的定义python类私有属性和公共属性 对于python而言,类的属性的可见度只有两种,public和private。 类的私...
    99+
    2024-04-02
  • python中有哪三种属性管理魔法函数
    这篇文章将为大家详细讲解有关python中有哪三种属性管理魔法函数,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、说明_setattr_如果这个对象没有这个属性的话,设定未知的属性的话,就会调用这个方法...
    99+
    2023-06-15
  • css中perspective属性和perspective()函数有什么区别
    本篇内容主要讲解“css中perspective属性和perspective()函数有什么区别”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“css中perspective属性和perspecti...
    99+
    2023-07-04
  • c++中如何定义类,属性,和成员函数
    类是 c++ 中封装数据的模板,可以通过以下步骤定义:使用 class 关键字定义类名及其范围。在私有部分定义数据成员(属性)。在公共部分定义成员函数(方法),用于操作这些数据。 如何...
    99+
    2024-05-12
    c++
  • 实例属性和类属性
    实例属性   由于Python是动态语言,根据类创建的实例可以任意绑定属性   实例绑定属性的方法     1) 通过实例变量     2) 通过self变量   class Student(object):     de...
    99+
    2023-01-31
    实例 属性 类属
  • javascript条件式访问属性和箭头函数介绍
    目录一、条件式访问属性二、箭头函数介绍一、条件式访问属性 ?. 是ES2020引入的新特性,是一个条件式属性访问操作符,当你访问值为undefined变量的某个属性值时,如果...
    99+
    2024-04-02
  • Object.defineProperty()函数之属性描述对象
    目录概述Object.getOwnPropertyDescriptor()Object.getOwnPropertyNames()Object.defineProperty(),Ob...
    99+
    2024-04-02
  • python_类属性和实例属性
    class AAA():     aaa = 10           # 可AAA.aaa直接调用,当实例属性没重名时,也可以obj1.aaa调用                     # 有重名时 通过对象调用的是实例属性      ...
    99+
    2023-01-31
    实例 属性 类属
  • Python编程:递归与匿名函数及函数属性与文档字符串(函数补充)
    本文简单扼要地说,辅以代码进一步地加深理解。 递归函数当函数调用自身而生成最终结果时,这样的函数称为递归。有时递归函数非常有用,因为它们使编写代码变得更容易——使用递归范式编写一些算法非常容易,而其他算法则不是这样。没有不能以迭代方式重写的...
    99+
    2023-05-14
    Python 语言 递归函数
  • css中perspective属性和perspective()函数的异同点有哪些
    小编给大家分享一下css中perspective属性和perspective()函数的异同点有哪些,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! css per...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作