语法进阶

一、变量
01-变量的引用
1.1 引用的概念
1.变量和数据是分开存储的
2.数据保存在内存的一个位置,变量存储着数据在内存中的地址
3.变量中纪录数据的地址就叫做引用
# 使用id()函数可以查看变量中保存数据所在的地址
注意:如果变量已被定义,当给一个变量赋值的时候,本质上就是修改了数据的引用
eg: 定义a = 1,id(1) 得出1的内存地址为0032
    id(a)得出a的内存地址也为0032
    定义b = a,id(b)得出b的地址也为0032
    修改引用为a = 2,id(a)与id(2)得出内存地址都为0064,而id(b)依旧为0032
所以我的理解是,原本的数据在内存中有一个固定的位置,而变量就是一个标签,上面写着要引用数据的地址
变量 a 上面写着1的内存地址0032,变量 b 因为赋值 a 所以也是0032,而之后 a 赋值2,于是 a 上面写着2的内存地址0064,b则因为没有操作依然为0032
1.2 函数的参数和返回值的传递
1.调用函数的,本质上传递的是实参保存数据的地址,而不是实参保存的数据
2.函数的返回值,返回的是数据的地址,而不是数据本身
3.如果函数有返回值,但是没有定义变量接收,程序不会报错,但是无法获得返回结果
eg:def test(num):
    print("%d的地址是%d" % (num, id(num)))
    result = "hello"
    print("%s的地址是%d" % (result, id(result)))
    return result
 
 
    a = 10
    print("a的地址是%d" % id(a))
    r = test(a)
    print("%s的地址是%d" % (r, id(r)))
 
02-可变和不可变类型
不可变类型:内存中数据不允许被修改
    数字类型:int,bool,float,complex,long(2.x)
    字符串:str
    元组:tuple
可变类型:内存中的数据可以被修改,即分配空间之后,仍然可以使用方法来修改类型中的内容,而不会改变内存地址
    列表、字典
eg:定义一个列表变量 a = [1, 2, 3],id(a)为70272,我们在其中利用append方法追加数据,变成 a = [1, 2, 3, 999],id(a)为70272 
   即使是clear方法清空后,id(a)仍为70272,但是如果赋值 a = [],id(a)为64352,发生改变。字典同理
# 如果给一个可变类型的变量,赋值一个新的数据,则变量不再引用之前的数据,改为引用新的数据
注意:字典的 key 只能使用不可变类型的数据,value 可以是任意类型的数据
哈希(hash)
python中的内置函数hash(o),用于接收一个 不可变类型 的数据作为 参数,而 返回 结果是一个 整数
哈希是一种 算法,其作用就是提取数据的 特征码(指纹),即相同的内容 得到 相同的结果,不同的内容 得到 不同的结果
在Python中,设置字典的 键值对 时,会首先对 key 进行 hash,保证内存中保存字典的数据得到优化,方便 后续 对字典的操作:增、删、改、查
 
03-局部变量和全局变量
局部变量 是在 函数内部 定义的变量,只能在函数内部使用
全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量
3-1 局部变量
1.局部变量 是在 函数内部 定义的变量,只能在函数内部使用
2.函数执行结束后,函数内部的局部变量,会被系统回收
3.不同的函数,可以定义相同的名字的局部变量,但是 彼此之间 不会产生影响
作用:临时保存函数内部需要的数据
生命周期:变量从被创建到被系统回收的过程
1.局部变量 在 函数执行时 才会被创建
2.函数执行结束后 局部变量 被系统回收
3.局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据
3-2 全局变量
1) 函数不能直接修改 全局变量的引用,但所有的函数内部都可以使用这个变量
# 若在函数内部定义的变量与全局变量同名,只认为是局部变量,不会修改全局变量
2) 在函数内部修改全局变量的值,需要使用 global 关键字进行声明
# global关键字会告诉解释器后面的变量是全局变量,再使用赋值语句就不会创建局部变量
3) 全局变量定义的位置
# 为了保证所有的函数都能够正确使用到全局变量,应该将全局变量定义在其他函数的上方,否则即使编写时不会出错,编译函数时也会报错
4) 全局变量命名的建议
为了避免局部变量和全局变量出现混淆,在定义全局变量时,可以适当添加前缀,如 g_ 或 gl_ 等
注意:
函数执行变量顺序:局部变量 ==> 全局变量 ==> 报错
代码顺序:shebang ==> import模块 ==> 全局变量 ==> 函数定义 ==> 执行代码
 
二、函数
01-函数的参数与返回值
外界通过参数将数据传递到函数内部进行处理,而函数通过返回值向外界报告函数结果,以此可分为四种类型:无参数,无返回值;无参数,有返回值;有参数,无返回值;有参数,有返回值
1.1 无参数,无返回值
 
 
 
 
02-函数的返回值(进阶)
要返回多个结果时,可以用元组来返回多个数据
def measure():
    print("开始测量...")
    temp = 37
    wetness = 50
    print("结束测量...")
    return temp, wetness
