看下面一段伪代码:

	if cpu使用率 >80%:
		连接邮箱
		发送邮件
		关闭邮箱
	if 内存使用率 >80%:
		连接邮箱
		发送邮件
		关闭邮箱
	if 硬盘使用率 >80%:
		连接邮箱
		发送邮件
		关闭邮箱

思考这段代码有什么问题?

1. 函数的概念

函数是一段具有特定功能的,可重用的语句组,用函数名来表示并通过函数名进行完成功能调用。

函数也可以看作是一段具有名字的子程序,可以在需要的地方调用执行,不需要再每个执行地方重复编写这些语句。每次使用函数可以提供不同的参数作为输入,以实现对不同数据的处理;函数执行后,还可以以反馈相应的处理结果。

函数是一种功能抽象。

2. python 中函数的定义

Python 定义一个函数使用 def 关键字,语法形式如下:

def <函数名>(<参数列表>):

	<函数体>

	return <返回值列表>

实例:生日歌

过生日时要为朋友唱生日歌,歌词为:

Happy birthday to you!

Happy birthday to you!

Happy birthday,dear<名字>

Happy birthday to you!

编写程序为 MikeLily 输出生日歌。最简单的方式是重复使用 print() 语句

# 最简单的方式
print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Mike!')
print('Happy birthday to you!')

print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Lily!')
print('Happy birthday to you!')

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!
Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Lily!
Happy birthday to you!
以函数的方式

# 定义函数
def happy():
    print('Happy birthday to you!')

def happy_birthday(name):
    happy()
    happy()
    print('Happy birthday, dear {}!'.format(name))
    happy()

# 调用函数
happy_birthday('Mike')
print()
happy_birthday('Lily')

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Lily!
Happy birthday to you!
看起来感和上面的直接 print 还多了几行代码,但是考虑如果要给 100 个人唱生日歌的情况。

3. 函数的调用过程

程序调用一个函数需要执行以下四个步骤:

  1. 调用程序在调用处暂停执行
  2. 在调用时将实参赋值给函数的形参
  3. 执行函数体语句
  4. 函数调用结束给出返回值,程序回到调用前的暂停处继续执行

上面的 happy_birthday 函数的调用过程



4. 函数的参数

定义函数时 () 里的参数叫形参(形式参数),它只是一个变量名,供函数体中的代码调用。

函数调用时,传入 () 里的参数叫实参(实际参数),它是实际的数据,会传递给形参,供函数体执行。

4.1 形参

定义函数时,形参根据功能不同,可以定义几种类型。

4.1.1 必须参数

在定义函数时,如果要求调用者必须传递实参给这个形参,它就是必须参数。

直接定义在函数名后的 () 中的形参就是必须参数。

例如上面的 happy_birthday 函数中的 name

案例:

定义一个函数接收两个数,然后打印它们的和

def add(x,y):
    print(x+y)
add(1)  # 调用时必须传递实参给必须参数,否则报错

TypeError Traceback (most recent call last)

in
----> 1 add(1) # 调用时必须传递实参给必须参数,否则报错

TypeError: add() missing 1 required positional argument: ‘y’

4.1.2 默认参数

在定义函数时,某些形参有可能在调用时不用接收实参,这种情况可以定义为默认参数。

在函数名后 () 中,以 参数名=默认值 的形式定义的形参就是默认参数。

注意:默认参数必须定义在必须参数的后面

案例:

定义一个函数,它接收两个参数 contenttimes,

content 是函数要打印的内容

times 是函数打印的次数,如果不传递 times 默认打印 1 次

# 定义
def my_print(content, times=1):
    for i in range(times):
        print(content)
# 调用
my_print('happy birthday!')
my_print('happy birthday!', 2)

happy birthday!
happy birthday!
happy birthday!
调用函数时传递实参给默认形参会覆盖默认值。

4.1.3 不定参数

在定义函数时,不确定在调用时会传递多少个实参时,可以定义不定参数。

不定参数根据传递实参的不同(详见 4.2 实参)有分为两种。

位置不定参

在函数名后的 () 中,在形参前加 * 号可以定义位置不定参,通常它会定义为 *args

