• 编程语言在函数中的参数传递


    1、Python

    Python 的参数传递是赋值传递 (pass by assignment),或者叫作对象的引用传递(pass by object reference)。Python 里所有的数据类型都是对象,所以参数传递时,只是让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递一说。 ----来自互联网

    总结一下:就是在使用函数时,把实参赋给函数的形参,即形参=实参,函数的形参和实参指向同一对象。

    那么在函数中参数的变化只受其本身对象的性质影响了。

    Python中的数据类型有可变不可变,string这种不可变类型被修改后相当于重新赋值,句柄指向新的对象。

    传递string(不可变)

    def fun(a:str):
        print("2  ",id(a))
        a+="b"
        print("3   ",id(a))
    
    
    a="aa"
    print(id(a))
    
    fun(a)
    
    print(a)
    
    1753958904624 
    2   1753958904624    #传递前后是一个对象
    3    1753960317104   #string是不可变类型,修改了就是另一个对象
    aa 
    

    传递list(可变类型)

    def fun(a:list):
        print("2  ",id(a))
        a.append("1")
        print("3   ",id(a))
    
    
    a=['a','b']
    print(id(a))
    
    fun(a)
    
    print(a)
    
    2017284788416         #传递前后是一个对象
    2   2017284788416
    3    2017284788416   #list是可变类型,即使修改了,对象也没变
    ['a', 'b', '1']      
    

    2、JS

    JS和Python一样,也是直接把实参给了形参。

    string(不可变的值类型)

    function f(str) {
        console.log("内部:  ",str==="Hello World");
        str += "!";
        return str;
    }
    
    var str="Hello World";
    console.log("外部1: ",str==="Hello World");
    
    console.log("外部2:   ",str===f(str));
    
    
    外部1:  true
    内部:   true
    外部2:    false
    

    Array(引用类型)

    function f(arr2) {
       console.log(arr===arr2);
       arr2.push("!");
       console.log(arr===arr2);
    }
    
    var arr=[];
    arr.push("hello");
    arr.push("world");
    
    f(arr);
    
    console.log("数组: ",arr);
    
    true
    true
    数组:  [ 'hello', 'world', '!' ]
    

    3、Java

    Java的数据类型分为两种:基本类型和引用类型。

    引用类型分为下面几种:类类型(class,interface,enum,annotation)和数组类型 。

    Java也是赋值传递。

    int(基本类型)

    基本类型不需要new,赋值直接使用,修改了句柄就指向新的位置了。

    public class Args_ref {
    
    
        public static int f(int x){
            x+=1;
            return x;
        }
    
    
        
        public static void main(String[] args) {
            int x=10;
            int y=f(x);
            System.out.printf("x=%d, y=%d, x==y?%b",x,y,x==y);
    
        }
        
    }
    x=10, y=11, x==y?false
    

    数组(对象)

    数组是对象。

     	public static int[] ff(int[] x){
            System.out.println("ff hashCode: "+x.hashCode());
            if(x!=null){
                x[0]=100;    //修改一下x中的元素,也就是对原数组进行修改
            }
            return x;
        }
    
    	public static void main(String[] args) {
    
            int[] s={1,2,3,4};
        
            System.out.println("main hashCode: "+s.hashCode());
    
            System.out.println("main ff hashCode: "+ff(s).hashCode());
    
            for(int i:s){
                System.out.println(i);
            }
    }
    main hashCode: 366712642  //数组传递前后,修改前后都没有变化
    ff hashCode: 366712642  
    main ff hashCode: 366712642 
    100                
    2
    3
    4
    

    String(对象、不可变)

    JavaString是对象类型,但也是不可变的,修改也是重新赋值,句柄指向新的字面量。

    public static String ss(String s){
            System.out.println("ss1: "+s.hashCode());
            s+="nice";
            System.out.println("ss2: "+s.hashCode());
            return s;
    
        }
    
    
        public static void main(String[] args) {
    
            String s="Hello Java";
    
            System.out.println("main1: "+s.hashCode());
    
            
            System.out.println("main2: "+ss(s).hashCode());
            System.out.println(s);
    
        }
    main1: 387417328   //传递前后没有变化
    ss1: 387417328
    ss2: 85926989       //修改后hashCode不一样了
    main2: 85926989
    Hello Java
    

    4、GO

    Go语言和C一样,是传值的,就是把实参拷贝一份给形参,不管你是值类型还是引用类型。

    Go语言不同于PythonJava,因为它提供了指针,可以通过传递指针,达到上面那些语言的功能。

    Go中就通过指针模拟面向对象的this关键字

    String(值类型)

    Go中的String是值类型,

    //值类型是拷贝
    func f(data string){
    	fmt.Printf("data:  %p
    ",&data)
    	data+="hi"
    }
    
    func main()  {
    	var s string="ok"
    	fmt.Printf("s    :  %p
    ",&s)
    	f(s)
    
    	fmt.Println("s    :  "+s)
    }
    
    
    s    :  0xc0000421f0  
    data:  0xc000042200  //地址不一样,拷贝了一份新的
    s    :  ok          
    

    []string切片

    func a(data []string)  {
    
    	fmt.Printf("data1:  %p
    ",&data)
    	adata:=append(data,"!")      //生成了新切片,从append函数也可以看出是拷贝了,否则没必要返回一个新切片
        							//func append(slice []Type, elems ...Type) []Type
    	fmt.Printf("data2:  %p,%s
    ",&data,data)
    	fmt.Printf("adata:  %p,%s
    ",&adata,adata)
    
    }
    
    func main()  {
    	var scl []string=[]string{"Hi ","My ","Friend "}
    	fmt.Printf("scl:  %p
    ",&scl)
    	a(scl)  //把实参拷贝一份给形参,互不影响
    
    	fmt.Println(scl) 
    
    }
    
    scl:  0xc000004480
    data1:  0xc0000044c0     //拷贝到新的内存里      
    data2:  0xc0000044c0,[Hi  My  Friend ]
    adata:  0xc0000044e0,[Hi  My  Friend  !] 
    [Hi  My  Friend ]    
    

    []string(切片指针)

    把地址作值传进去,这时形参修改也会影响到实参了。

    Go中模拟面向对象时,用这个特性模拟this关键字。

    func a(data *[]string)  { 
    
    	fmt.Printf("data1:  %p
    ",data)
    	if len(*data)>=0{
    		(*data)[0]="nono"   //这里修改就会影响到外界
    	}
    
    }
    
    func main()  {
    	var scl *[]string=&[]string{"Hi ","My ","Friend "}
    	fmt.Printf("scl:  %p
    ",scl)
    	a(scl)
    
    	fmt.Println(scl)
    
    }
    
    
    scl:  0xc000068440     //地址相同
    data1:  0xc000068440
    &[nono My  Friend ]    //函数影响到了外界
    
  • 相关阅读:
    Handler Looper MessageQueue HandlerThread
    Android屏幕适配
    android开发环境搭建
    Task
    C#语法糖
    Window Phone 开发学习
    Android ListView使用
    网络分析工具
    VS2005在水晶报表中如何显示数据库中保存的是图片路径的图片
    在SQL Server中获取Excel文件中所有Sheet工作表的名称
  • 原文地址:https://www.cnblogs.com/cgl-dong/p/14060762.html
Copyright © 2020-2023  润新知