iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >javassist的介绍
  • 370
分享到

javassist的介绍

2023-06-14 11:06:28 370人浏览 薄情痞子
摘要

这篇文章主要介绍“javassist的介绍”,在日常操作中,相信很多人在javassist的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”javassist的介绍”的疑惑有所帮助!接下来,请跟着小编一起来

这篇文章主要介绍“javassist的介绍”,在日常操作中,相信很多人在javassist的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”javassist的介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、Javassist入门

(一)Javassist是什么

Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编辑类文件的。

(二)Javassist核心api

在Javassist中每个需要编辑的class都对应一个CtCLass实例,CtClass的含义是编译时的类(compile time class),这些类会存储在Class Pool中(Class poll是一个存储CtClass对象的容器)。
CtClass中的CtField和CtMethod分别对应Java中的字段和方法。通过CtClass对象即可对类新增字段和修改方法等操作了。

javassist的介绍

(三)简单示例

为了减少演示的复杂度,示例以及之后的操作,都在Maven项目下进行,因为我们可以直接引入依赖就可以达到我们导包的目的,很方便,不用再去下载jar包,然后自己手动导入了。

创建一个maven项目

如果你使用的是idea,可以像我一样;如果是其他工具,可以自行百度,或者按照自己的经验来创建即可。

javassist的介绍

创建一个测试类,代码如下:

package com.ssdmbbl.javassist;import javassist.*;import java.io.IOException;public class JavassistTest {    public static void main(String[] args) throws CannotCompileException, IOException {        ClassPool cp = ClassPool.getDefault();        CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");        ctClass.writeFile("./");    }}

当运行这个代码的时候,可以看到已经在项目的根目录下创建了一个“com.ssdmbbl.javassist”包,在这个包下创建了“Hello.java”的java文件。

javassist的介绍

内容如下:

package com.ssdmbbl.javassist;public class Hello {    public Hello() {    }}

二、Javassist操作字节码示例

回想一下,咱们如果对一个Java正常操作的话,大概存在哪些操作呢?

  • 咱们会对一个类添加字段;

  • 咱们会对一个类添加方法;

好像没其他的了吧。其余的就是在方法里写代码了呗。

(一)新增一个方法

咱们继续套用上面简单示例的代码,在此基础之上进行新增一个方法。

新增方法的名字为"hello1",传递两个参数分别为int和double类型,并且没有返回值。

package com.ssdmbbl.javassist;import javassist.*;import java.io.IOException;import java.net.URL;public class JavassistTest2 {    public static void main(String[] args) throws CannotCompileException, IOException {        //找到本文件的路径,与之保存在一起        URL resource = JavassistTest2.class.getClassLoader().getResource("");        String file = resource.getFile();        System.out.println("文件存储路径:"+file);        ClassPool cp = ClassPool.getDefault();        CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");        //创建一个类名为"hello",传递参数的顺序为(int,double),没有返回值的类                CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);//设置hello方法的权限为public        ctMethod.setModifiers(Modifier.PUBLIC);                //向ctClass中添加这个方法        ctClass.addMethod(ctMethod);                //写入本地        ctClass.writeFile(file);    }}

执行后,就可以查看生成的代码了:

可以看到,我们并没有指定参数的名字,也会给生成var1、var2依次类推的名字。

var1和var2其实class变量表中存放的名字。

package com.ssdmbbl.javassist;public class Hello {    public void hello1(int var1, double var2) {    }    public Hello() {    }}

可以设置的返回值类型:

public static CtClass booleanType;public static CtClass charType;public static CtClass byteType;public static CtClass shortType;public static CtClass intType;public static CtClass longType;public static CtClass floatType;public static CtClass doubleType;public static CtClass voidType;

(二)新增一个变量

URL resource = JavassistTest2.class.getClassLoader().getResource("");String file = resource.getFile();System.out.println("文件存储路径:"+file);ClassPool cp = ClassPool.getDefault();CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");//添加一个hello1的方法CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);ctMethod.setModifiers(Modifier.PUBLIC);ctClass.addMethod(ctMethod);//添加一个int类型的,名字为value的变量CtField ctField = new CtField(CtClass.intType,"value",ctClass);ctField.setModifiers(Modifier.PRIVATE);ctClass.addField(ctField);ctClass.writeFile(file);

那么执行后的内容就是如下了:

package com.ssdmbbl.javassist;public class Hello {    private int value;    public void hello1(int var1, double var2) {    }    public Hello() {    }}

(三)给变量新增get和set方法

代码修改如下:

   public static void main(String[] args) throws CannotCompileException, IOException {        URL resource = JavassistTest2.class.getClassLoader().getResource("");        String file = resource.getFile();        System.out.println("文件存储路径:"+file);        ClassPool cp = ClassPool.getDefault();        CtClass ctClass = cp.makeClass("com.ssdmbbl.javassist.Hello");        //添加一个hello1的方法        CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);        ctMethod.setModifiers(Modifier.PUBLIC);        ctClass.addMethod(ctMethod);        //添加一个int类型的,名字为value的变量        CtField ctField = new CtField(CtClass.intType,"value",ctClass);        ctField.setModifiers(Modifier.PRIVATE);        ctClass.addField(ctField);        //为value变量添加set方法        CtMethod setValue = new CtMethod(CtClass.voidType, "setValue", new CtClass[]{CtClass.intType}, ctClass);        setValue.setModifiers(Modifier.PUBLIC);        ctClass.addMethod(setValue);        //为value变量添加get方法        CtMethod getValue = new CtMethod(CtClass.intType, "getValue", new CtClass[]{}, ctClass);        getValue.setModifiers(Modifier.PUBLIC);        ctClass.addMethod(getValue);        ctClass.writeFile(file);    }

执行效果:

package com.ssdmbbl.javassist;public class Hello {    private int value;    public void hello1(int var1, double var2) {    }    public void setValue(int var1) {    }    public int getValue() {    }    public Hello() {    }}

(四)给方法内部添加代码

你是不是很好奇,set和get方法内部并没有代码,当程序运行的时候,肯定会出错的。
下面就来看一下。

我们预想的结果:

private int value;    public void setValue(int var1) {        this.value = var1    }    public int getValue() {        return this.value;    }

修改如下:

//为value变量添加set方法CtMethod setValue = new CtMethod(CtClass.voidType, "setValue", new CtClass[]{CtClass.intType}, ctClass);setValue.setModifiers(Modifier.PUBLIC);//设置方法体setValue.setBody("this.value = var1;");ctClass.addMethod(setValue);//为value变量添加get方法CtMethod getValue = new CtMethod(CtClass.intType, "getValue", new CtClass[]{}, ctClass);getValue.setModifiers(Modifier.PUBLIC);//设置方法体getValue.setBody("return this.value;");ctClass.addMethod(getValue);

很倒霉,说找不到这个var1这个变量

报错的堆栈信息如下:

Exception in thread "main" javassist.CannotCompileException: [source error] no such field: var1
at javassist.CtBehavior.setBody(CtBehavior.java:474)
at javassist.CtBehavior.setBody(CtBehavior.java:440)
at com.ssdmbbl.javassist.JavassistTest2.main(JavassistTest2.java:41)
Caused by: compile error: no such field: var1

这个原因我们前面其实提到了,因为在编译的时候,会把变量名抹掉,传递的参数会依次在局部变量表中的顺序。

如果传递:

public void test(int a,int b,int c){    ...}

那么a,b,c就对应本地变量表中的1,2,3的位置。

 —— ——|a|1||b|2||c|3| —— ——

那么我们获取变量时就不能使用原始的名字了,在Javassist中访问方法中的参数使用的是$1, 2 , 2, 2,…,而不是直接使用原始的名字。

我们修改如下:

//为value变量添加set方法CtMethod setValue = new CtMethod(CtClass.voidType, "setValue", new CtClass[]{CtClass.intType}, ctClass);setValue.setModifiers(Modifier.PUBLIC);//设置方法体setValue.setBody("this.value = $1;");ctClass.addMethod(setValue);//为value变量添加get方法CtMethod getValue = new CtMethod(CtClass.intType, "getValue", new CtClass[]{}, ctClass);getValue.setModifiers(Modifier.PUBLIC);//设置方法体getValue.setBody("return this.value;");ctClass.addMethod(getValue);

结果成功了:

public class Hello {    private int value;    public void hello1(int var1, double var2) {    }    public void setValue(int var1) {        this.value = var1;    }    public int getValue() {        return this.value;    }    public Hello() {    }}

再来一个:修改hello1方法体,使传递的两个参数相加然后赋值给value;

//添加一个hello1的方法CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody("this.value = $1 + $2;");ctClass.addMethod(ctMethod);

执行结果如下:

因为我们value是int,$1是int,$2是double,所以做了强制转型处理。

public void hello1(int var1, double var2) {    this.value = (int)((double)var1 + var2);}

(五)在方法体的前后分别插入代码

测试代码如下:

//添加一个hello1的方法CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody("this.value = $1 + $2;");ctMethod.insertBefore("System.out.println(\"我在前面插入了:\"+$1);");ctMethod.insertAfter("System.out.println(\"我在最后插入了:\"+$1);");ctClass.addMethod(ctMethod);

结果如下:

public void hello1(int var1, double var2) {    System.out.println("我在前面插入了:" + var1);    this.value = (int)((double)var1 + var2);    Object var5 = null;    System.out.println("我在最后插入了:" + var1);}

三、Javassist中的一些特殊参数示例讲解

在官方文档中看到有几个比较特殊的标识符,还有几个比较特殊的标识符需要了解。

标识符作用
$0、$1、$2、 3 、 3、 3、…this和方法参数(1-N是方法参数的顺序)
$args方法参数数组,类型为Object[]
$$所有方法参数,例如:m($$)相当于m($1,$2,…)
$cflow(…)control flow 变量
$r返回结果的类型,在强制转换表达式中使用。
$w包装器类型,在强制转换表达式中使用。
$_返回的结果值
$sig类型为java.lang.Class的参数类型对象数组
$type类型为java.lang.Class的返回值类型
$class类型为java.lang.Class的正在修改的类

下面咱们来一起分别来看一下,分析一下,怎么用,有什么用吧。

只介绍几个常见和常用到的吧。
有兴趣的话,剩下的可以看官方文档:Http://www.javassist.org/tutorial/tutorial2.html

(一)$0,$1,$2,…

这个其实咱们已经在上面用到过了,再来细说一下吧。$0代表this,$1, 2 , 2, 2,…,依次对应方法中参数的顺序。
如果有:

public void test(int a,int b,int c){}

那么如果想引用a和b和c的话,需要这样:

ctMethod.setBody("return $1 + $2 + $3;");

对了还有:静态方法是没有$0的,所以静态方法下$0是不可用的。

(二)$args

$args变量表示所有参数的数组,它是一个Object类型的数组(new Object[]{…}),如果参数中有原始类型的参数,会被转换成对应的包装类型。比如原始数据类型为int,则会被转换成java.lang.Integer,然后存储在args中。

例如我们测试代码如下:

CtMethod ctMethod = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);ctMethod.setModifiers(Modifier.PUBLIC);ctMethod.setBody("System.out.println($args);");

编译后的结果如下:

public void hello1(int var1, double var2) {    System.out.println(new Object[]{new Integer(var1), new Double(var2)});}

(三)$$

变量 是 所 有 参 数 的 缩 写 , 参 数 用 逗 号 分 割 , 例 如 : m ( 是所有参数的缩写,参数用逗号分割,例如:m( 是所有参数的缩写,参数用逗号分割,例如:m()相当于:m($1,$2,$3,…)。

如何使用呢?

我们经常做一些代码优化,把较为复杂的方法内部的逻辑,提炼出来,提炼到一个公共的方法里。

或者说一个方法调用另一个方法,这两个方法传递的参数是一样的时候就用到了。

例如原java:

public Object m1(String name,String age){...省略10000行代码逻辑}

提炼后的:

提炼出来的代码,我们也可以在其他地方使用(所谓的公共的代码)。

public Object m1(String name,String age){    ...省略20行代码逻辑    return m2(name,age);}private Object m2(String name,String age){...}

那么我们就造一个这个场景来说明一下用法吧。

简单点来说,就是一个方法调用另一个方法,传递全参数时。

CtMethod hello2 = new CtMethod(CtClass.voidType, "hello2", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);hello2.setModifiers(Modifier.PUBLIC);hello2.setBody("this.value = $1 + $2;");ctClass.addMethod(hello2);//添加一个hello1的方法CtMethod hello1 = new CtMethod(CtClass.voidType, "hello1", new CtClass[]{CtClass.intType, CtClass.doubleType}, ctClass);hello1.setModifiers(Modifier.PUBLIC);hello1.setBody("this.value = $1 + $2;");hello1.insertAfter("hello2($$);");

可以看到我们hello1调用hello2时,需要传递全部参数。此时即可写成$$方法,当然了也可以写成hello2($1,$2)。

编译后的结果:

public void hello2(int var1, double var2) {    this.value = (int)((double)var1 + var2);}public void hello1(int var1, double var2) {    this.value = (int)((double)var1 + var2);    Object var5 = null;    this.hello2(var1, var2);}

(四)$cflow(…)

$cflow 的全名为:control flow,这是一个只读变量,返回指定方法递归调用的深度。

我们以计算n的斐波拉契数列为例,来演示一下如何使用。

我们正确的递归算法代码如下:

public int f(int n){if(n <= 1){    return n;    }    return f(n-1) + f(n - 2) }

对于上面这段代码,我们可以这样写:

CtMethod f = new CtMethod(CtClass.intType,"f", new CtClass[]{CtClass.intType}, ctClass);f.setBody("{if($1 <= 1){" +          "     return $1;" +          "}" +          "return f($1 - 1) + f( $1 - 2);}");f.setModifiers(Modifier.PUBLIC);

编译后的:

public int f(int var1) {    return var1 <= 1 ? var1 : this.f(var1 - 1) + this.f(var1 - 2);}

那么我们只想在递归到前n次的时候打印log,我们该怎么做呢。

例如,我们下面写的是"$cflow(f) == 1"时

CtMethod f = new CtMethod(CtClass.intType,"f", new CtClass[]{CtClass.intType}, ctClass);f.setBody("{if($1 <= 1){" +          "     return $1;" +          "}" +          "return f($1 - 1) + f( $1 - 2);}");f.setModifiers(Modifier.PUBLIC);//在代码body的前面插入f.useCflow("f");f.insertBefore("if($cflow(f) == 1){" +               "               System.out.println(\"我执行了,此时的n是:\"+$1);" +               "           }");

编译后的代码:

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package com.ssdmbbl.javassist;import javassist.runtime.Cflow;public class Hello {    public static Cflow _cflow$0 = new Cflow();    public int f(int var1) {        if (_cflow$0.value() == 1) {            System.out.println("我执行到来第2次,此时的n是:" + var1);        }        boolean var6 = false;        int var10000;        try {            var6 = true;            _cflow$0.enter();            if (var1 <= 1) {                var10000 = var1;                var6 = false;            } else {                var10000 = this.f(var1 - 1) + this.f(var1 - 2);                var6 = false;            }        } finally {            if (var6) {                boolean var3 = false;                _cflow$0.exit();            }        }        int var8 = var10000;        _cflow$0.exit();        return var8;    }    public Hello() {    }}

通过查看源码,发先关键的一个地方是调用了Cflow对象的enter方法:

public static Cflow _cflow$0 = new Cflow();...        _cflow$0.enter();

点进enter()的内部发现,调用了get().inc()方法:

public class Cflow extends ThreadLocal<Cflow.Depth> {    protected static class Depth {        private int depth;        Depth() { depth = 0; }        int value() { return depth; }        void inc() { ++depth; }        void dec() { --depth; }    }    @Override    protected synchronized Depth initialValue() {        return new Depth();    }        public void enter() { get().inc(); }        public void exit() { get().dec(); }        public int value() { return get().value(); }}

而inc()方法控制着一个全局变量的增加操作。

void inc() { ++depth; }

boolean var6 = false;相当于是一个开关,控制着是否开始和结束。

当参数var1<=1时,即结束

if (var1 <= 1) {    var10000 = var1;    var6 = false;}

我们可以使用反射来验证一下,测试代码如下:

package com.ssdmbbl.javassist;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Test {    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Class<?> aClass = Class.forName("com.ssdmbbl.javassist.Hello");        //初始化这个类        Object obj = aClass.newInstance();        //获取所有的方法        Method[] methods = aClass.getMethods();        //遍历所有的方法        for (Method method : methods) {            //当方法为f的时候,进行调用            if(method.getName().equals("f")){                //调用并传递参数为5,即f(5)                method.invoke(obj,5);            }        }    }}

执行的结果:

为什么是2次呢?原因上面也说了:if(var1 <= 1){…},所以是

我执行了,此时的n是:4
我执行了,此时的n是:3

相关链接

javassist的API接口文档

http://www.javassist.org/html/index.html

javassist的GitHub开源地址

https://github.com/jboss-javassist/javassist

javassist的官网

http://www.javassist.org/

javassist官方的英文教程

http://www.javassist.org/tutorial/tutorial.html

到此,关于“javassist的介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: javassist的介绍

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • javassist的介绍
    这篇文章主要介绍“javassist的介绍”,在日常操作中,相信很多人在javassist的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”javassist的介绍”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-14
  • Python~~简介介绍
    Python (英国发音:/paθn/ 美国发音:/paθɑn/), 是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于...
    99+
    2024-04-02
  • golang的map介绍
    Go语言中map是一种无序的键值对集合,也被称为哈希表或字典,map使用哈希算法实现,可以高效地进行插入、查找和删除操作,需要注意的是,map是一个引用类型,当将map传递给函数或赋值给其他变量时,实际上是传递了map的引用,多个变量共享同...
    99+
    2023-12-18
    go语言 Golang golang的map
  • python介绍
    python是一门优秀的综合语言,python的宗旨是简明,优雅,强大,在人工智能,云计算,金融分析,大数据开发,web开发,自动化运维,测试等方向应用广泛,已是全球第4大最流行的语言目前python主要应用领域:  web开发-...
    99+
    2023-01-30
    python
  • 1. 介绍
    在本教程中,我们将学习如何在亚马逊 AWS 上搭建 Linux 服务器。AWS 是一家全球领先的云计算服务提供商,提供了各种各样的云计算服务,包括虚拟机、存储、数据库、网络等等。AWS 的 EC2 服务是一种弹性计算云服务,可以轻松地创建和...
    99+
    2023-10-27
  • 介绍PHP
    PHP是一种流行的服务器端编程语言,用于开发Web应用程序。它是一种开源的编程语言,具有易学易用的语法和强大的功能。PHP支持在服务器上运行的动态网页和Web应用程序的快速开发。 PHP可以与HTM...
    99+
    2023-09-14
    php 开发语言 PHP phpstorm 学习 学习工具
  • springCloud介绍
    springCloud介绍SOA:更注重于相同功能的重用,来构建一条企业功能的主线,其他的功能在这条主线上进行开发和扩展。有点类似于EJB的功能。微服务:将整个功能拆分成若干个服务,各个服务独立部署,此时的重点是业务拆分的粒度。 ...
    99+
    2023-06-02
  • OAuth2.0介绍
    概述OAuth 2.0 授权框架能够是第三方应用获取应用被保护的服务资源,它是一种授权互联网标准,由IETF(Internet Engineering Task Force)管理发布。本文主要参考材料为 RFC 6749 初步理解接下来以一...
    99+
    2023-06-02
  • Kafka 介绍
    一、基本概念 1.1 什么是 kafka Kafka 它最初由 LinkedIn 公司开发,之后成为 Apache 项目的一部分。Kafka 是一个分布式消息中间件, 支持分区的、多副本的、多订阅者的、基于 zookeeper 协调的分布式...
    99+
    2023-08-30
    kafka 分布式 java
  • SpringMvc介绍。
    目录 1、SpringMvc概述 1、基本介绍 2、工作流程  3、bean加载控制  二、请求 1、请求映射路径 2、请求方式 3、请求参数 4、请求参数(传递json数据) 5、日期类型参数传递 三、响应 四、REST风格 1、REST...
    99+
    2023-09-01
    java SpringMVC
  • document.getElementById介绍
    document.getElementById()是一个JavaScript方法,用于通过给定的id值来获取HTML文档中具有该id的元素。语法:document.getElementById(id)参数:id - 表示要获取的元素的i...
    99+
    2023-08-11
    介绍
  • ANYDATA介绍
    ANYDATA特殊列,属于Oracle内建列,对于Oracle数据库,每一个值都是一种数据类型。当用户创建表或聚簇时,需要为每一个列指定对应的数据类型。即使是创建存储过程或函数的时,一样需要为参数指定相应的...
    99+
    2024-04-02
  • Python函数介绍:delattr函数的介绍及示例
    Python函数介绍:delattr函数的介绍及示例Python作为一门高级的编程语言,拥有丰富的内置函数库,提供了许多方便快捷的函数来进行各种操作。其中之一就是delattr函数。本文将详细介绍delattr函数的作用以及用法,并附上具体...
    99+
    2023-11-03
    Python 介绍 delattr函数
  • Python函数介绍:str函数的介绍及示例
    Python函数介绍:str函数的介绍及示例Python是一种简单易学的编程语言,拥有丰富的内置函数来帮助开发者处理数据。其中一个常用的内置函数是str函数。str函数主要用于将其他数据类型转换为字符串类型。str函数的用法如下:str(o...
    99+
    2023-11-03
    Python函数 str 的介绍及示例
  • Python函数介绍:reversed函数的介绍及示例
    Python函数介绍:reversed函数的介绍及示例在Python中,reversed()函数可以将一个序列类型的对象进行反转排列,返回一个包含了反转后元素的迭代器。在本文中,我们将介绍reversed()函数的具体用法,并提供一些代码示...
    99+
    2023-11-04
    Python函数/函数介绍/reversed函数/示例
  • Python函数介绍:ord函数的介绍及示例
    Python函数介绍:ord函数的介绍及示例在Python编程中,ord()函数是一个很有用的函数,它用于返回给定字符的Unicode数值,即该字符在Unicode表中的位置。本篇文章将介绍ord()函数的用法、语法以及...
    99+
    2023-11-04
    Python 函数 编程关键词: ord示例
  • Python函数介绍:range函数的介绍及示例
    Python函数介绍:range函数的介绍及示例Python是一种广泛应用于各种领域的高级编程语言,它具有简单易学的特点,并且有着丰富的内置函数库。其中,range函数是Python中常用的一个内置函数之一。本文将详细介绍range函数的功...
    99+
    2023-11-04
    示例 Python函数 range函数
  • Python函数介绍:input函数的介绍及示例
    Python函数介绍:input函数的介绍及示例随着Python语言的快速发展,越来越多的人开始学习和使用Python进行编程。在Python中,函数是一种非常重要的概念,它可以帮助我们将一段代码逻辑封装起来,使得代码更加清晰和易于维护。其...
    99+
    2023-11-04
    示例 Python函数 input函数
  • Python函数介绍:max函数的介绍及示例
    Python函数介绍:max函数的介绍及示例函数在Python编程中是非常重要的概念。Python内置了许多有用的函数,其中一个是max函数。本文将介绍max函数的用法以及示例代码,帮助读者更好地理解和运用。max函数的作用是返回给定参数的...
    99+
    2023-11-03
    Python 函数 max函数
  • Python函数介绍:exec函数的介绍及示例
    Python函数介绍:exec函数的介绍及示例引言:在Python中,exec是一种内置函数,它用于执行存储在字符串或文件中的Python代码。exec函数提供了一种动态执行代码的方式,使得程序可以在运行时根据需要生成、修改和执行代码。本文...
    99+
    2023-11-03
    示例 介绍 exec函数
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作