它用来接收函数调用时,以位置参数传递过来的超过形参数量的多余的实参。

注意:不订参必须定义在默认参数后面

位置不定参数会将所有多余的位置实参创建成元组。

def func(a, *args):
    print(args,type(args))

func(1,2,3,4)

(2, 3, 4) <class ‘tuple’>

案例:

定义一个函数,接收 2 个以上的数,打印它们的和。

def add(x,y,*args):
    x += y
    for i in args:
        x += i
    print(x)
add(1,2,3,4)

10

关键字不定参

在函数名后的 () 中,在形参前加 ** 号可以定义关键字不定参,通常它会定义为 **kwargs

它用来接收函数调用时,以关键字参数传递过来的超过形参数量的多余的实参。

注意:不订参必须定义在默认参数后面

关键字不定参数会将所有多余的关键字实参创建成字典。

def func(a, **kwargs):
    print(kwargs,type(kwargs))

func(a=1,b=2,c=3,d=4)

{‘b’: 2, ‘c’: 3, ‘d’: 4} <class ‘dict’>

4.2 实参

调用函数是传递实参有两种方式。

4.2.1 位置参数

调用函数时,传递实参时默认会按照形参的位置一一对应,这种实参传递叫做位置参数。

案例

定义一个函数实现打印一个数的 n 次幂。

def my_power(x, n):
    print(x**n)

my_power(3,2)
my_power(2,3)

9
8

4.2.2 关键字参数

调用函数时,传递实参时以 形参名=实参 的形式传递参数,叫做关键字参数。

这是不用考虑参数的位置。

注意:关键字参数必须写在位置参数后面。

案例

使用关键字参数调用上面的案例

my_power(x=3,n=2)
my_power(n=2,x=3)
my_power(3,n=2)

9
9
9

my_power(n=2,3)

File “”, line 1
my_power(n=2,3)
^
SyntaxError: positional argument follows keyword argument

4.2.3 *,** 在传递实参时的用法

啥是解包
  • 个人通俗理解:解开包袱,拿出东西
  • 正确理解:将元素从可迭代对象中一个个取出来
  • python 中,解包是自动完成的
* 解包

在传递实参时,可以通过 * 对迭代对象进行解包。

def fun(a,b,*arg):
    print(a,b,arg)
ls = [1,2,3,4,5,6]
fun(*ls) # => fun(1,2,3,4,5,6)
# 解包成多个位置参数


# 输出结果
1 2 (3, 4, 5, 6)
** 解包

在传递实参时,可以通过 ** 对字典对象进行解包。

def fun(a,b, **kwargs):
    print(a,b,kwargs)
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
fun(**d) # => fun(a=1,b=2,c=3,d=4)
# 解包成多个关键字参数

1 2

4.3 返回值

函数还有一个很重要的功能就是返回结果。

python 中使用 return 关键字来退出函数,返回到函数被调用的地方继续往下执行。

return 可以将 0 个,1 个,多个函数运算完的结果返回给函数被调用处的变量。

函数可以没有返回值,也就是说函数中可以没有 return 语句,这时函数返回 None,例如上面我们定义的那些函数。

return 会将多个返回值以元组的形式返回。

案例:

定义一个函数接收 2 个或多个数值,并返回它们的和。

def add(x,y,*args):
    x += y
    for i in args:
        x += i
    return x

res = add(1,2)
print(res)

3
定义一个函数接收被除数 x 和除数 y,返回它们的商和余数。

def my_mod(x,y):
    res1 = None
    res2 = None
    if x < y:
        res1 = x
        res2 = 0
    else:
        i = 0
        while x >= y:
            x = x-y
            i += 1
        res1 = i
        res2 = x

    return res1, res2
res = my_mod(10,3)
print(res)

(3, 1)

函数的返回

Python 提供了 return 语句用于从函数中返回,当程序执行到 return 语句时,程序从函数中返回到调用函数的地方

实际栗子
# return
def test2():
    print('Before return')
    return
    # 这条语句不会被执行
    print('After return')


print('Before test')
test2()
print('After test')


