【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

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

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

原文地址:https://www.cnblogs.com/liupengpengg/p/5623171.html