• python全栈开发中级班全程笔记(第二模块)第 二 部分:函数基础(重点)


    python学习笔记第二模块         第二部分    :    函数(重点)

    一、函数的作用、定义 以及语法

    1、函数的作用

    2、函数的语法和定义

    函数:来源于数学,但是在编程中,函数这个概念与数学中大不相同,在不同的编程语言里,有不同的叫法。

    在 python 里叫函数,是指将一个语句的集合,通过一个名字(函数名)封装起来,执行时,调用函数名即可

    特点:

    (1)减少重复代码(简洁)

    (2)使程序变得可扩展(更广泛)

    (3)让程序变得易维护(好维护)

    3、函数的基本语法(pycharm实现)

    例:
    #实现函数语法:                 
    def sayhi():                              #注意,冒号和小括号一定要有不能忘记
        print("hello world!")
        print("python好简单")
        print("学会挣大钱")
        print("hello my name is Guoyilong age :25")
    print(sayhi)                              #不带括号,会出现一个内存地址,也就是函数名的内存地址
    sayhi()                                   #直接写名字,执行的时候就会出现函数内容
    
    执行后效果:
    <function sayhi at 0x00000286F8393EA0>    #打印不带括号的函数名会出现函数的内存地址
    hello world!
    python好简单
    学会挣大钱
    hello my name is Guoyilong age :25

    4、函数内的参数(pycharm实现)

      函数名的括号内,可以写进去很多参数,实现不同的功能。下面代码实现下简单参数的作用

    例:
    #函数内参数
    def sayhi(name):        #括号里面的“name”就是参数,在这里设置什么,执行前就要穿进去对应的值
        print("hello",name)   
        print("hello my name is Lin Da age :25")
    sayhi("GuoYilong")      #上边设置了参数,这边就要写进对应的值,否则会报错提示没有对应的值
    
    
    #执行后:
    
    hello GuoYilong         #填进去参数会自动生成
    hello my name is Lin Da age :25

    5、函数内简单的计算参数:

       数学计算,也可以用函数来实现,而且利用函数,还可以实现自定制输入不同参数,计算不同结果),

      下面代码实现:

    例:
    def calc(x,y):    #定义两个参数
        res = x**y
        print(res)
    calc(5,7)       #需输入两个参数,输入参数不同,产生结果不同
    calc(3,6)       #参数作用就是产生一定程度的自定制
    
    
    #执行后输出:
    
    78125
    729

    以上就是函数的基本方法和函数内简单的参数实现方法

    下面分析下它的几个特性

    1、减少代码重复:这个一看就很明显,直接调用函数名,比之前挨个编写节省很多空间,很简洁。

    2、使用程序变得可扩展:不用函数,要写很多重复的,而且容易出错,现在只需要写一个就可以全部实现,修改也方便

    3、使程序变的易维护:方便维护,检索一个地方,不繁杂,好维护。

     

    二、函数内的参数

    定义:参数可以让函数更灵活啊,不只能做默认参数的事情,还可以根据调用时传入参数的不同,来决定函数内部的执行流程

    参数 包括 形参变量  和  实参变量

    1、形参变量

    形参,参数内部占位,只能在函数内部使用,函数调用结束,返回主函数后,就不能再使用该形参变量,

    在被调用时才分配内存单元,调用结束后,即刻释放内存。(就像一个数学公式

     

    2、实参变量:

    实参,就是实际的参数,真真正正存在的值,可以是常量、变量、表达式、函数、列表、字典等,无论实参是何种变量,

    在函数调用时,都必须有确定的值,以便把这些值传给形参。因此应预先赋值或现实输入等办法使参数获得确定的值。(就像公式中的值

    下面代码验证下 :       

    形参
    例:
    def calc(x,y):    #定义两个参数,这就是形参(占位)
        res = x**y    #就像是一个数学公式
        print(res)    #调用时分配内存单元,调用结束后即刻释放

     实参 

    例:
    a = 4            #变量可以赋数字,也可以是列表,字典,字符串,函数等等很多类型
    b = 7           
     calc(a,b)       #括号内的 a 和 b 这就是实参
    calc(b,a)        #就像是公式中的具体值

    3、默认参数

      默认参数,就是有一个固定的值,如果不修改,他也会填进去,如果修改,就按修改后的填

    下面代码举例说明:

    例:
    def stu_register(name,age,country,course):  #括号内为形参
        print("---------注册学生信息——————")
        print("姓名",name)
        print("年龄",age)
        print("国籍",country)
        print("课程",course)
    
    stu_register("卿秀安",22,"CN","python")     #括号内为实参
    stu_register("灵千少",24,"CN","java")
    stu_register("张旭东",20,"CN","c+")         
    发现大部分学生信息国籍都是中国(CN),大部分都是国内的学生,那能不能把国籍默认写成中国,其他国家的也可另外修改。
    这个就用到了默认参数的作用
    下面我们代码实现:
    例:
    def
    stu_register(name,age,course,country = "CN"): #注意,默认参数赋值后,必须放在最后面,不能影响位置参数的排序 print("---------注册学生信息——————") print("姓名",name) print("年龄",age) #打印顺序就是位置参数,如果下面填写错误,电脑是分辨不出来的,只能按照填写的运行 print("国籍",country) print("课程",course) stu_register("卿秀安",22,"python") #一旦把默认参数放在没赋值的参数前面,系统会报错,而且会影响位置参数的显示 stu_register("灵少",24,"java") stu_register("张旭东",20,"c+")

    以上两种代码写出来的效果都是一样的

    ---------注册学生信息——————
    姓名 卿秀安
    年龄 22
    国籍 CN
    课程 python
    ---------注册学生信息——————
    姓名 灵少
    年龄 24
    国籍 CN
    课程 java
    ---------注册学生信息——————
    姓名 张旭东
    年龄 20
    国籍 CN
    课程 c+

    4、关键参数

    定义:正常情况下,给函数传参需要按照位置顺序,不想按照位置顺序就可以用关键参数。只需指定参数名即可(指定了参数名的参数就叫关键参数

      但是要求是,关键参数要放在位置参数(以位置顺序确定确定对应关系的参数)之后。

    代码实现:

    例:
    def stu_register(name,age,course,country = "CN"):   
        print("---------注册学生信息——————")
        print("姓名",name)
        print("年龄",age)
        print("国籍",country)                                    #位置参数是这样的
        print("课程",course)
    
    stu_register("卿秀安",course="python",age=18,country=“JP”) #改变了位置参数的默认顺序,但是我都指定赋值,这就是主要参数
    执行结果:
    ---------注册学生信息—————— 姓名 卿秀安 年龄 18 国籍 JP #发现位置没有改变,而且都对应 课程 python

    5、函数--非固定参数

    没有特殊的定义,举例说明下:

    就拿刚讲的发报警的事情来说,之前给一个运维人员发报警,没什么问题,但是现在我的需求是给10个人甚至之后的更多个人发,

    怎么实现这个需求呢?

    代码来看:

    例:
    #非固定参数1(元祖型)
    #发报警,1个人,是这样写的
    def send_alert(msg,users):
        pass
    send_alert("赶紧招呼系统","Guo Yilong")     #警报只发给一个人
    #报警发给10个人,怎么办呢?
    def send_alert(msg,*args):      #只需要在原有的基础上,给users前加个 * 符号(相当于给参数内定义一个元祖),
    #就能实现把多个名字打包一起赋给users(前面加个 * 这个时候,users就属于元祖类型)
    for u in args: print("报警发送给",u) #用 for 循环,把元祖循环打印,发给不同的人,这样就可以实现给10个甚至更多个人发消息 #总结,如果参数里面出现了 *users传递的参数就可以不再是固定参数,而是传过来的所有参数都会打包成元祖发送给 *usres
    #
    方法一: send_alert("赶紧回来,系统出问题了","Alex","Guo Yilong","Wangle","Lining","Msck","Tige") #有多少个人,就可以加多少个人 #方法二: send_alert("赶紧回来,系统出问题了",*["Alex","Guo Yilong","Wangle","Lining","Msck","Tige"]) #这样就相当于把 * 符号后面的列表自己打包,传给 *args #需要注意了:带 * 符号的参数放在所有参数最后,除了用主要参数去实现,否则会报错。

    上面讲了用元祖类型的参数实现非固定应用

    下面我们用字典类型的参数实现非固定参数的应用: 

    例:
    #非固定参数2(字典型)
    def func(name,*args,**kwargs):                    #参数前加一个 * 符号,属于元祖类型,加两个 ** 符号,就属于字典类型
        print(name,args,kwargs)                       #我们先证明数据类型
    func("Guoyilong",22,"Alex","peiqi", "shanshan")   #传进去多个实参
    #执行效果
    Guoyilong (22, 'Alex', 'peiqi', 'shanshan') {}    #发现除了name有对应的值,其他值都赋给了元祖,字典是空的,

     发现字典是空的,是因为传进去的实参,既没有字典的特征,也没有定义字典

    **kwaegs 这个参数接收的是未定义的关键字参数

    下面我们改变方法实现:

    #有字典特征,实现字典内写入实参:
    例:
    def func(name,*args,**kwargs):
        print(name,args,kwargs) 
    
    func("Guoyilong",22,"Alex",adds = "peiqi",tesla = "shanshan",mck = "Wanghua")    #给实参内写入字典格式,通过判断 key ,来实现如果过有 去a , 没有 去b。
    执行代码结果:
    Guoyilong (22, 'Alex') {'adds': 'peiqi', 'tesla': 'shanshan', 'mck': 'Wanghua'}  #发现字典内已有写入的实参

     或者直接定义字典(调用时,直接定义声明,这个就是传给字典结构的)

    定义型:
    例:
    def func(name,*args,**kwargs):
        print(name,args,kwargs) 
    c = {"im":"Liuxin","se":"Qiqiang"}      #把字典赋给变量 c
    func("qiqi","lingsen",**c)              #在变量前加 ** 
    执行代码结果:
    qiqi ('lingsen',) {'im': 'Liuxin', 'se': 'Qiqiang'}   #成功实现了功能

     三、函数 -- 返回值

    函数在外部的代码想要获取函数的执行结果,就可以在函数里用 return 语句把函数内的执行结果返回。

    需要注意的是:

    1、函数在执行过程中,只要遇到 return 语句,就会停止并返回结果,也可以理解为,函数里只要遇见 return 语句,代表着函数的结束。(如果在函数缩进内的 retutrn 下面再写任何代码,都不会被执行)

    2、如果未在函数中定义 feturn ,这个函数会返回值 None 

    注册信息的代码举例说明:

    返回值的作用
    例:
    def stu_register(name,age,course,country = "CN"):
        print("---------注册学生信息——————")
        print("姓名",name)
        print("年龄",age)
        print("国籍",country)
        print("课程",course)
        if age > 22:
            return False               #返回值,一定要返回有用的东西
        else :
            return True
    registriation = stu_register("灵少",24,"java")
    if registriation:
        print("注册成功")               #返回值调用在函数外的使用
    else :
        print("你太老了")
    执行代码结果:
    ---------注册学生信息—————— 姓名 灵少 年龄 24 国籍 CN 课程 java 你太老了 #返回值得作用

    不止能返回 False 和 True 这两个值,还可以返回列表,元祖等类型

    返回元祖:
    例:
    def stu_register(name, age, course, country="CN"):
        print("---------注册学生信息——————")
        print("姓名", name)
        print("年龄", age)
        print("国籍", country)
        print("课程", course)
        return name,age       #如果要返回多个值,在句尾加逗号
    registriation = stu_register("灵少",24,"java")
    print(registriation)      #打印变量
    执行代码结果:
    
    ---------注册学生信息——————
    姓名 灵少
    年龄 24
    国籍 CN
    课程 java
    ('灵少', 24)              #它会把输入的值变成元祖返回
    返回列表类型:
    例:
    def stu_register(name, age, course, country="CN"):
        print("---------注册学生信息——————")
        print("姓名", name)
        print("年龄", age)
        print("国籍", country)
        print("课程", course)
        return [name,age]    #返回列表,只需要把返回值填进列表内,(多个值单词用逗号隔开)
    registriation = stu_register("灵少",24,"java")
    print(registriation)     #打印变量
    执行代码结果:
    例:
    ---------注册学生信息——————
    姓名 灵少
    年龄 24
    国籍 CN
    课程 java
    ['灵少', 24]             #已返回列表

     四、函数 -- 局部变量

      函数内定义的变量,就叫局部变量,在函数内定义的变量,与函数外没任何关系

      下面我们代码验证下:

    局部变量:
    例:
    name = "Guo Yilong","hello world!"   #在函数外,把文字写成英文
    def choice_name():
        name = "郭毅龙","你好"             #(局部变量)在函数内,把名字写成中文
        print("",name)                  #打印函数内名字
    choice_name()
    print("",name)
    #这函数内和函数外虽然变量名是相同的,但是他们是完全独立的,没有任何关系

    执行代码结果:
    
    内 ('郭毅龙', '你好')                  #函数内的值
    外 ('Guo Yilong', 'hello world!')    #函数外的值

     下面更详细的验证下相同变量名的内存地址是否相同

    例:
    name = "Guo Yilong","hello world!" def choice_name(): name = "郭毅龙","你好" print("",name,id(name)) choice_name() print("",name,id(name))
    执行代码结果:
    
    内 ('郭毅龙', '你好') 2993864636857     
    外 ('Guo Yilong', 'hello world!') 2993864700936     #发现两个内存地址完全不同

     还有一种情况就是,如果函数缩进内没有变量会调用外部变量(只能调用不可修改)

    下面代码验证下:

    优先级别:(由内而外)
    例:
    name = "Guo Yilong","hello world!"
    def choice_name():
        print(name,id(name))          #如果内部没有变量,会自动调用函数外变量
    choice_name()                     #分优先级别,先调用函数缩进内变量,如果没有 ,会调用函数外变量
    print("",name,id(name))
    执行代码结果:
    
    ('Guo Yilong', 'hello world!') 2176036502664
    外 ('Guo Yilong', 'hello world!') 2176036502664   #这就叫由内而外,发现调用了外部变量

    小结:

    1. 全局变量:定义在函数外部的一级代码变量,按照顺序全局都可调用。 
    2. 局部变量:是定义在函数缩进内的变量,只能在函数内生效,函数执行结束,局部变量全部无效。
    3. 如果全局和局部都有同名变量,函数会查找变量顺序(由内而外)优先使用函数内部变量,如果相同级别有两个函数的同名变量,它们也是独立的,函数只会优先调用函数缩进内变量,如果没有回调用全局变量,与另外一个同级别函数无关
    4. 函数内部调用全局变量,不可修改,如需修改,需重新定义变量或创建
    5. 函数内可以引用全局变量,但是全局不可以调用局部变量

    五、在函数内修改全局变量

         在实际应用中,不建议在函数内修改全局变量,但如果非要修改,也还是有方法的( global ),所以还是不建议在函数内修改全局变量,因为如果养成恶习,在以后涉及 代码量大的 时候,函数内修改全局变量会导致不好调试和维护,带来很多麻烦

    代码讲一下方法:

    修改全局变量:
    例;
    name = "Guo Yilong","hello world!"
    def choice_name():
        global name               #新语法(意思是告诉python程序要修改全局变量、列表还有其他类型的变量)
        name = "郭毅龙","你好"   #把变量重新修改成汉语(也可是列表、元祖、字典等等其他类型)(注意顺序,先声明,再修改
        age = 52
        print("",name)
    
    choice_name()
    print("",name)  
    执行代码效果:
    
    内 ('郭毅龙', '你好')
    外 ('郭毅龙', '你好')   #发现都改掉了

      在函数内,不只能修改字符串变量,也可修改列表、函数等等很多变量

        下面我们看修改列表变量的方法

        先尝试普通方法能否修改: 

    普通方法:
    例:
    names = ["Alex","peiqi","liudehua","meishu"]      #先设定变量
    def change_names():
        names = ["Guoyilong","Meiliang","Alex"]      #尝试直接改是否可行
        print(names)
    change_names()
    print(names)                                        #打印各层
    执行代码结果:
    
    ['Guoyilong', 'Meiliang', 'Alex']
    ['Alex', 'peiqi', 'liudehua', 'meishu']     #发现并没有修改

        因为之前讲过,列表、其他类型套列表都是不可更改整个列表的内存地址的,(当然除了 global 这个方法 )但列表内的值是可以修改的,

        下面代码实现下:

    修改列表内元素:
    例:
    names = ["Alex","peiqi","liudehua","meishu"]
    
    def change_names():
    
        del names[3]                   #修改和删除列表内的元素
        names[2] = "Guoyilong"
        print(names)
    
    change_names()
    print(names)       
    执行代码结果:
    
    ['Alex', 'peiqi', 'Guoyilong']
    ['Alex', 'peiqi', 'Guoyilong']         #发现已经修改成功,验证了上边的话
    注意:所有包含很多字符串元素的内部值,都是可以通过这样方法实现修改,唯一不能修改的是:字符串和数字(因为本事就是个内存地址,没办法修改)

    六、函数--嵌套函数

       元祖、列表、字典等类型可以嵌套,函数类型也可嵌套(利用缩进)

      下面代码执行下:   

    嵌套函数:
    例:
    age = 22                 #设定全局变量
    def funt1():
        age = 35             #设定各层级局部变量
        print(age)
        def funt2():         #内部函数可以再次定义函数
            age = 48
            print(age)       #每一层都互不干扰
            def funt3():
                age = 77
                print(age)
            funt3()
        funt2()             #注意缩进
    funt1()                 #执行时,需被调用,否则,不会执行

    执行代码结果:
    
    35                     #发现嵌套内代码 全部执行
    48
    77

      下面分析几个情况,把变量放在不同位置,看执行哪里变量

    #换位置
    age = 22
    def funt1():
        print(age)
        def funt2():
            age = 35
            print(age)
            def funt3():
                print(age)  #这种情况会执行那个变量
            funt3()
        funt2()
    funt1()

    代码输出结果:
    
    22                     #发现外边函数调用的是全局变量
    35                     #发现内2套函数调用的是局部变量
    35                     #这就总结了局部变量的调用方法,它会由最内部逐层、逐级依次向外查找变量,找到为止

     六、函数 -- 作用域

    定义:在 python 中,一个函数就是一个作用域,所有的局部变量,就是放置在局部变量内,代码定义完成后,作用域就已生成,调用时,就会根据作用域嵌             套关系(也可称为作用域链)由内而外层层往上找。

    下面我们代码验证下:

    作用域
    例:
    第一
    age
    = 18 def funt1(): age = 22 def funt2(): print(age) return 666 #设置返回值 val = funt1() print(val)
    666                #被执行会会是 return 返回值,而不是其他
    
    
    
    第二
    age = 18
    def funt1():
        age = 22
        def funt2():
            print(age)
        return funt2        #设置不带括号的函数名
    val = funt1()
    print(val)
    执行代码结果;
    
    <function funt1.<locals>.funt2 at 0x00000259AE603F28>    #返回 funt2 的内存地址,
    #理下思路:val = funt1(),
    而 funt1()设置的返回值 return 返回的是funt2 的内存地址 (函数名不加括号返回函数本身的内存地址)
    这就证明,其实 val = funt2 (加了括号会返回funt2 函数代码的执行结果)
    第三
    age = 18
    def funt1():
        age = 22
        def funt2():
            print(age)
        return funt2       
    val = funt1()
    val()              #现在把val 加上括号看是否与 val = funt2()相同
    执行代码结果:
    
    22                #和 funt2()  效果相同

     七、函数--匿名函数

    匿名函数,顾名思义就是没起名字的函数,定义一个函数不用名字,下面先和正常函数对比下

    匿名函数:
    例:
    #先写一个正常的函数
    def calc(x,y): 
        return x*y
    
    #再看匿名函数
    lambda x,y:x*y      #这句话叫声明一个匿名函数,
    #这个公式就和上边的正常函数一个效果,但是如果使用的话还是要定义一个变量
    func = lambda x,y:x*y 
    
    下面验证下执行结果
    print(calc(7,8) )   #执行正常函数
    print(func(7,8) )   #执行匿名函数
    执行代码结果:
    
    56
    56       #发现执行结果相同,说明作用相同

    那么,匿名函数还能做什么,下下面我们再来看:

    例:
    #下面写一个判断
    def calc(x,y):
        if x < y:
            return x*y
        else :
            return x/y
    #正常函数判断是没错的,但是匿名函数内是不可以写这样复杂的判断的
    
    func = lambda x,y:x*y if x<y else x/y    #但是匿名函数可以用三元运算
    print(calc(16,4))
    print(func(16,4))

    执行代码结果:
    
    4.0
    4.0
    #执行结果也相同,其实只看上面觉得匿名函数还是要赋变量名,看着还很模糊,还不如用正常的函数
    #这只是在普通场景下,在很多场景下,匿名函数不是单独使用而是搭配其他语法使用

    匿名函数的搭配使用:

    例:
                                 #匿名函数最常用的是搭配其他语句的使用
    #下面有一个列表,需求就是把列表的每一个值自乘(1*1,2*2,3*3....循环之)
    data = list(range(10))       

    1、用普通的方法(for 循环)
    for index,i in enumerate(data): data[index] = i*i #比较麻烦

    map()
    #新语法 :括号内可以放2个值(函数,数据集合)
    相当于会把数据结合内的每一个值当做一个参数,交给函数执行一遍
    2、用普通的函数实现map的功能 data = list(range(10)) print(data) #先预设一个普通函数: def func(n): return n*n map(func,data)#简单的这样就是可以取到值 f = list(map(func,data))# 但是传进去的是列表所以要打印列表格式 print(f)
    3、用 lambda 函数(匿名函数)实现 data = list(range(10)) print(data) print(list(map(lambda x :x*x,data)))
    ****以上代码执行结果都是一样的***** #lambda 后面就是匿名函数,我再这里使用之后就不再调用,所以只在这一个地方起作用就可以了

    *** 匿名函数小结:1、节省代码量      2、看着高级 

    八、函数--高阶函数

      定义:变量可以指向函数,函数的参数可以接收变量,那么一个函数就可以接收另一个函数作为参数,而这种函数就称为高阶函数。

      变量可以指向函数:

    例:
    f = lambda  x: x*x       #变量可以指向函数
    print(f(8))
    
    def calc(x,y):           #变量可以指向函数
        return x/y
    s = calc
    print(s(8,4)) 

     函数的参数可以接收变量:

    例 :
    
    def calc(x,y):           #设置正常函数
        return x+y
    def func(x):
        return x*x
    n = calc                 #函数可设置成变量
    a = 7
    b = 13
    print(n(a,b))            #函数的参数可以设置成变量

    这就相当于一个函数的参数可以设置成另外一个函数(一个函数就可以接收另一个函数作为参数):

    例:
    def calc(x,y):          #设置一个函数
        return x+y
    
    def func(x):            #设置另一个参数
        return x
    
    f = func(calc)          #相当于第一个函数被第二个函数当做参数执行,
    print(f(7,5))           #因为第一个函数被当作参数,所以要传进去2个值

    以上这种函数结构就叫高阶函数

    还有另一种方法:(把函数当作一个参数返回)

    例:
    def calc(x,y):         #设置一个函数
        return x+y
    def func():
        return  calc(7,5)  #把上一个函数当做函数的返回值
    
    print(func())

    绝对值函数:

    例:
    def func2(x,y):        #设置一个函数
        return abs(x+y)    # abs() 新语法:绝对值,就是负数绝对值后成正数返回(abs()是参数)
    print(func2(-5,-8))
    执行代码结果:
    
    13                    #已经当正数返回
    例:
    def func2(x,y):       #再设置一个参数
        return abs,x,y    # abs() 新语法:绝对值,就是不管正负数,都会返回正数
    res = func2(7,-11)    #只要函数内包含另一个函数,就被称为高阶函数
    print(res)
    执行代码结果:
    
    (<built-in function abs>, 7, -11)  #只要执行的函数包含另一个函数就叫高阶函数

    高阶函数查看执行结果:

    例:
    def func2(x,y):       
        return abs,x,y  
    res = func2(-3,-11)    
    print(res[0](res[1]+res[2]))   #函数也是以索引为导向提取对应的值,注意括号外的是函数名,括号内的值为函数的参数

    执行代码结果:
    
    14               #这就是告诫函数,和绝对值的作用
    小结:只需满足下面任意条件即是高阶函数
    1、接收一个或者多个函数作为输入(参数)
    2、return 返回另一个函数

     ———————————————————结束线———————————————————

  • 相关阅读:
    Springboot中mybatis控制台打印sql语句
    CTF资源
    Python渗透测试工具合集
    哪些方法可以绕过PowerShell Execution Policy?
    路由器漏洞挖掘使用的脚本
    路由器漏洞挖掘(栈,危险函数,方法)
    路由器漏洞挖掘环境搭建
    MIPS 汇编指令学习
    Linux下安装Sublime Text 3 及使用快捷方式
    Ubuntu 16.04 安装Python 3.6
  • 原文地址:https://www.cnblogs.com/guoyilong/p/10059120.html
Copyright © 2020-2023  润新知