# 输出结果
Before test
Before return
After test

如果用的是 pycharm,after return 这一行会提示 warning:This code is unreachable,这行代码是无法到达的

return 语句有两个常见用途
  • 提前退出函数
  • 返回具体的数据
提前退出函数
  • 通常情况下,函数执行到最后一条语句时退出函数的执行
  • 但某些情况下,可以通过 return 语句提前退出函数(像上面的栗子其实就是了)
提前退出函数的栗子
# return
def check(gender, age):
    if gender == 'female':
        return
    if age < 50:
        return

    print('We only process old man')
    print(gender)
    print(age)


print(check("male", 49))
print(check("female", 55))

check("male", 55)


# 输出结果
None
None

We only process old man
male
55

如果是提前退出函数,那么会返回 None

函数的返回值

return 语句可以携带参数,该参数作为函数的计算结果返回给调用方

return 返回值
return 一个返回值

求和函数

# return a
def test3(a, b):
    return a + b


print(test3(1, 2))


# 输出结果
3
return 多个返回值
# return a,b
def test4(a, b, c):
    if a > b:
        return a, c
    else:
        return b, c


print(test4(1, 2, 3))
print(test4(2, 1, 3))


# 输出结果
(2, 3)
(2, 3)

return 多个返回值,得到的是一个元组

return 语句是必须的吗?
  • 不是,函数可以不写 return 语句
  • 但变量赋值这个函数的时候,会得到一个 None
函数 + pass 语句

有时候只想先声明一个函数,但并不想这么快写代码块,怎么办呢

错误写法
def test():
    # 啥代码没有

会爆红

正确写法
def test():
    pass


print("调用函数:", test(), "hahaha")


# 输出结果
调用函数: None hahaha

Python 提供了 pass 语句,代表函数没有功能代码块

5. lambda

语法格式如下:

简单来说,lambda 函数用来定义简单的,能够在一行内表示的函数。
lambda arg1,arg2,... : expression
案例

f = lambda x,y : x + y
res = f(1,2)
print(res)

3
lambda 函数一般不会直接定义,通常是作为参数传递给其他函数作为参数使用。

为什么有 lambda 匿名函数

  • 在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便
  • Python 提供了 lambda 表达式对匿名函数提供支持

lambda 表达式的语法

lambda args: expression

expression 只允许是一条表达式,所以使用很受限

lambda 表达式小栗子

lambda x:x>2

等价函数写法

def select_positive(x):
    return x > 2

使用 lambda 表达式重写上面的将函数作为参数传递

def test(list, select_fun):
    for item in list:
        if select_fun(item):
            print(item)


list = [1, -1, 2, -2, 3, -3]

test(list, lambda x: x > 0)
test(list, lambda x: x < 0)


# 输出结果
1
2
3
-1
-2
-3
ls=[('多少才能健康',59),
    ('KOI',9),
    ('DKFVLCDASKV',90),
    ('二的非常',40)]

成绩的排序

ls.sort(key =lambda x:x[1])
print(ls)

[(‘KOI’, 9), (‘二的非常’, 40), (‘多少才能健康’, 59), (‘DKFVLCDASKV’, 90)]

6. 变量作用域

python 中一个变量能够被访问的范围叫做作用域。根据作用域的大小简单的分为全局变量和局部变量。

6.1 全局变量

python 是解释型编程语言,解释器在运行一个 python 程序时会在计算机内存中申请一块内存用来运行这个程序。全局变量在这块内存空间中都可以被访问和修改。

直接定义在函数外的变量就是全局变量,在程序运行的全过程有效。

6.2 局部变量

定义在函数里,的变量就是局部变量,它只在它定义的函数里起作用,一旦函数执行完毕它就不存在了。

案例

a = 1 # 全局变量

def fun():
    print(a)
fun()

1
上面的案例说明全局变量能够在函数里访问。

def fun():
    b = 2  # 局部变量
    print(b)

fun()
print(b)

2


# 输出
NameError Traceback (most recent call last)

in
4
5 fun()
----> 6 print(b)

NameError: name 'b' is not defined

