揭秘python函数:编程艺术的核心力量(2) |
您所在的位置:网站首页 › python中的可变类型有 › 揭秘python函数:编程艺术的核心力量(2) |
文章目录 前言变量的作用域局部变量全局变量 函数的返回值函数的参数1.位置参数2.关键字参数3.缺省参数4.不定长参数 拆包交换变量的值引用可变数据类型和不可变数据类型 前言 前面我们学习了 python 函数的基本使用,那么今天我将继续带大家深入了解 python 函数的更多操作。 变量的作用域变量分为局部变量和全局变量,两种变量的作用域不同。 局部变量是指定义在函数体内部的变量,只在函数体的内部生效。全局变量是指在函数的内部和外部都能生效的变量。 局部变量 def test1(): a = 100 # 这里a属于局部变量 print(a)当出了函数体之后,局部变量 a 会被销毁。 def test1(): a = 100 print(a) print(a) 全局变量 a = 100 def test1(): print(f'在函数内部使用全局变量{a}') test1() print(f'在函数外部使用全局变量{a}')在函数体外部修改全部变量,全局变量会被修改,那么如果我们在函数体内部修改全局变量会怎样呢? a = 100 def test1(): a = 200 print(a) test1() print(a)可以发现:在函数体内部修改全局变量只是修改的是函数体内部的变量,实际上全局变量并未改变,也就是说函数体内部修改的其实还是局部变量,那么如何在函数体内部修改全局变量呢? global 变量 声明此变量为全局变量,然后对全局变量进行修改。 a = 100 def test1(): global a a = 200 print(a) test1() print(a) 函数的返回值前面我们说过的函数的返回值都是一个数据,那么如果我们想要返回多个数据该怎么办呢? 使用逗号 , 来分割多个数据,但是这多个数据最总会被合并为一个元组返回。以列表、元组、字典、集合的形式返回多个数据。以逗号 , 形式返回 def test1(): return 1,2,3 print(test1())以列表形式返回 def test1(): return [1,2,3] print(test1())以元组的形式返回 def test1(): return (1,2,3) print(test1())以集合的形式返回 def test1(): return {1,1,2,3} print(test1())对此,我们可以根据需要来选择以哪种形式返回数据 函数的参数函数传参的方式有四种: 位置传参关键字传参缺省传参不定长传参 1.位置参数调用函数的时候,根据函数定义的参数的位置顺序和数量进行传参。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zhangsan',18,'man')当传入的参数的数量与函数定义时的参数数量不同时,会报错。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zhangsan',18)传参时,顺序与定义时参数顺序不同,可以运行通过,但代码无意义。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1(18,'zhangsan','man') 2.关键字参数通过“键 = 值” 的形式加以制定,可以让函数更加清晰、容易使用,同时也不需要遵守传参的顺序。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1(gender = 'man',name = 'zhangsan',age = 18)使用关键字传参时,可以有位置参数,但是位置参数必须在关键字参数之前。位置参数必须要和函数定义时的参数的位置对应。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zhangsan',gender = 'man',age = 18)当位置参数与函数定义时参数不对应时,会报错。 def test1(name,age,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('man',name = 'zhangsan',age = 18) 3.缺省参数缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。 在函数定义的时候,我们可以为参数指定默认值,这样当我们不为这个参数传入值的时候,这个参数就会使用默认值,如果我们为这个参数传入数据,这个参数也会变成我们传入的数据。 def test1(name,age,gender = 'man'): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zhangsan',18) def test1(name,age,gender = 'man'): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zhangsan',18,'woman') test1(age = 19,name = 'lisi')一旦你开始在函数定义中使用默认参数,那么所有在该默认参数后面的参数都必须是默认参数。换言之,所有无默认值的参数(位置参数)都必须出现在带有默认值的参数(关键字参数)前面。 def test1(name,age = 18,gender): print(f'姓名:{name} 年龄:{age} 性别:{gender}') test1('zahngsan','man') 4.不定长参数不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。 1)包裹位置传递 def 函数名(*args): 这个 * 不可省略,是包裹位置传递的标志,后面的args可以更换,但是实际生活中建议使用args,因为 python 底层也是使用的args。 使用位置包裹传递的参数会被合并成一个元组传入函数中。 def test1(*args): print(args) test1() test1(1) test1(1,2)2)包裹关键字传递 def 函数名(**args): 传入参数时,以 “键 = 值” 的形式传递。并且以包裹关键字传递的形式传参的时候,这些参数会被合并为一个字典传入参数中。 def test1(**args): print(args) test1(name = 'zhangsan',age = 18,gender = 'man')上面的包裹位置传递和包裹关键字传递都是一个组包的过程,我们也可以进行拆包过程。 拆包1)元组拆包 def test1(): return 100,200 a,b = test1() print(a) print(b)这里注意:拆包过程中,接收的变量的数量要与元组中的元素个数相同。 2)字典拆包 字典拆包,变量中存储的是字典的 key ,我们可以根据拆包获得的 key ,来操作 value 值 dict1 = {'name':'zhangsan','age':18,'gender':'man'} a,b,c = dict1 print(a) print(b) print(c) print(dict1[a]) print(dict1[b]) print(dict1[c]) 交换变量的值在 python 中,常见的交换两个变量的值有两种方法。 采用中间值的方法。a,b = b,a采用中间值的方法 a = 100 b = 200 c = 0 c = a a = b b = c print(a) print(b)采用中间值c来存储其中一个数据,防止在交换过程中被替换掉。 b,a = a,b a = 100 b = 200 a,b = b,a print(a) print(b) 引用在Python中,引用对于对象的处理有着举足轻重的作用。 对象赋值:在Python中,当你创建一个对象并给它赋一个变量名时,这个变量名只是指向那个对象的引用,而并非对象本身。例如,当你创建一个列表a = [1, 2, 3],a实际上是对列表[1, 2, 3]的引用。 函数参数传递:Python使用引用传递(pass-by-reference)方式向函数传递参数。所以,如果你在函数内部改变了传入对象的值,那么在函数外面的那个对象的值也会随之改变。需要注意的是,对于不可变类型(如整数、字符串、元组),由于其不可变的特性,函数内部对其进行的操作不会影响外部实际对象。 共享和复制:Python中对象的赋值,实际上是在创建一个新的引用,而不是创建一个全新的对象。例如,当你写b = a,你实际上只是创建了一个新的引用b,并没有创建一个新的列表。这就是所谓的浅复制(shallow copy)。如果你要创建一个对象的深度副本(deep copy),即一个全新的对象,可以使用copy模块的deepcopy函数。尤其是对于复杂的数据结构如列表、字典或者自定义的对象,理解Python中的引用模型非常重要。 这里第三点我们先做了解,后面再给大家讲解。 在了解引用之前,我们需要了解在 python 中,哪些数据类型是可变数据类型,哪些类型是不可变类型。 可变数据类型和不可变数据类型可变类型 列表字典集合不可变类型 整型浮点型字符串元组我们用一段代码来了解什么是引用。 id() 函数可以知道引用所引用的内容的地址。 a = 1 b = a print(id(a)) print(id(b))
a 引用的是 1 ,b 引用 a 引用的引用。 a = 1 b = a a = 2 print(a) print(b) print(id(a)) print(id(b))
这里因为 int 类型是不可变类型,所以当 a 的值由1变为2的时候,会另外开辟一个空间存储2,然后引用 a 指向该地址。 当引用指向的类型是可变类型时,会不会发生这种情况呢? a = [1,2,3] b = a a.append(4) print(a) print(b) print(id(a)) print(id(b))我们看到,当引用的是可变数据类型时,当改变数据内容时,引用的地址不会改变。 我们可以将引用作为参数传递参数。 def test1(a): print(id(a)) a = 2 print(id(a)) a = 1 print(id(a)) test1(a) print(id(a)) print(a)在这里,函数内部的引用 a 其实是一个临时变量,并且 a 引用的数据类型是 int 型,是不可变类型,当改变临时变量 a 的值时,会额外创建一个值为 2 的 int 类型的内存,然后临时变量 a 指向该内存,当出了函数时,临时变量 a 会被销毁,打印的 a 的值还是之前的值。 当传入的引用引用的数据类型是可变类型时 def test1(a): print(id(a)) a[0] = 4 print(id(a)) a = [1,2,3] print(id(a)) test1(a) print(id(a)) print(a) |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |