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

18 篇文章 4 订阅
17 篇文章 0 订阅

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));


外部1true
内部:   true
外部2false

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语言不同于Python\Java,因为它提供了指针,可以通过传递指针,达到上面那些语言的功能。

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

String(值类型)

Go中的String是值类型,

//值类型是拷贝
func f(data string){
	fmt.Printf("data:  %p\n",&data)
	data+="hi"
}

func main()  {
	var s string="ok"
	fmt.Printf("s    :  %p\n",&s)
	f(s)

	fmt.Println("s    :  "+s)
}


s    :  0xc0000421f0  
data:  0xc000042200  //地址不一样,拷贝了一份新的
s    :  ok          

[]string切片

func a(data []string)  {

	fmt.Printf("data1:  %p\n",&data)
	adata:=append(data,"!")      //生成了新切片,从append函数也可以看出是拷贝了,否则没必要返回一个新切片
    							//func append(slice []Type, elems ...Type) []Type
	fmt.Printf("data2:  %p,%s\n",&data,data)
	fmt.Printf("adata:  %p,%s\n",&adata,adata)

}

func main()  {
	var scl []string=[]string{"Hi ","My ","Friend "}
	fmt.Printf("scl:  %p\n",&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\n",data)
	if len(*data)>=0{
		(*data)[0]="nono"   //这里修改就会影响到外界
	}

}

func main()  {
	var scl *[]string=&[]string{"Hi ","My ","Friend "}
	fmt.Printf("scl:  %p\n",scl)
	a(scl)

	fmt.Println(scl)

}


scl:  0xc000068440     //地址相同
data1:  0xc000068440
&[nono My  Friend ]    //函数影响到了外界
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值