上面的案例说明局部变量在函数外部不能直接访问

a = 1
def fun():

    a += 1  # 尝试直接在函数内部修改全局变量
    print(a)
fun()

# 输出
UnboundLocalError Traceback (most recent call last)

in
4 a += 1 # 尝试直接在函数内部修改全局变量
5 print(a)
----> 6 fun()

in fun()
2 def fun():
3
----> 4 a += 1 # 尝试直接在函数内部修改全局变量
5 print(a)
6 fun()

UnboundLocalError: local variable 'a' referenced before assignment

上面的案例说明在函数内部不能直接修改全局变量(不可变数据类型)

可变数据类型的修改不受影响,所以可变类型的全局变量在使用的过程中需要格外的注意

a = [1,2]
def func():
    a[0] = 2
    print(a)
func()
print(a)

[2, 2]
[2, 2]

6.2 global 关键字

有时候需要在函数内部修改全局变量。

使用 globals 关键字可以在函数内部修改全局变量

案例:

a = 1 # 全局变量

def fun():
    global a  # 申明 a 是全局变量
    a += 1
fun()
print(a)

2

7.python 内建函数

python 解释器提供了 70 多个内置函数。

import builtins
print(dir(builtins))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '**IPYTHON**', '**build_class**', '**debug**', '**doc**', '**import**', '**loader**', '**name**', '**package**', '**spec**', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

小写的就是全局内建函数和类

7.1 基本数据类型类

7.1.1 int

语法结构:
int([x]) -> integer    
int(x, base=10) -> integer

将一个数字或字符串转换成整数。
如果 x 不是一个数字,那么它必须是和 base 匹配的整数字符串表达式

  int(1.1)

1

  int('1')

1

  int('0b0101',2)

5

  int('0x11',16)

17

  int('0o11',8)

9

7.1.2 float

语法结构:float([*x*])

将一个字符串或数字转换为浮点数。

  float(123)

123.0

  float('1.2')

1.2

 float('-12345')

-12345.0

7.1.3 complex

语法结构:complex(real=0, imag=0)

将字符串或数字转换为复数。如果第一个形参是字符串,则它被解释为一个复数,并且函数调用时必须没有第二个形参。第二个形参不能是字符串。每个实参都可以是任意的数值类型(包括复数)

创建一个复数通过实部和虚部

complex(10,8)

(10+8j)

7.14 str

语法结构:str(object='')

通过给定的对象创建一个新的字符串对象。

  str(1)

‘1’

  str([1,2,3])

‘[1, 2, 3]’

  str({'name':'xinlan'})

“{‘name’: ‘xinlan’}”

7.15 list

语法结构:list(iterable=())

根据传入的可迭代对象创建一个列表,如果没有参数返回空列表

  list()

[]

  list(range(10))

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  list('abcde')

[‘a’, ‘b’, ‘c’, ‘d’, ‘e’]

7.16 tuple

语法结构: tuple(iterable=())

根据传入的可迭代对象创建一个元组,如果没有参数返回空元组

  tuple()

()

  tuple('abcd')

(‘a’, ‘b’, ‘c’, ‘d’)

7.17 set

语法结构: set(iterable)

根据传入的可迭代对象创建一个集合对象。

  set('abc')

  set(range(10))

7.18 dict

语法结构: 
dict(***kwarg*)
dict(*mapping*, ***kwarg*)
dict(*iterable*, ***kwarg*)

根据传入的参数创建一个字典对象

  # 形如(key, value)的键值对数据
dict([('name','xinlan'),('age',18)])

  # 关键字参数
dict(name='xinlan',age=18)

7.2 常用内建函数

7.2.1 print

语法结构: print(value,..,sep=' ', end='\n')   
  • value 会打印 value 的字符串形式
  • sep 分隔符,当有多个 value 时默认用空格作为分割
  • end 每次打印在最后默认添加回车换行符

打印传入对象的字符串形式

  print(1,2,3,sep=',')

1,2,3

print(1,end='')
print(2)

12

7.2.2 input

接收用户的输入数据,以字符串的形式返回。

可以接收字符串参数最为提示信息输出

  input('>>>:')
