zoukankan      html  css  js  c++  java
  • 函数

    • 函数的作用
    • 函数的使用原则
    • 函数的三种形式
    • 函数的返回值
    • 函数的参数
    • 固定参数
    • 非固定参数
    • 高阶函数
    • 匿名函数
    • 作用域
    • 递归
    • 全局变量与局部变量

    为什么要用函数?

    #1、代码的组织结构不清晰,可读性差
    #2、遇到重复的功能只能重复编写实现代码,代码冗余
    #3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大 
    

    函数的使用原则:先定义,后调用。

    函数即“变量”,“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名

    #测试一
    def foo():
        print('from foo')
        bar()
    foo() #报错
    
    #测试二
    def bar():
        print('from bar')
    def foo():
        print('from foo')
        bar()
    foo() #正常
    
    #测试三
    def foo():
        print('from foo')
        bar()
        
    def bar():
        print('from bar')
    foo() #会报错吗?不会
    
    
    #结论:函数的使用,必须遵循原则:先定义,后调用
    #我们在使用函数时,一定要明确地区分定义阶段和调用阶段
    
    #定义阶段,只检测语法,不执行代码
    def foo():
        print('from foo')
        bar()
    def bar():
        print('from bar')
    #调用阶段
    foo()
    

    定义函数的三种形式

    #1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印
    #2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
    #3、空函数:设计代码结构
    
    def func1(name):  # 有参数
        print(name)
        
    def func2():  # 无参数
        print("hello word")
        
        
    def func3():  # 空函数
        """void funcation"""
        pass
        
    

    函数返回值(return)

    python返回值三种形式

    
    返回值数=0;返回none
    
    返回值数=1;返回object
    
    返回值数>1;返回tuple
    
    

    示例代码

    
    name = "jack"
    
    
    def func1():
        print(name)
        # 返回None
    
    
    def func2():
        x = [1, 2, 3]
        y = {"name": "alex", "age": 56}
        return x, y, 1
        # 返回 ([1, 2, 3], {'name': 'alex', 'age': 56}, 1)
    
    def func3():
        print(name)
        return 666
        # 返回 666
    
    a = func1()
    b = func2()
    c = func3()
    print(a, b, c)
    
    

    函数参数

    函数参数传递概念:对象作为输入发送给函数的方式

    1、参数的传递是通过自动将对象赋值给本地变量名来实现的

    2、在函数内部的参数名赋值不会影响调用者。因为函数头部的参数名是在函数本地的作用域的。

    3、改变函数的可变对象参数的值也许对调用者有影响

    不可变参数“通过值”进行传递。像整数和字符串这样的对象是通过对象引用而不是拷贝进行传递的。因为对象不可变,实际效果像拷贝一样

    可变对象是通过“指针”进行传递的。列表和字典等可变对象能够在函数内部进行原处的改变,所以在函数退出后仍然有效。

    def change(a, b):
        a = 2
        b[0] = "spam"
      
        
    x = 1
    y = [1,2]
    
    change(x, y)
    
    print(x, y) # 1 ['spam', 2]
    

    形参变量

    只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变

    实参

    可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

    def calc(x, y):  # x, y 是形参
        print(x,y)
        
    a, b = 1, 2
    c = (a, b)  # a,b 是实参
    

    关键参数&默认参数

    关键字参数通过变量名进行匹配,使用name=value这种语法。

    默认参数,在调用中没有传递,函数头部name=value就是默认参数

    默认参数必须放在位置参数之后
    小结:在调用时代表关键字参数,在函数头部代表默认参数

    def func(a, b=2, c=3):  # b=2,c=3为 默认参数
        print(a, b, c)  # 1 4 3
        
        
    func(1, b=4)  # b=4是关键字参数
    

    非固定参数

    *args

    对于调用者来说,以name传递的所有对象,并作为独立的基于位置的参数

    def foo(x, y, *args):
        print(x, y)  # 1 2
        print(args)  # (3, 4, 5)
        
        
    foo(1, 2, 3, 4, 5) 
    
    
    def foo(x, y, *args):
        print(x, y)  # 1, 2
        print(args)  # (3, 4, 5)
    
    
    foo(1, 2, *[3, 4, 5])
    
    
    def foo(x, y, z):
        print(x, y, z)  # 1 2 3
    
    
    foo(*[1, 2, 3])
    

    **kwargs

    以name成对的传递所有的关键字,并作为独立关键字参数

    def foo(x, y, **kwargs):
        print(x, y)
        print(kwargs)  # {'a': 1, 'b': 2, 'c': 3}
    
    
    foo(1, y=2, a=1, b=2, c=3)
    
    
    def foo(x, y, **kwargs):
        print(x, y)
        print(kwargs)  # {'a': 1, 'b': 2, 'c': 3}
    
    
    foo(1, y=2, **{'a': 1, 'b': 2, 'c': 3})
    
    
    def foo(x, y, z):
        print(x, y, z)  # 2 3 1
    
    
    foo(**{'z': 1, 'x': 2, 'y': 3})
    

    *args+**kwargs

    def foo(x,y):
                print(x,y)
    
    def wrapper(*args,**kwargs):
        print('====>')
        foo(*args,**kwargs)
    

    命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递

     def foo(x,y,*args,a=1,b,**kwargs):
                print(x,y)  # 1,2
                print(args) # (3, 4, 5)
                print(a)  # 1
                print(b)  # 3
                print(kwargs)  # {'c': 4, 'd': 5}
    
    foo(1,2,3,4,5,b=3,c=4,d=5)
    
    

    参数总结:

    语法 位置 解释
    func(value) 调用者 常规参数:通过位置匹配
    func(name=value) 调用者 关键字参数:通过变量名匹配
    func(*sequence) 调用者 以name传递所有的对象,并作为其独立的给予位置的参数。
    func(**dict) 调用者 以name成对的传递所有的关键字/值,并作为独立的关键字参数
    def func(name) 函数 常规参数:通过位置或者变量名进行匹配
    def func(name=value) 函数 默认参数值,如果没有在调用中传递的话
    def func(*name) 函数 匹配并收集(在元组中)所有包含位置的参数
    def func(**name) 函数 匹配并收集(在字典中)所有包含位置的参数
    def func(*args, name) 函数 参数必须在调用中按照关键字传递
    def func(*, name=value) 函数 python3.0+中,跟在 * name或一个单独的 * 之后的任何正式的默认的参数都是keyword-only参数,必须按照关键字传递

    全局变量与局部变量

    1、在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

    2、全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

    3、当全局变量和局部变量同名时;在局部变量的子程序内,局部变量起作用;在其他地方全局变量起作用。

    name = "Alex Li"
    
    def change_name(name):
        print("before change:",name)
        name = "金角大王,一个有Tesla的男人"
        print("after change", name)
    
    
    change_name(name)
    
    print("在外面看看name改了么?",name)
    

    输出

    before change: Alex Li
    after change 金角大王,一个有Tesla的男人
    在外面看看name改了么? Alex Li
    

    作用域

    作用域的定义:在代码中变量名被赋值的位置决定了变量能否被访问的范围,这个范围就是作用域。函数定义了本地作用域,模块定义了全局作用域。

    LEGB原则

    L:Local
    E:Enclosing function locals
    G:Gobal(module)
    B:Built-in(python)

    首先是本地然后是函数内,之后是全局,最后是pyonth内置函数。

    作用域法则

    1、内嵌模块是全局作用域

    2、每次对函数的调用都创建一个新的作用域

    3、赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量

    4、所有其他的变量名都可以归纳为本地
    全局或者内置的。

    作用域实例

    age = 18
    def func1()
        age = 73
        def func2():
            print(age)
        return 666
        
    val = func1()
    print(val)  # 73
    

    思考?下面代码会输出什么?

    def extend_list(val, list=[]):
    	# print("in func", list)
    	list.append(val)
    	return list
    
    
    list1 = extend_list(10)
    list2 = extend_list(13, [])
    list3 = extend_list('a')
    
    print("list1",list1)
    print("list2",list2)
    print("list3",list3)
    
    

    输出>>>

    list1 [10, 'a']
    list2 [13]
    list3 [10, 'a']
    

    list1和list3共享一个内空间, list2传入参数'[]',会开辟新的内存空间。

    递归

    在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就叫递归函数

    1.必须有一个明确的结束条件

    2.每次进入更深一层递归时,问题的规模相比上次递归都应有所减少

    3.递归效率不高,递归层次过多会导致栈溢出

    def calc(n, count):
        print(n, count)
        if count < 5:
            return calc(n/2, count+1)
        else:
            return n
    
        
    res = calc(188, 1)
    print("res", res)
    

    高阶函数

    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数.

    def add(x,y,f):
        return f(x) + f(y)
    
    
    res = add(3,-6,abs)
    print(res)
    

    只需满足以下任意一个条件,即是高阶函数

    1、接受一个或多个函数作为输入
    2、return 返回另外一个函数

    匿名函数

    匿名函数就是不需要显式的指定函数名

    calc = lambda x,y:x**y
    print(calc(2,5)
    

    匿名函数往往搭配其他函数使用

    res = map(lambda x:x**2,[1,5,7,4,8])
    for i in res:
        print(i)
    

    内置方法

    http://www.cnblogs.com/Jason-lin/p/8186513.html

  • 相关阅读:
    maven项目启动报错
    maven环境变量配置
    jdk版本升级 eclipse启动失败
    jdk10 环境变量配置
    Invalid bound statement 无效的绑定 的解决办法!
    【Java】-NO.16.EBook.4.Java.1.004-【疯狂Java讲义第3版 李刚】- 内部类
    【Java】-NO.14.Java.4.Java.1.001-【Java JUnit 5 】-
    【Java】-NO.13.Java.1.Foundation.1.001-【Java IO】-
    【设计模式】用追MM来解释23种设计模式,转
    【Linux】-NO.8.Linux.4.Command.1.001-【Common Command】-
  • 原文地址:https://www.cnblogs.com/Jason-lin/p/8186517.html
Copyright © 2011-2022 走看看