zoukankan      html  css  js  c++  java
  • Python函数的基础知识

    函数是一段具有特点功能的、可重用的语句组。(将代码封装起来) 

    定义:def(定义一个函数)关键词开头,空格之后接函数名称和圆括号(),最后还有一个“:”。

       def是固定的,不能变,必须是连续的def三个字母,不能分开。

       空格  为了将def关键字和函数名称分开,必须空。

       函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短并表达函数功能

       括号:必须要有;

    注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性

    调用:就是函数名()一定要加上括号

    #函数定义
    def my_len():
        """计算s1的长度"""
        s1 = "hello world"
        length = 0
        for i in s1:
            length = length+1
        print(length)
    
    #函数调用  
    my_len()
    函数的定义和调用
    注:只定义函数而不调用,函数就不执行。

    函数的返回值

    在调用python自带的len函数时,必须用一个变量来接收这个值。

    str_len=len('hello,word')

    使用自己写的函数也可以做到这一点

    # 函数定义
    def my_len():
        s1='hello world'
        length=0
        for i in s1:
            length=length+1
        print(length)
    str_len=my_len()  #函数调用
    print('str_len:%s'%str_len)
    # 11
    # str_len:None  说明这段代码什么都没有返回。

    在写函数的时候,要尽量以功能为向导,结果最好不要直接在函数中打印出来。

    关键字return的作用

    1、返回一个值

    2、终止一个函数的继续

    def my_len():  # 函数名的定义
        s1='hello world'
        length=0
        for i in s1:
            length=length+1
        return length  # 函数的返回值
    str_len=my_len()  #函数的调用以及返回值的接收
    print(str_len)
    # 11

    在没有返回值的时候:

    1、不写return与写入return None的效果相同,返回的只都是None          

    2、只写一个return后面不加任何东西的时候与写return None的效果一样

    返回多个值:

    1、当用一个变量接收返回值的时候,收到的是一个元组。这是因为在python中把用逗号分割的 多个值认为是一个元组。

    2、当返回值有多个变量接收,那么返回值的个数应该和接收变量的个数完全一致。

    3. return还有一个特殊的用途,一旦执行到return,后面的语句就不在执行了(结束一个函数)。(和break类似但有区别,break是跳出循环,如果循环后有代码则继续执行。return是结束整个函数)

    4.如果在函数中有多个return,只执行第一个return。

    ###########
    def func():
        return "a" , "b"   #返回多个值时接收到的是一个元组
    c = func() # c接收的是一个元组
    print(c)
    ##('a', 'b')
    #返回多个值,用多个变量接收(接收的变量数与返回值的个数要一致)
    def func():
        return "a" , "b" , "c"
    d , e , f = func()
    print(d , e , f)
    ##a b c
    
    def func():
        return [1,2,3]
    a , b , c = func() #列表和元组是可以解包的
    print(a,b,c)
    ##1 2 3

    返回的字典类型有点意外:
    def func():
    return {"name":"span"}
    dic = func() #需要字典类型来接收,而不能直接用k,v,字典解包解出来的只是键
    print(dic)
    ##{'name': 'span'}
     
    ##return扩展
    def f(L):  #L为形式参数,接收参数
        if len(L)>4:
            return True
        else:
            return False
    s=[1,2,3,4]
    dic={5,6,7,8,9}
    print(f(s)) #s为实际参数,给参数的过程就是传参(argument)
    print(f(dic))
    # False
    # True

    函数的参数:

    #函数定义
    def fun(s):
        count=0
        for i in s:
            count+=1
        return count
    #函数调用
    str=fun('jshdjkshkdhsk')
    print(str)
    #13
    在上述代码中,告诉了fun函数要计算的字符串是谁,这个过程就是传递参数,简称传参;在调用函数时传递的这个'jshdjkshkdhsk'和定义函数时的s就是参数。

    实参与形参:

    在调用函数时传递的'jshdjkshkdhsk'被称为实际参数,因为这是实际要交给函数的内容,简称实参

    定义s的时候,s只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参

    在传递多个参数:多个函数分别可以使用任意数据类型

    按照关键字传参数和按照位置传参数是可以混用的,但是首先都是按位置传,之后再是按关键字传的;按照位置传完该接收的参数只能接收一个值,不接受或者重复接收。

    ###传递两个参数的情况
    def my_sum(a,b):#有两个参数就该传两个参数,1对应a;2对应b (这样的参数就称为位置参数)
        res = a + b
        return res
    ret = my_sum(1,2)
    print(ret)
    #3
    #站在传参(实参)的角度
    #按照位置传参
    #按照关键字传参
    #混着用也可以,但必须是先按照位置传参,再按照关键字传参
       #不能给一个变量传多个值
    def my_sum(a,b):
        print(a,b)
        res = a + b
        return res
    
    ret = my_sum(1,b=2)
    print(ret)
    ##
    1 2
    3

    def my_sum(a,b):
        print(a,b)
        res = a + b
        return res
    
    ret = my_sum(b=2,a=1)
    print(ret)
    
    ##
    1 2
    3
    
    

     

    ###站在形参的角度上:

      #位置参数:必须传(有几个参数就传几个,不能多传和少传)

      #默认参数,可以不传,如果不传就按默认的参数,如果传了就按传了的值

    ####在调用函数的时候:

      #若按照位置传,直接写参数的值

      #若按照关键字传,关键字=值

    ###定义函数的时候

      #位置参数

      #默认参数,关键字参数。 参数名=值

      #在定义参数时必须先定义位置参数再定义默认参数

      #动态参数(*args),可以接收任意多个参数,组织成一个元组

      #动态参数(**kwargs),接收的是按照关键字传参的值,组织成一个字典

      #args必须在kwargs之前

    ######接收参数的先后顺序:位置参数、*args、默认参数、**kwargs#############

     ###默认参数:是可以不传的参数,在不传参数的情况下可以使用默认值;如果传了,就会使用传的值

    def classmate(name,sex=''):
        print('姓名:%s,性别:%s' %(name,sex))
    classmate('张三')
    classmate('李四')
    classmate('翠花','')
    
    # 姓名:张三,性别:男
    # 姓名:李四,性别:男
    # 姓名:翠花,性别:女

    默认参数 魔性用法:默认参数尽量避免使用可变数据类型(默认参数的陷阱)

    def func(L=[]):  # 相当于在def之前先定义了一个str=[],再将str赋值给L,如果不传参数就共用这个数据类型
        L.append(2)
        print(L)
    func()
    func()
    func()
    func()
    
    # [2]
    # [2, 2]
    # [2, 2, 2]
    # [2, 2, 2, 2]

    def fun(L=[]):  # 相当于在def之前先定义了一个str=[],再将str赋值给L
        L.append(2)
        print(L)
    fun([])
    fun([])
    fun([])
    fun([])
    #[2]
    # [2]
    # [2]
    # [2]

    ##################################
    def func(k,d={}): #参数有可变数据类型如列表、字典等,如果不给可变数据类型赋值,则一直用的是同一个列表或字典
        d[k] = "V"
        print(d)
    
    func(1)
    func(2)
    func(3)
    ###
    {1: 'V'}
    {1: 'V', 2: 'V'}
    {1: 'V', 2: 'V', 3: 'V'}

    动态参数:

    1、*args:接收所有按照位置传的参数。

    #动态参数def func(*args):  # 在参数前面加个*,这个参数就变成了动态参数
    def func(*args):
        print(args)  # 使用的时候,所有接收过来的参数都被组织成一个元组的形式
    func(2,3,4,'span',[1,2,3])
    ##(2, 3, 4, 'span', [1, 2, 3])


    ###*args只能接收按位置传参,按照关键字传参就接收不到
    def func(*args,L=[]):
        print(args,L)  # 使用的时候,所有接收过来的参数都被组织成一个元组的形式
    func(2,3,4,'span',L=[1,2,3])
    ##(2, 3, 4, 'span') [1, 2, 3]

    #位置参数  动态参数  默认参数
    def func(a,b,c,*args,key='key'):  # 在参数前面加个*,这个参数就变成了动态参数
        print(a,b,c)
        print(key)
        print(args)  # 使用的时候,所有接收过来的参数都被组织成一个元组的形式
    func(2,3,4,'span',[1,2,3],'xiaoming')
    
    ##
    2 3 4
    key
    ('span', [1, 2, 3], 'xiaoming')

    ##累加器

    def sum(*args): ##多个动态参数累加
        res = 0
        for i in args:
            res += i
        return res
    
    ret = sum(3,4,5)
    print(ret)
    #12

     2、**kwargs:按照所有接收关键字传的参数。 

    def func(**kwargs):
        print(kwargs) 
    func(a=1,b=2,c=3)
    func(a=100)
    ##
    {'a': 1, 'b': 2, 'c': 3}
    {'a': 100}

    ##无敌用法: 

    def func(*args,**kwargs): #能接收无限多个位置参数和关键字参数
        print(args,kwargs)
    func(1,2,3,a=1,b=2,c=3)   #必须先传位置参数再传关键字参数
    ##
    (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}

    ######接收参数的先后顺序:位置参数、*args、默认参数、**kwargs#############

    ## *args的魔性用法:

    def sum(*args):  # 站在形参的角度上,*args的作用是聚合,将传入的参数转变成元组的形式
        print(args)
        sun=0
        for i in args:
            sun+=i
        return sun
    L=[1,2,34,5]
    print(sum(*L))  # 站在实参的角度上,*L是将列表L按顺序打散之后变成将列表中的每个元素分别输出
    ##
    (1, 2, 34, 5)
    42

    ##**kwargs的魔性用法:

    def func(**kwargs):#聚合
        print(kwargs)
    func(c
    =3,d=5) dic={'a':1,'b':4} func(**dic) #打散 # {'c': 3, 'd': 5} # {'a': 1, 'b': 4}

     ####三元运算符

     三元运算符 
    a=1
    b=7
    c=0
    if a>b:
        c=a
    else:
        c=b
    print(c)
    
    #与以下的代码的作用效果相同(三元运算表达式)
    c=0
    a=1
    b=7
    c=a if a>b else b  #如果a>b成立,则c=a,否则c=b
    print(c)

    NAMESPACE 命名空间,名称空间

    局部命名空间:定义函数都拥有自己的命名空间(局部命名空间可以有多个)。(函数内部定义的变量名,当调用函数的时候才会产生这个名字空间,随着函数的结束这个名字空间又消失)

    ##多个函数应该拥有多个局部的名字空间,且不互相共享。

    def  func1():
        a = 1
    
    def func2():
        print(a)
    
    func2()
    ##
    NameError: name 'a' is not defined

    全局命名空间:写在函数外面的变量名和函数名(全局命名空间,是在程序从上到下执行的过程中依次加载进内存里的,放置了全局变量名和函数名)

    内置命名空间:python解释器启动之后就可以使用的名字(Python解释器一启动就能认识的函数,这些函数就存放在内置命名空间里,这些函数(内置的名字)在解释器启动时加载到内存里

    ########################################################################################################################################

    作用域:

    全局作用域:-----作用在 全局-------内置和全局名字空间中的名字都属于全局作用域

    局部作用域:-------作用在局部-------函数(局部名字空间中的名字)

    #######################################################################################################################################

    Python的解释器要运行起来

    加载顺序:

    先加载所有内置命名空间中的名字,然后按照顺序加载全局命名空间中的名字。

    局部命名空间中的名字:在调用函数的时候产生,并且随着调用的结束而消失。

    ###1.在局部可以使用全局和内置命名空间中的名字

    ###2.在全局可以使用内置命名空间中的名字,但不能使用局部命名空间中的名字(当定义的函数执行完后局部空间就被释放了,消失了)

    ###3.在内置不能使用全局和局部的名字

    (依赖倒置原则,上层模块只能依赖下层模块。反之则不可!)

    ##例:

    例如:max()本身是个内置函数

    print(max([1,2,3]))
    #3

    如果定义一个和内置函数相同名字的函数,则执行定义的函数(全局名字空间的函数,当自己有的时候就不找上级要,如果自己没有就找最近的上级要,如果在没有就找更上级要!)

    def max(L):
        print("In max function!")
    
    print(max([1,2,3]))
    ##
    In max function! #执行的是定义的函数(虽然和内置函数同名)
    None #由于没有返回值,所以打印的是None

    作用域:一个名字可以使用的区域。局部作用域可以使用全局作用域中的变量,而全局作用域不能使用局部作用域中的变量;在局部作用域中还可以嵌套更小的局部作用域。

    全局作用域:内置名字空间和全局名字空间中的名字属于全局作用域

    局部作用域:局部名字空间中的名字属于局部作用域(对于不可变数据类型,在局部只能查看全局作用域的变量,但是不能修改,如果要修改要在变量前加global)

    作用域链:小范围作用域可以使用大范围的变量,但作用域链是单向的,不能反向应用。

    globals():保存了在全局作用域中的名字和值;

    globals和locals方法:小范围可以使用大范围的,但是不能修改,如果想要修改,可以使用global关键字,但是要尽量避免使用,这是因为使用global之后会将全局变量修改掉,这样可能会使其他的要使用原来的全局变量的函数发生变化。(globals()永远打印全局,locals()输出什么要看它出现在什么位置)

    locals():保存了当前作用域中的变量,其中的内容会根据执行的位置来决定作用域中的内容,如果是在全局执行,打印的结果会与globals打印的结果一致。

    n=1
    def func():
        global n  # 在加入这句话之前函数func中没有定义n,会报错。
        n += 1
    func()
    print(n) #如果在一个局部内声明了一个global变量,这个变量在全局有效
    
    #2
    PS:是要尽量避免使用,这是因为使用global之后会将全局变量修改掉,这样可能会使其他的要使用原来的全局变量的函数发生变化。

    ##locals()

    a = 1
    b = 2
    def func():
        x = "aaa"
        y = "bbb"
        print(locals())  #使用locals()可以查看局部空间里的所有名字
    func()
    print(globals())  #使用globals()不仅能够查看全局名字空间里的名字,还可以查看内置名字空间里的名字
    ## {'y': 'bbb', 'x': 'aaa'}

    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000224A85F8828>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/Dell/PycharmProjects/s9/day10/函数进阶.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x00000224A84F2E18>}

    ##locals();globals()

    a = 1
    b = 2
    def func():
        x = "aaa"
        y = "bbb"
    func()
    print(globals())
    print(locals())#本地的
    (输出的结果一样,如果locals()放在全局,打印的就是全局,如果放在局部就是局部)
    ###
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002A1B06F8828>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/Dell/PycharmProjects/s9/day10/函数进阶.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x000002A1B06A2E18>}
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002A1B06F8828>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/Dell/PycharmProjects/s9/day10/函数进阶.py', '__cached__': None, 'a': 1, 'b': 2, 'func': <function func at 0x000002A1B06A2E18>}

    ## nonlcoal 变量名  修改最近的拥有该变量的外层函数的变量,不会影响全局。

    n=0
    def func():
        n=1
        def func2():
            nonlocal n  # 调用上一级函数中的n
            n+=1
        func2()
        print(n)  # n=2
    func()
    print(n)  # 使用全局变量中的n=0
    
    # 2
    # 0
  • 相关阅读:
    【转贴】Cookie + Session + OAuth + SSO
    zz淘宝商品库MySQL优化实践
    HIVE 数据倾斜调优总结zz
    数据挖掘笔记(一)
    hive函数参考手册
    hive QL(HQL)简明指南zz
    数据挖掘笔记(二)
    python format string (转)
    hive 中转义符使用问题
    关于文档管理
  • 原文地址:https://www.cnblogs.com/shaopan/p/9989064.html
Copyright © 2011-2022 走看看