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

  • 相关阅读:
    21.Merge Two Sorted Lists 、23. Merge k Sorted Lists
    34. Find First and Last Position of Element in Sorted Array
    leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、301. Remove Invalid Parentheses
    31. Next Permutation
    17. Letter Combinations of a Phone Number
    android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
    oc 异常处理
    oc 类型判断
    oc Delegate
    oc 协议
  • 原文地址:https://www.cnblogs.com/Jason-lin/p/8186517.html
Copyright © 2011-2022 走看看