java 和 python中参数在函数体中的改变对参数本身的影响 您所在的位置:网站首页 python中可变参数在继承函数中的作用 java 和 python中参数在函数体中的改变对参数本身的影响

java 和 python中参数在函数体中的改变对参数本身的影响

2024-07-06 19:34| 来源: 网络整理| 查看: 265

最近几天在看python , 看到函数这一段的时候 , 突然发现一个问题 , 字符串在函数体中重新赋值 , 不会对函数体外 , 该字符串本身的值产生影响 . 例如 :

def changestr (str): str = "inside" print("这是function中 , 值为:",str) mystr = "outside" changestr(mystr) print("这是函数外边 , 值为:",mystr)

运行结果为 :

这是function中 , 值为: inside 这是函数外边 , 值为: outside

考虑到字符串不可变的特性 (python的六种标准类型 , 其中有三种是不可变的类型 , 即 : Number ,String , Tuple) , 我分别测试了Number和Tuple , 发现同以上结果是一样的 , 因为这三种类型只能通过重新赋值来改变对象的值 , 另外三种类型(List , Set , Dictionary) 是可以改变内部的元素 , 于是又测试了这三种seq类型 , 第一次测试如下 :

def change(mylist): mylist.append([1,2,3,4]) mylist = ["aa",21] print(mylist) change(mylist) print(mylist)

结果如下:

['aa', 21] ['aa', 21, [1, 2, 3, 4]]

发现在函数体中的修改 , 对对象本身的值发生了改变 , 在函数之外 , 该列表的内容依然发生了改变 , 这是事先就能猜测到的结果 , 因为python中的参数 , 传入的是变量引用的副本 , 它与变量指向同一个值. 鉴于前三种类型的参数是直接重新赋值的 , 于是继续下一步测试 :

def change2(list): list = [1,2,3,4] mylist = ["aa",21] print(mylist) change2(mylist) print(mylist)

结果如下:

['aa', 21] ['aa', 21]

有些意外 , 出现了和三种不可变类型参数一样的情况 , 在函数体中的重新赋值 , 没有对外部变量的值产生影响 , 不过仔细一想 , 却又在情理之中 . 我对python还不够熟悉 , 但是从近两天的学习中发现 , 其存储模型与java相似 , 即变量中存储的是引用 , 是指向真正内容的内存地址(当然 ,java中的八大基本数据类型 , 变量名和值都是存储在堆栈中的 ) , 对变量重新赋值 , 相当于修改了变量副本存储的内存地址 , 而这时的变量已经和函数体外的变量不是同一个了, 在函数体之外的变量 , 依旧存储的是原本的内存地址 , 其值自然没有发生改变 .

简单来说 : - 函数体传入的参数 , 为函数体外变量引用的副本 . - 在函数体中改变变量指向的堆中的值 , 对函数外变量有效. - 在函数体中改变变量的引用 , 对函数外变量无效

大致图如下 :(红色线代表重新赋值动作) 这里写图片描述

当然 , 测试时不能少的 , 我在java中也做了相应的测试 , 结果与猜想一致 , 测试代码如下:

import java.util.ArrayList; import java.util.List; /** * Created by dell on 2017/3/27. * * @author dell * @date 2017/03/27 */ public class DemoScope { public static void main(String[] args) { { String str1 = "aaa"; testStr(str1); System.out.println("方法外:"+str1); } { int a = 5; testNumber(a); System.out.println("方法外:"+a); } { List list = new ArrayList(); list.add("a"); list.add("b"); testList(list); System.out.println("方法外:"+list.toString()); } { char a = 'a'; testChar(a); System.out.println("方法外:"+a); } { List list = new ArrayList(); list.add("a"); list.add("b"); testList2(list); System.out.println("方法外:"+list.toString()); } { boolean fl = true; testBoolean(fl); System.out.println("方法外:"+fl); } { Tree tree = new Tree(50 , "银杏"); testObject(tree); System.out.println("方法外:"+tree.toString()); } { Tree tree = new Tree(50 , "银杏"); testObject2(tree); System.out.println("方法外:"+tree.toString()); } } static class Tree{ int height; String type; Tree(int height, String type){ this.height = height; this.type = type; } @Override public String toString() { return "Tree{" + "height=" + height + ", type='" + type + '\'' + '}'; } } private static void testStr(String str){ System.out.println("1.这是function中,str="+str); str = "新的值"; System.out.println("2.这是function中,str="+str); } private static void testNumber(int num ){ System.out.println("重新赋值前:"+num); num = 10; System.out.println("重新赋值后:"+num); } private static void testList(List list){ System.out.println("重新赋值前:"+ list.toString()); list.set(0, "A"); } private static void testList2(List list){ System.out.println("重新赋值前:"+ list.toString()); list = new ArrayList(); list.add("A"); System.out.println("重新赋值后:"+list.toString()); } private static void testChar(char a){ System.out.println("重新赋值前:"+ a); a = 'A'; System.out.println("重新赋值后:"+a); } private static void testBoolean(boolean flag){ System.out.println("重新赋值前:"+ flag); flag = false; System.out.println("重新赋值后:"+flag); } private static void testObject(Tree obj){ System.out.println("重新赋值前:"+obj.toString()); obj.height = 100 ; System.out.println("重新赋值后:"+obj.toString()); } private static void testObject2(Tree obj){ System.out.println("重新赋值前:"+obj.toString()); obj = new Tree(100 , "琵琶") ; System.out.println("重新赋值后:"+obj.toString()); } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有