zoukankan      html  css  js  c++  java
  • 【Python】函数基础简介


    一、函数

    1. 简介

      函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率

    2. 组成

    • 函数代码块以 def 关键词开头,后接函数名和圆括号()
    • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数主体部分:函数内容以冒号起始,并且缩进。
    • 函数结束部分:return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

    示例:

    1 def functionname( parameters ):
    2    "函数声明、注释等内容,一般为__doc__部分"
    3    函数主体部分
    4    return [expression]

    3. 简单调用

      以上边的示例为例,调用方法很简单执行如下代码。

       functionname(参数) 

      注意,函数定义好之后,并不会运行。只有在调用的时候会运行。

    二、函数各组成部分

    2.1 函数的命名

      函数名应该为小写,可以用下划线风格单词以增加可读性。如:myfunction,my_example_function。

    Python之父Guido推荐的命名规范包括如下几点:
    模块名和包名采用小写字母并且以下划线分隔单词的形式;
    类名采用以大写字母开头,并且以大写字母分隔单词的形式命名;
    全局或者类常量,全部使用大写字母,并且以下划线分隔单词;其余变量命名则是采用全部小写字母,并且以下划线分隔单词的形式命名。
    以上的内容如果是内部的,则使用下划线开头命名。

    2.2 函数参数

      函数的参数分为四类:普通参数、默认参数、指定参数、可变参数

    2.2.1 普通参数

    1 def functionname(name,age):
    2     print("I'm %s, age %s" % (name, age))
    3 
    4 functionname("yaoming",18)
    5 out: I'm yaoming, age 18

    2.2.2 默认参数

    1 def functionname(name,age=18):
    2     print("I'm %s, age %s" % (name, age))
    3  
    4 functionname("yaoming")
    5 out: I'm yaoming, age 18

    2.2.3 指定参数

    1 def functionname(name,age=18):        
    2     print("I'm %s, age %s" % (name, age))
    3  
    4 functionname(age=32, name="yaoming")    #上述默认age参数为18,如果这里不指定age的话,默认会使用18,但是如果我们指定参数的话,优先会执行我们指定的参数值。
    5 out: I'm yaoming, age 32

    2.2.4 可变参数

    2.2.4.1 可变参数*

    复制代码
    1 def function_name(*args):
    2     print(args, type(args))
    3 
    4 function_name(1,2,3)
    5 out: (1, 2, 3) <class 'tuple'>
    6 
    7 function_name((1,2,3))
    8 out: ((1, 2, 3),) <class 'tuple'>
    复制代码

      由上边的例子可以看出,默认将传入的参数,全部放在元组中,即args = (...),在执行()的时候,会进行tuple.__init__方法。

    复制代码
    1 def function_name(*args):
    2     print(args, type(args))
    3 function_name(*(1,2,3))
    4 
    5 out: (1, 2, 3) <class 'tuple'>
    6 
    7 function_name(*'wzg')
    8 function_name(*['jack','tony'])
    9 out: ('w', 'z', 'g') <class 'tuple'>
    10 out: ('jack', 'tony') <class 'tuple'>
     
    复制代码

      从上边的例子,可以看出带*的参数,会循环变量中的每个元素加入至tuple中。字符串的话循环每个字母。如果传入的是个列表或者元组,返回的是列表,元组中的每个元素。class类型都是作为'tuple'返回。

    def function_name(*args):
    #print(args,type(args))

    for name in args:
    print(name,type(name))


    function_name('liupeng','jack',11,22,['a','b','c'])
    out: 
    liupeng <class 'str'>
    jack <class 'str'>
    11 <class 'int'>
    22 <class 'int'>
    ['a', 'b', 'c'] <class 'list'>

       还是基于*args案例的基础上添加了for循环语句,循环的是args中的每个元素并显示元素的类型。从上例可以看出*接收的不光可以是一个字符串,还可以是数字或者列表。

    2.2.4.2 可变参数**

    复制代码
    
    
    def function_name(**args):
    print(args,type(args))


    function_name(name = 'wzg',job = "IT")
    
    
    out: {'name': 'wzg', 'job': 'IT'} <class 'dict'>

    -----------------------------------------------------------
    dic = {'k1':'v1','k2':'v2'}
    function_name(**dic)
    out: {'k2': 'v2', 'k1': 'v1'} <class 'dict'>
    -----------------------------------------------------------
    function_name(di = dic)
    out: {'di': {'k2': 'v2', 'k1': 'v1'}} <class 'dict'>
    复制代码

      从上边的例子可以看出,可变参数** , 默认将参数的参数,全部放在字典中进行处理。

      具体分析下上例:

      1.函数本身不用多说,当我们在第一次调用函数时因为参数我们指定了(name跟job的)参数因此打印时候直接输出了字典keys为name跟job,values为wzg,IT即 {'name': 'wzg', 'job': 'IT'} <class 'dict'>

      2.在第二次调用函数时,会发现我们这次调用函数()中传的参数也是**的方式。这里提前创建了一个dic的字典并把它作为函数的参数使用。结合**的用法,使得字典中每个元素作为参数传到函数中被调用。

             即{'k2': 'v2', 'k1': 'v1'} <class 'dict'>

      3.最后一次调用函数时,我们参数是这么指定的(di = dic),这里可以看出跟1的使用方法相同。对了,没错。这次只不过是我们把整个dic作为了字典中的values来传入函数了而di做为了字典中的key。即

       {'di': {'k2': 'v2', 'k1': 'v1'}} <class 'dict'>

    总结:上面1-3不管那一种的类型最终都是<class 'dict'>也就是说**args,或者**其他什么变量最终生成的结果都是以字典的方式呈现。而*args最终都是以元组的方式呈现。

    2.3 函数注释

      Python有一种独一无二的的注释方式: 使用文档字符串. 文档字符串是包, 模块, 类或函数里的第一个语句. 这些字符串可以通过对象的__doc__成员被自动提取, 并且被pydoc所用。参照下面的一个代码

    def function_name(big_table, keys, other_silly_variable=None):
        """Fetches rows from a Bigtable.
    
        Retrieves rows pertaining to the given keys from the Table instance
        represented by big_table.  Silly things may happen if
        other_silly_variable is not None.
    
        Args:
            big_table: An open Bigtable Table instance.
            keys: A sequence of strings representing the key of each table row
                to fetch.
            other_silly_variable: Another optional variable, that has a much
                longer name than the other args, and which does nothing.
    
        Returns:
            A dict mapping keys to the corresponding table row data
            fetched. Each row is represented as a tuple of strings. For
            example:
    
            {'Serak': ('Rigel VII', 'Preparer'),
             'Zim': ('Irk', 'Invader'),
             'Lrrr': ('Omicron Persei 8', 'Emperor')}
    
            If a key from the keys argument is missing from the dictionary,
            then that row was not found in the table.
    
        Raises:
            IOError: An error occurred accessing the bigtable.Table object.
        """
        function_body
        return [expression]
    
    注释
    注释:

      从例子中,可以看出函数注释包含以下几个部分:

      1.整体功能说明  2.输入参数说明  3.输出/返回值说明  4.异常说明  5.其他

    2.4 函数主体

      函数主体部分就是代码逻辑的实现/处理过程。

    2.5 函数返回值

      函数返回值是一个可选的选项,可以返回一个表达式、某种数据结构等。默认返回None

    三、函数的分类

       函数大概可以分为以下几类

    • 內建函数
    • 自定义函数
    • 匿名函数

     3.1 內建函数 __builtins__

      从Python3.5官网拔下来一张最新的内置函数列表

      与2.7Python相比:

      新增:ascii() ,bytes() , exec(),
      减少:basestring() ,cmp(), execfile(), file(),long(),raw_input(),reduce(), reload() , unichr(), unicode() ,xrange()

    3.2 常用內建函数

    3.2 常用內建函数

    函数名 作用
    all(iterable) 1、集合中的元素都为真的时候为真  2、特别的,若为空串返回为True
    any(iterable) 1、集合中的元素有一个为真的时候为真 2、特别的,若为空串返回为False
    bool([x]) 将x转换为Boolean类型
    ascii() 只要执行这个方法,则会自动调用对象的__repr__。这个函数跟repr()函数一样,返回一个可打印的对象字符串方式表示。当遇到非ASCII码时,就会输出x,u或U等字符来表示。与Python 2版本里的repr()是等效的函数。
    abs(x) 求绝对值
    pow(x, y[, z])  返回x的y次幂
    oct(x) 将一个数字转化为8进制
    hex(x) 将整数x转换为16进制字符串
    bin(x) 将整数x转换为二进制字符串
    bytes("要转化的字符串", encoding="编码") 字符串转换为字节类型

    具体详细使用方法请参照:https://docs.python.org/3/library/functions.html#reversed

    or http://www.cnblogs.com/phennry/p/5544509.html (英文不好的同学推荐)

    3.3 自定义函数

      我们平时使用的大多数函数,以及开发中创建的函数,都属于自定义函数。这极大的提高了代码的重用性和可读性。

          自定义函数的创建和使用,在上文中已经进行了说明和示例,参照上边文章即可。这里不作过多说明。

    3.4 匿名函数

      python 使用 lambda 来创建匿名函数。

    • lambda只是一个表达式,函数体比def简单很多。
    • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
    • lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
    • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    3.4.1 匿名函数创建语法

        lambda [arg1 [,arg2,.....argn]]:expression

    3.4.2 示例

    >>> lambda x: x+1 #一个参数
    >>> lambda x,y,z:x+y+z #多个参数

    >>> lambda x,y=3: x*y #允许参数存在默认值,但是默认值的参数必须参数顺序最后

    e = lambda x,y = 3: x*y
    print(e(4))
    
    out:
    12
    
    a = lambda x,y=2: x*y
    print(a(4,5))
    
    out:
    20
    
    b = lambda x,y,z: x*y*z
    print(b(3,5,2))
    
    out:
    30
    lambda表达式

    lambda表达式函数表达

    通过下例可以看出普通方式跟lambda表达式的方便之处直接通过lambda表达式就能返回值。

    #定义函数  (普通方式)
    
    def name(arg):
        return arg + 1
    
    #执行函数
    
    print(name(23))
    
    out:
    24
    
    #定义函数  (lambda表达式)
    
    my_lambda= lambda arg: arg +1
    
    #执行函数
    
    result = my_lambda(23)
    
    print(result)
    
    out:
    24
    

    四、作用域

      python中的作用域分4种情况:

      L:local,局部作用域,即函数中定义的变量;
      E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
      G:global,全局变量,就是模块级别定义的变量;

      B:built-in,系统固定模块里面的变量,比如int, bytearray等。

    搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB。

    补充:

    函数局部变量和全局变量:
    在局部中调用全局变量(读取全局变量默认不用写。修改时需要),当全局变量为列表和字典,局部引用区域引用时不使用global时也是可以修改,不能重新赋值。全局变量与局部变量名称冲突时,在函数体内部优先使用局部变量

    >>> li=[11,22,33]
    >>> def  name(li):
        li=li.append(44)    #全局变量在函数体内由于是引用,所以可以别修改,但是不能被赋值
    >>> name(li)
    >>> print(li)
    [11, 22, 33, 44]
    
    >>> li=[11,22,33]
    >>> def  name(li):
        li='hello'     #函数体内对全局变量赋值,结果没有改变
    >>> name(li)
    >>> print(li)
    [11, 22, 33, 44]
    
    
    >>> li=[11,22,33]
    >>> def  name(arg):
        global li            #使用global,可以对全局变量进行修改,不建议使用
        li='hello world'    
    >>> name(li)
    >>> print(li)
    hello world
    

    五、文件操作

    操作文件,一般需要经过三大步骤

      1. 打开文件

      2. 操作文件

      3. 关闭文件(非必须)

    3.1 打开文件

      打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。通常我们使用open()函数来打开文件,源码中说明了打开模式:

    open函数3.5.1源码
    模式描述
    r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
    rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
    r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
    rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
    w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。这种方法基本不用
    wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
    ab+

    以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    x
    如果文件存在则报错,如果不存在,则创建文件并写内容

    3.2 操作文件

      创建文件句柄之后,可以针对句柄对文件进行如下操纵

    python3.5.1源码

     3.3 关闭文件

      这步操作并不是必须的,如果使用open()函数打开文件,那么要记得最终close()文件

    如果使用with 语句打开的文件,则不需要。在with 语句主体语句执行完之后,会自动调用close()来关闭文件句柄。语法如下:

    1 with open('db1', 'r', encoding="utf-8") as f1:
    2     for line in f1:
    3         print(line)

    同时打开2个文件,语法如下:

    1 with open('file1', 'r', encoding="utf-8") as f1, open("file2", 'w',encoding="utf-8") as f2:
    2     pass

    本章总结至此结束!

    此文转载于http://www.cnblogs.com/jishuweiwang/p/5528905.html

    转载此文对于函数的总结个人感觉已经非常细致,因此没有自己撰写,直接转载并对其内容做了测试并添加了部分自己的案例。

    “今天的努力都是明天别人对你的膜拜,今天的停滞就是明天别人对你的唾弃!“

  • 相关阅读:
    Webx5 label的取值和赋值(div)
    webx5 复选框的显示
    WebX5 Data遍历以及获取数组最后一个元素(更新)
    API集市--分享API
    WebX5 Data判断当前行的值是否改变,以及改变当前行的状态
    WebX5手机GPS定位,无需开启网络
    JS:var 变量=变量 && 变量
    jQuery的ready ()的几种写法
    .net 微信支付(公众号支付)遇到的问题
    .net中的Dictionary字典类的使用方法
  • 原文地址:https://www.cnblogs.com/liupengpengg/p/5623171.html
Copyright © 2011-2022 走看看