返回类型是元组时,小括号可以省略
 
 
result = measure()
在python中可以将一个元组通过赋值语句同时赋给多个变量,要求变量数量和赋值顺序必须和元组一致
gl_temp, gl_wetness = result
拓展1:交换数字顺序
a = 6, b = 100
1.使用其他变量
c = a
a = b
b = c
2.不使用其他变量
a = a + b 
b = a - b
a = a - b
3.python专属,元组
a, b = b, a
 
03-函数的参数(进阶)
3-1 可变参数和不可变参数
1.只要针对参数使用赋值语句,会在函数内部修改局部变量的引用,不会影响到外部变量的引用
def demo(num, num_list):
    num = 100
    num_list = [1, 2, 3]
    print("在内部是以下结果:")
    print(num)
    print(num_list)
 
 
gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num, gl_list)
print("在外部是以下结果")
print(gl_num, gl_list)
2.如果传递的可变参数,在函数内部使用方法进行修改,同样会影响到外部数据
def mutable(num_list):
    num_list.extend([4, 5])
    print("在函数内部是:")
    print(num_list)
 
 
gl_num_list = [1, 2, 3]
mutable(gl_num_list)
print(gl_num_list)
拓展2:+=在列表中的操作
在python中,对列表的+=操作本质上是执行列表的 extend 方法,没有修改引用,会影响外部数据
而先+后=分开操作,则会修改引用,不改变外部数据
def demo(num, num_list):
    num += num
    num_list += num_list             # 外部为[1, 2, 3, 1, 2, 3]
    num_list = num_list + num_list   # 外部为[1, 2, 3]
    print("函数内部的代码是:")
    print(num)
    print(num_list)
    print("函数结束")
 
 
gl_num = 1
gl_list = [1, 2, 3]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)
3-2 缺省参数
介绍
定义函数时,给某个参数指定一个默认值,具有默认属性的参数就叫做缺省参数
在调用函数时,如果没有传入缺省参数的值,则在函数内部定义函数时指定的参数默认值
函数的缺省参数,将常见的值设置为参数的缺省值,从而 简化函数的调用
gl_num_list = [6, 3, 9]
 
# 默认就是升序排序,因为这种应用需求更多
gl_num_list.sort()
 
# 只有当需要降序排序时,才需要传递 `reverse` 参数,在这里reverse就是缺省参数,默认缺省值为False,降序时才传入True
gl_num_list.sort(reverse=True)
指定函数的缺省参数
在参数后使用赋值语句,可以指定参数的缺省值
def print_info(name, gender=True):
    gender_text = "男生"
    if not gender:
        gender_text = "女生"
    print("%s是%s" % (name, gender_text))
# 注意
1. 缺省参数,需要使用最常见的值作为默认值
2. 如果一个参数的值不能确定,则不应该设置默认值,具体的数值在调用函数时,由外界传递
缺省参数的注意事项
(1) 带有默认值的缺省参数必须定义在参数列表末尾
(2) 在调用具有多个缺省参数的函数时,需要指定参数名
def print_info(name, title="", gender=True):
    gender_text = "男生"
    if not gender:
        gender_text = "女生"
    print("%s[%s]是%s" % (name, title, gender_text))
 
 
print_info("小明")
print_info("小明", title="班长")
print_info("小美", gender=False)
3-3 多值参数(了解)
1.定义支持多值的参数的函数
有时需要一个函数能处理的参数是不确定的,则需要使用多值参数
参数前一个 * 可以接收元组,常命名为 *args   # arguments缩写,意为变量
参数前两个 * 可以接收字典,常命名为 **kwargs   # keywordarguments的缩写,记忆键值对参数
eg:def demo(num, *args, **kwargs):
        print(num)
        print(args)
        print(kwargs)
 
 
    demo(1, 2, 3, 4, 5, name="小明", age=18)
2.案例演练——计算任意多数字的和
将所有传递的数字累加,并返回累加结果
def sum_numbers(*args):
    num = 0
    for i in args:
        num += i
    return num
 
 
print(sum_numbers(1, 2, 3))
3-4 元组和字典的拆包(了解)
在调用带有多值参数的函数时,为了让元组变量直接传递给args,字典变量直接传递给kwargs,则要使用拆包,否则只能一个一个传递元素
即在元组变量前添加 * ,在字典变量前添加 **
eg:def demo(*args, **kwargs):
        print(args)
        print(kwargs)
 
 
    gl_num = (1, 2, 3)
    gl_dict = {"name": "小明", "age": 18}
    demo(*gl_num, **gl_dict)
如果不添加*和**,则字典变量同样会传入元组中
 
04-函数的递归
1.一个函数自己调用自己称为递归,递归需要一个出口,否则会陷入死循环
eg:def sum_numbers(num):
        print(num)
 
        if num == 1:
            return
    sum_numbers(num - 1)
 
 
    sum_numbers(3)
2.案例——计算数字累加
eg:def demo(num):
        if num == 1:
            return 1
        temp = demo(num - 1)
        return num + temp
 
 
    print(demo(100))
# 这里demo(100) = 100 + demo(99),demo(99) = 99 + demo(98),以此类推,最后demo(1) = 1,随后又依次返回,相当于 100 + 99 + 98…… = 5050
在处理不确定的循环条件(如:遍历整个文件目录的结构),递归则非常有用
 
 
 
posted @ 2021-09-02 23:35  icui4cu  阅读(56)  评论(0编辑  收藏  举报