>>>: aaa
'aaa'

7.2.3 type

语法结构:type(object)

返回 object 的类型

  type(1)

int

7.2.4 dir

语法结构:([object])

返回传入对象的所有属性和方法名的列表

  print(dir(1))

[‘abs’, ‘add’, ‘and’, ‘bool’, ‘ceil’, ‘class’, ‘delattr’, ‘dir’, ‘divmod’, ‘doc’, ‘eq’, ‘float’, ‘floor’, ‘floordiv’, ‘format’, ‘ge’, ‘getattribute’, ‘getnewargs’, ‘gt’, ‘hash’, ‘index’, ‘init’, ‘init_subclass’, ‘int’, ‘invert’, ‘le’, ‘lshift’, ‘lt’, ‘mod’, ‘mul’, ‘ne’, ‘neg’, ‘new’, ‘or’, ‘pos’, ‘pow’, ‘radd’, ‘rand’, ‘rdivmod’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘rfloordiv’, ‘rlshift’, ‘rmod’, ‘rmul’, ‘ror’, ‘round’, ‘rpow’, ‘rrshift’, ‘rshift’, ‘rsub’, ‘rtruediv’, ‘rxor’, ‘setattr’, ‘sizeof’, ‘str’, ‘sub’, ‘subclasshook’, ‘truediv’, ‘trunc’, ‘xor’, ‘as_integer_ratio’, ‘bit_length’, ‘conjugate’, ‘denominator’, ‘from_bytes’, ‘imag’, ‘numerator’, ‘real’, ‘to_bytes’]

7.2.5 help

语法结构:help(builtins.object)

返回内建对象的帮助信息

  help(help)

Help on _Helper in module _sitebuiltins object:

class _Helper(builtins.object)
| Define the builtin ‘help’.
|
| This is a wrapper around pydoc.help that provides a helpful message
| when ‘help’ is typed at the Python interactive prompt.
|
| Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object ‘thing’.
|
| Methods defined here:
|
| call(self, *args, **kwds)
| Call self as a function.
|
| repr(self)
| Return repr(self).

Data descriptors defined here:
dict
dictionary for instance variables (if defined)
weakref
list of weak references to the object (if defined)

7.2.6 len

返回对象的长度(元素个数)。实参可以是序列(如 string、bytes、tuple、list 或 range 等)或集合(如 dictionary、set 或 frozen set 等)。

语法结构:len(obj)

返回容器的元素个数

  len([1,2,3])

3

7.2.7 hash

语法结构: hash(obj)

返回对象的 hash 值

  hash('a')

3636161774609400683

7.2.8 iter

语法结构:iter(iterable)

根据传入的可迭代对象返回一个迭代器

  iter('abcd')

<str_iterator at 0x7f98b7dd2eb0>

7.2.9 id

语法结构:id(obj)

返回传入对象的身份 id(虚拟内存地址的整数形式)

  id(1)

4344134656

7.2.10 range

range 实际上是一个不可变的序列类型

语法结构:
range(stop) -> range object
range(start, stop[,step])

返回一个 range object 对象,产生整数序列

  range(10)

range(0, 10)

  range(0,10,2)

range(0, 10, 2)

7.2.11 map()

map() 函数语法:map(function, iterable, ...)
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

>>> def square(x) :         # 计算平方数
...     return x ** 2
...
>>> map(square, [1,2,3,4,5])    # 计算列表各个元素的平方
<map object at 0x100d3d550>     # 返回迭代器
>>> list(map(square, [1,2,3,4,5]))   # 使用 list() 转换为列表
[1, 4, 9, 16, 25]
>>> list(map(lambda x: x ** 2, [1, 2, 3, 4, 5]))   # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
>>>

7.2.12 enumerate()

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标。
也就是说,对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值。
语法

enumerate(sequence[,startindex=0])

参数

  • sequence :一个序列、迭代器或其他支持迭代对象。
  • start :下标起始位置。
    举例:
a = [10, 30, 50, 70]
for i, j in enumerate(a):
    print(i, j)
代码运行结果为:

0 10
1 30
2 50
3 70