第五章 函数

5.1 三元运算

  • 又称为三目运算

和运算符相关

val = v if v else 666
val = v or 666 # 源码中会见到

Note:为了赋值

# 简单条件赋值时使用
v = 前面 if 条件 else 后面
# 用户输入,如果是整数,则转换,否则赋值为None
data = input('>>>')
value = int(data) if data.isdecimal() else None

5.2 函数基础

面向过程【可读性差、可重用性差】—> 函数式编程—>面向对象

# 如果给其他人发送邮件,可以把发送程序进行封装起来,可缩减代码长度和提高重复利用性。

函数式编程

  • 将n行代码放在别处,并取别名,以后可以调用
  • 场景:
    • 代码重复执行
    • 代码量特别多,超过一屏,可以选择函数编程(一般控制在一屏以内

1. 定义函数

可以定义一个由自己想要功能的函数,以下是简单的规则:(5)

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始并且缩进
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
def functionname( parameters ):   
  "函数_文档字符串"
  function_suite  # 函数体  
	return [expression]
# 默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
# 函数定义
# way1
def 函数名():
  	# 函数体
    pass
# 函数的执行
函数名()    # 会自动执行

# way2 
# 形参可以是多个
def 函数名(形参):
  	# 函数体
    pass
函数名(实参)

Note1(1)

  • None方法类似函数,但不是(方法操作是s.upper(),方式,而函数是直接调用,len(),open())

2. 两种参数(示例)

形参(形式参数)与实参(实际参数)的位置关系。

def 函数名(形参):
  	# 函数体
    pass
函数名(实参)
# 无形参示例
def get_sum_list()
	sum = 0
  for i in li:
    sum += i
print(get_sum_list())
# 有形参示例
# 请写一个函数,函数计算列表 info = [11,22,33,44,55] 中所有元素的和。
info = [11, 22, 33, 44]
def get_list_sum(li):
    sum = 0
    for i in li:
        sum += i
    print(sum)
get_list_sum(info)

3. 函数的返回值

Note2(4)

  1. return [表达式] 结束函数,选择性地返回一个值给调用方(func()为返回值)。
  2. return 1, 2 ,3 会返回tuple:(1, 2, 3)
  3. 函数默认返回值是 None ,有时可以使用其作为flag
  4. 可变类型(list)的基本上都是None, 不可变(str)基本上会返回新值
def func(arg):
  	return 9 # 返回值为9,默认为None,可以返回任何类型的数据
val = def func(v)
# 示例2
# 让用户输入一段字符串,计算字符串中有多少A,就在文件中写入多少‘echo’
def get_char_count(arg):
  	count = 0
    for i in arg:
      	count += 1

def write_file(data):
  	open('a.txt', mode='w', encoding='utf-8') as v:
        if len(data) == 0:或者 if not bool(data):
            return '写入失败'
				v.write(data)
        return '写入成功'
  	
print(count)
content = input()

4. 函数的四种方式

# way1 无形参,无return
def fun1():
  	pass
fun()
# way2 有形参,无return
def fun2(arg):
  	pass
fun2(v)
# way3 无形参,有return(指定值)
def fun3():
  	pass
  	return 9
val = fun3(v)
# way4 有形参,有return(变量)
def fun4(arg1, arg2):
  	pass
  	return arg1 + arg2
val = fun4(v1 + v2)

5. 练习(3)

# 1. 写函数,计算一个list中有多少个数字,打印,有%s个数字
# 判断数字:type(a) == int
# 2. 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。
# 3. 读取文件,将文件的内容构造成指定格式的数据,并返回。
a.log文件
    alex|123|18
    eric|uiuf|19
    ...
目标结构:
a. ["alex|123|18","eric|uiuf|19"] 并返回。
b. [['alex','123','18'],['eric','uiuf','19']]
c. [
	{'name':'alex','pwd':'123','age':'18'},
	{'name':'eric','pwd':'uiuf','age':'19'},
]

5.3 变量作用域&嵌套

1. 函数传参方式(2+1)

  • 参数传递方式分为位置传参、关键字传参、函数作为参数进行传递

  • 位置传参

    • 严格按照位置进行传参
# 示例
def func(a1, a2):
  pass

func(1, 3)
func(1, [1, 2, 3])
  • 关键字传参
# 示例
def func(a1, a2):
	pass

func(a1 = 1, a2 = [1, 2, 3])

func(a1 = 1, 2 )     # 此时会报顺序错误

Note3(1)

  1. 关键字传参可以和位置传参混合使用,但 位置参数 必须在 关键字传参

2. 函数定义参数(3)

  • 函数定义中,def func() 括号中可以省略默认参数和 *args/**kwargs。

1. 省略参数

# 示例
def func():
	pass

2. 默认参数

  • 注意默认参数一定要在位置参数之后
  • 在定义默认参数时,慎用可变类型变量
# 示例 
def func(a1, a2=2):
	pass
# 调用方法,有默认参数时,可以不用省略,采取默认值,也可以重新赋值
func(1)
func(1, 3)
# 默认形参时,如果默认是可变类型的需要谨慎使用
# 如果想要给values设置默认是空list
def func(data, value=[]):
  pass
# 推荐
def func(data, value=None):
  if not value:    
    valu=[]

3. *args/**kwargs(万能参数)

  • *args 表示接收所有由实参通过位置传参方式,传递过来的数据,可以和位置参数一起使用。
  • 接收到的参数值,会通过循环加入tuple
# 示例 : 可以传递任意类型数据
def func(*args):
	pass

# [1, 2, 3]会被当成整体变成tuple中的一个元素
func(1, 2, 3, [1, 2 ,3])
# 直接赋值, [1, 2, 3]也会循环取出追加到tuple中
func(4, 5 ,6 ,*[1, 2 ,3])
  • **kwargs 表示接收所有关键字传参的数据,也可以通过**{'k1': 1, 'k2':2},循环取出keys对,加入形参dict中
# 示例 :只能通过关键字传参,或者dict赋值
def func(**kwargs):
    print(kwargs)

# [1, 2, 3]会被当成整体变成dict中 'd': [1, 2, 3]
func(a=1, b=2, c=3, d=[1, 2 ,3])
# 直接赋值, {'k1': 4, 'k2': 5}也会循环取出追加到形参的dict中
func(a=1, b=2, c=3, d=[1, 2, 3], **{'k1': 4, 'k2': 5})

Note4(4)

  1. 形参中的默认参数,也可以使用位置传参方式
  2. 传参时,有*(**)时,会直接赋值 (循环加入) 给形参
  3. 不带* / **的实参,会转换为tuple / dict
  4. 传入的数据都是循环加入tuple / dict中

3. 作用域&函数嵌套

  • 变量作用域时是变量的有效作用范围,在python中函数就是一个局部作用域。由于作用域的不同,变量的有效范围也不同,根据作用范围可以把变量分为,全局变量和局部变量。
  • 全局变量:可供任何函数进行使用,修改,在python文件第一层的变量。在python中一般把全局变量命名为全部大写(规范),例如:USRE_NAME = 'henry'。
  • 局部变量:可以把函数中的变量视为局部变量。函数体中变量为函数所私有(只能被其子函数进行使用)。
# 示例1
a	= 'henry'
def func():
  print(a)
a = 123
func()   # 此时使用的是全局变量, 结果是 123

# 示例2
a = 'henry'
def func1():
    def func2():
     		a = 'echo'
        print(a)
    func2()
    print(a)

a = 123
func1()
print(a)
# echo 123 123

Note5(4)

  1. python文件就是一个全局作用域
  2. 函数是一个 (局部) 作用域
  3. 局部作用域中的数据归自己私有
  4. 作用域中查找数据规则
    • 优先查找自己作用域,自己没有,去父籍作用域查找直到找到全局作用域
    • 查找不到会报错,默认只能使用父籍作用域中的变量值不能赋值(可变类型可以修改
# 示例
# 对于可变变量可以进行修改
a = [1, 3, 5, 7]
def fun1():
  	a.append('henry')
fun1()
print(a)     # 此时a会被修改
# 两种赋值的方法
# 可以使用 global 关键字对全局变量进行重新赋值
global name
name = 'alex'  # 给全局变量重新赋值

# 可以使用 nolocal 关键字对父籍变量进行重新赋值, 在父籍找不到时,会报错
nonlocal name 
name = 'alex'  # 给父籍变量重新赋值

Note6(3)

  1. 对于可变变量可以进行修改
  2. global 关键字对全局变量进行重新赋值
  3. nolocal 关键字对父籍变量进行重新赋值, 在父籍找不到会报错

5.4 函数进阶

  • 高阶函数(3)
    1. 对函数赋值
    2. 函数当作参数传递
    3. 把函数当作返回值
# <class 'function'>
def func ():
  pass
print(type(func))
# 函数可以认为是一变量

1. 函数赋值

def func():
  print(123)
v = fun # 指向相同的地址
v()
# 示例
def func():
  print(123)
v1 = [func, func, func]
v2 = [func(), func(), func()]
print(v1)
print(v2)

2. 函数传参

def func(arg):
  print(arg)
def show():
  return 999

func(show)   # 999 None

3. 函数作为返回值

def func():
  print(1,2,3)
def bar():
  return func
v = bar()  # func
v()

Note7(3)

  1. 注意funcfunc() 的区别
  2. 函数(实际是内存地址)可以放入set()中(不常用), 或dict中(一般用于values,也可以放在key中但不常用)
  3. 函数一旦定义,只要进行加载,就是不可变,可 hash
# 10 个函数, 一般是建立字典
def func():
  print('话费查询')
def bar():
  print('***')
def base():
  print('***')

info = {
    'f1': func,
    'f2': bar,
    'f3': base
  }
choice = input('please input your choice: ')
name = info.get('choice')
 if not name:
  	print('输入不存在')
 else:
		name()

3. lambda表达式

# 三目运算,为了解决简单的if...esle的情况
# lambda,为了解决简单函数的情况
eg:
def func(a1, a2):
  return a1 + a2
# 可以改写为,a1 + 100 即为return 值
func = lambda a1, a2: a1 + 100
# way1 直接使用
func = lambda : 100
func = lambda a: a*10
func = lambda *args, **kwargs: len(args) + len(kwargs)
# way2 使用全局变量
DATA = 100
func = lambda a: a + DATA
func(1)
# way3 使用父籍变量
DATA = 100
def func():
  DATA = 1000
  func1 = lambda a: a + DATA
  v = func1(1)
  print(v)
func()
# way4 使用条件判断 ########
func = lambda n1, n2: n1 if n1 > n2 else n2
# 练习1
USER_LIST = []
func1 = lambda x: USER_LIST.append(x)
v1 = func1('alex')
print(v1)			# None
print(USER_LIST) # ['alex']

# 练习2
func1 = lambda x: x.strip()
v1 = func1('   alex')
print(v1)			# 'alex'

# 练习3
func_list = [lambda x: x.strip(), lambda y: y+100, lambda x,y: x+y]
v1 = func_list[0]('   alex')
print(v1)			# 'alex'

Note8(2)

  1. 用于表示简单函数(一行解决的函数)。
  2. lambda 表达式会默认返回冒号:之后的值

4. 内置函数(30)

  • 自定义函数

  • 内置函数(31)

    1. 强制转换(7):int(),str, bool, list,dict,tuple,set
    2. 输入输出(2):print, input
    3. 其他(5):type, id, range, open, len
    4. 数学(7)
      • abs,round,float(int(55.5)保留整数部分)
      • max,min,sum,
      • divmod(两数相除,得商和余数, 两个值)
  1. 面向对象相关(4):dir,super,issubclass,isinstance
# divmod. 练习
USER_LIST = []
for i in range(1, 836):
  tem = {name':'hello-%s' % i, 'email':'XXXX%s@qq.com' %s}
  USER_LIST.append(tem)
"""
	要求:
		每页展示10条
		根据用户输入的页码,查看
"""
  1. 进制转换(3):bin(0b,int<—>bin),oct(0o,int<—>oct),int(其他进制转int),hex(0x,int<—>hex)

     # base 默认为 10
      v1 = '0b1101'
      result = int(v1, base = 2)
      # 转8进制
      v1 = '0o1101'
      result = int(v1, base = 8)
      # 转16进制
      v1 = '0x1101'
      result = int(v1, base = 16)
    
      # ip 点分二进制,将十进制转为二进制并通过 . 连接ip = '192.168.12.79'
      ip = '192.168.12.79'
      li = ip.split('.')
      l = []
      for i in li:
          i = int(i)
          i = bin(i)
          i = str(i).replace('0b', '')
          i = i.rjust(8, '0')
          l.append(i)
      s = '.'.join(l)
      print(s)
    
  2. 编码相关

  • chr() :把int型数据,转换为unicode编码

    • ord():把unicode转换为字符
    # 生成验证码
    import random	# 导入一个模块
    def get_random_data(length=6):
      data = []
      for i in range(length):
          v = random.randint(65,90) # 得到一个随机数
          data.append(v)
    	return ' '.join(data)
      
    code = get_random_data()
    

print(code)


8. map / filter / reduce(py2)/zip

- **map**,循环每个元素(第二个参数),然后让元素执行函数(第一个参数),将每个函数结果保存到新的list中,并返回。(批量修改数据)

```python
# map操作的 func 是一个函数 v 必须是可迭代,
v = [11, 22, 33]
def func(arg):
  return arg + 100 
result = map(func, v) # 将函数的返回值添加到空list中[111, 122, 133]
print(list(result))
# 使用lambda 改写
result = map(lambda x: x+100, v)
  print(result)		# py2直接返回
print(list(resutl)) # py3会返回一个object,可用list()查看
  • filter
```python
# 结果为True的时候,才返回数据

v = [1, 2, 3, 'welcome', 4, 'hello']
result = filter(lambda x: type(x) == int, v) # 生成新list
print(list(result))
```

  • reduce
import functools
v = [1, 2, 3, 4]
result = functools.reduce(lambda x,y: x*y, v)
print(result)
  • zip
  a = [1,2,3]
  b = [4,5,6]
  c = [4,5,6,7,8]
  zipped = zip(a,b)     # 打包为元组的列表
  [(1, 4), (2, 5), (3, 6)]
  zip(a,c)             
  # 元素个数与最短的列表一致
  [(1, 4), (2, 5), (3, 6)]
  zip(*zipped)          
  # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
  [(1, 2, 3), (4, 5, 6)]  

5.5 函数闭包

1. 函数闭包

def func(name):
  def inner():
    print(name)
  return inner

v1 = func('henry')
v1()
v2 = func('echo')
v2()
# 不是闭包
def func(name):
  def inner():
    return 123
  return inner

# 闭包:封装值 + 内层函数需要使用
def func(name):
  def inner():
    print(name)
    return 123
  return inner 

Note9(5)

  1. 闭包,为函数创建一块区域(内部变量供自己使用),为以后执行提供数据;
  2. 闭包是能够读取其他函数内部变量的函数。
  3. 执行完毕+内部数据不被其他程序使用会被销毁
  4. 应用:装饰器,SQLAlchemy源码
  5. 由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)

2. 递归(效率较低)

  • 递归限制为1000次
def func(i):
  print(i)
  func(i+1)
# 斐波那契数列
def func(a, b):
  print(b)
  func(a, a+b)
# 递归
def fun(a):
  if a == 5:
    return 100
  result = func(a+1) + 10
  return result
v = func(1)

# 注意
def fun(a):
  	if a == 5:
    		return 100
  	result = func(a+1) + 10

v = func(1)

5.6 装饰器和推导式

  • 使用func.__name__获取被调用的func函数名,func为形参

1. 装饰器(重点)

def func():
  def inner():
    pass 
 	return inner

v = func()
print(v)   # inner 函数
# ##############################
def func(arg):
  def inner():
    print(arg) 
 	return inner

v1 = func(1)   # 1
v2 = func(2)   # 2
# ##############################
def func(arg):
  def inner():
    arg()
 	return inner

def f1():
  print(123)
  
v = fucn(f1)
v()		# 123
# ##############################
def func(arg):
    def inner():
        arg()
return inner
def f1():
    print(123)
return 666
v1 = func(f1)
result = v1() 
# 执行inner函数 / f1含函数 -> 123 print(result) 	
# None

# ##############################
def func(arg):
    def inner():
        return arg()
return inner
def f1():
    print(123)
return 666
v1 = func(f1)
result = v1()   # 123 666
  • 装饰器示例
def func(arg):
  def inner():
		print('before')
    v = arg()
    print('after')
    return v
  return inner

def index():
  print('123')
  return 666

# 示例
v1 = index()   # 123

v2 = func(index)  # before 123 after
v3 = v2()

v4 = func(index)   # before 123 after
index = v4
index()

index = func(index)  # before 123 after
index()
# 第一步,执行func函数,并将下面的函数当作函数传递,相当于func(index)
# 第二部,将func返回值,重新赋值为下面的函数名,index = func(index)
def func(arg):
    def inner():
        return arg()
    return inner

@func
def index():
    print(123)
    return 666

print(index)  # <function func.<locals>.inner at 0x1054a16a8>

应用示例

# 计算函数执行时间
def wrapper(func):
  	def inner():
      	start_time = time.time()
				func()
				end_time = time.time()
				print(end_time - start_time)
        return func()
      return inner

import time
 @ warpper   
def func():
    time.sleep(2)
  	print(123)
  
 @ warpper   
def func():
    time.sleep(1.5)
  	print(123)

# 判断用户是否登陆

Note10(2)

  1. 目的:在在不改变原函数的基础上,在执行函数前后自定义一些操作
  2. 场景:想要为函数扩展功能时
  • 编写装饰器
# 装饰器的编写(示例)
def wrapper(func):		# 必须有一个参数
  def inner():
    ret = func()
    return ret
 	return inner
# 应用 index = wrapper(index)
@wapper
def index():
  pass
@wapper
def manage():
  pass 
# 在执行函数,自动触发装饰器
v = index()
print(v)
# 导入本目录下的其他py文件
import a
a.f1()
a.f2()
a.f3()
  • 编写格式
def wrapper(func):
  	def inner(*args, **kwargs):
		return func(*args, **kwargs)
  	return inner

为什么要加*args,**kwargs?

2. 关于参数

# 让参数统一的目的:为装饰的函数传参
def x(func):
  def inner(a, b):
    return func()
  return inner

@x
def index():
  pass

index(1, 2)
  • 返回值
# 装饰器建议写法
def wrapper(function):
  	def inner(*args, **kwargs):
        v = funtion(*args, **kwargs)
        return v
  	return inner

@wrapper
def func():
	pass
  • 带参数的装饰器
# 第一步:v = wrapper(9)
# 第二步:ret = v(index)
# 第三步:index = ret
def x(counter):
    def wrapper(function):
      	def inner(*args, **kwargs):
        	v = funtion(*args, **kwargs)
        	return v
      	return inner
     return wrapper

@x(9)
def index():
  	pass		
# 示例:
# 写一个带参数的装饰器,实现,参数是多少,被装饰器就要执行多少次,最终返回一个list
def x(*args):
  def wrapper():
    def inner():
      li = [index() for i in range(args[0])]
      return li
    return inner
  return wrapper

@x(9)
def index():
  return 8

v = index()
print(v)
  • 元数据
  • 多个装饰器:@x1 @x2

3. 推导式

  1. list推导式(生成式)

    • 格式(生成一个list)
    vals = [i for i in 'henry']
    v = [i for i in 可迭代对象 if 条件]  # 满足条件生成list
    v = [i if i > 5 else i+1 for i in 可迭代对象 if 条件]  
    # 满足条件生成list
    
    # 新浪
    def num():
      	return [lambda x: x * i for i in range(4)]
    print([m(2) for m in num()])
    
  2. set推导式

    • 格式
    # 满足条件生成set,会去重,条件判断可以省略
    v = {i for i in 可迭代对象 if 条件} 
    
  3. dict推导式

    • 格式
    # 满足条件生成dict,但需要key值和冒号:,条件判断可以省略
    v = { 'k' + str(i): i for i in 可迭代对象 if 条件}
    

5.7 迭代器&生成器

:int ,str, list…. / bytes(b'xxx'), datetime

对象:由创建的数据

类和对象

1. 迭代器(class:iterator)

  • 展示list中所有数据

    1. 迭代器:对某种(str/list/tuple/dict/set) (序列)对象中的元素,进行逐个获取。
  1. 表象:具有__next__()方法,
  • list —> 迭代器:

    • v = iter([1, 2, 3, 4])
    • val = [1, 2, 3, 4].__iter__()
  • 迭代器获取每一个元素:v.next

  • 直到报错:StopIteration,表示迭代终止

    v = [1, 2, 3, 4]
    val = iter(v)
    value = val.__next__()
    print(value)
    
  • 甄别:数据中是否包含__next__()方法

    • for循环的内部,首先把数据转化为iter,反复执行iter.__next__(),取完不报错

2. 可迭代对象

  • 具有__iter__()方法,必须返回一个迭代器(生成器)
  • for循环

3. 生成器(函数的变异)(class:generator)

  • yiled可以保存状态,yield的状态保存与操作系统的保存线程状态很像,但是yield是代码级别控制的,更轻量级
  • send可以把一个函数的结果传给另外一个函数,以此实现单线程内程序之间的切换
  1. 生成器基础
def func():
  pass 
func()
# 生成器函数(内部是否包含yield)
def func(arg):
  arg = arg + 1
  yield 1
  yield 2
  yield 100
# 函数内部代码不执行,返回一个生成器
val = func(100) 

# 生成器:可以被for循环的,一旦开始循环,函数内部代码就开始执行
for i in val:
  print(i)
# 遇到第一个yield会把后面的值赋值给 i
# 如果 yield 已经执行完毕,则意味着for循环结束
# 边使用边执行
def func():
  count = 1 
  while True:
  	yield count
    count += 1

# v 只取yield值,是一个生成器对象
v = func()
for i in v:
  print(i)
  
# 查看v中有哪些方法
dir(v)

Note11(4)

  1. 函数中如果存在yield,则该函数为生成器函数,调用生成器函数会返回一个生成器
  2. 只有被for循环时,生成器内部代码才会执行,每次循环都会获取yield的返回值
  3. 即使函数内部的yield函数永远执行不到,也是生成器
  4. 生成器也是一种特殊的迭代器,也是一个可迭代对象
class Foo(object):
  def __iter__(self):
    return iter([1, 2, 3])
  	yield 1 
    yield 2
    
obj = Foo(object)
  1. 生成器中send

Note12(2)

  1. send方法,会触发一次next操作,yiled结果为其返回值
  2. 总的来说,send方法和next方法唯一的区别是在执行send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现与生成器方法的交互。
  3. 需要注意,在一个生成器对象没有执行next方法之前,由于没有yield语句被挂起,所以执行send方法会报错
def func():
    print(123)
    n = yield('aaa')
    print('----->', n)
    yield 'bbb'

data = func()
next(data)
v = data.send('太厉害了,直接传进去了')
print(v)
  1. 生成器示例
# 示例:读取文件
def func():
    curse = 0
    while True:
        f = open('db','r','utf-8')
        f.seek(curse)
        data_list = []
      	for i in range(10):
        	line = f.readline()
            if not line:
              	return
            data_list.append(line)
        curse = f.tell()
        f.close
        for row in data_list:
          	yield row
# redis 示例
import redis
coon = redis.Redis(host='192.168.12.12')
  1. yield from 关键字
# yield from (py3.3之后)
def base():
  yield 88
  yield 99
 
def bar():
  return 123

def func():
  yield 1
  yield from base()
  yield from bar()   # 报错,int 不可迭代,如果可迭代,则循环取出
  yield 2
  yield 
  1. 生成器推导式
v1 = [i for i in range(10)] # list推导式,立即产生数据
def func():
  for i in range(10):
    yield i
v2 = func()  # 与下面v2相同
v2 = (i for i in range(10)) # 生成器推导式,不会立即产生数据
  1. 酸爽生成器

    • 所有生成器取一次就没有了

    • 不取不会执行,惰性运算

# 示例1
ret = filter(lambda n: n%3==0, range(10))
print(len(list(ret)))				# 4
print(len(list(ret)))				# 0
# 示例2
def add(n, i):
  return n + i

def test():
  for i in range(4):
    yield i
    
g = test()
for n in [1, 10]:
  g = (add(n, i) for i in g)
  
print(list(g))
# [20 21 22 23 24]
# 示例3
def add(n, i):
  return n + i

def test():
  for i in range(4):
    yield i
    
g = test()
for n in [1, 10, 5]:
  g = (add(n, i) for i in g)
  
print(list(g))
# [15, 16, 17, 18]

5.8 异常处理

1. 示例

# 示例1
try:
  val = input('请输入数字:')
  num = int(val)
except Exception as e:
  print('操作异常')
# 示例2
import requests
try:
  ret = requests.get('http://www.baidu.com')
	print(ret.text)
except Exception as e:
  print('请求异常')
# 示例3
def func(a):
  try:
    return a.strip()
  except Exception as e:
    pass
  return False

v = func([1, 2, 3])
print(v)
# 练习1,函数接收一个list将list中的元素每个都加100
def func(arg):
    li = []
    for items in arg:
        if items.isdecimal():
            li.append(int(items) + 100)
     return li
# 写函数,接收一个list, 中全是url 访问地址,并获取结果
import requests
def	func(url_list):
  li = []
  try:
    for i in url_list:
      reponse = requests.get(i)
      li.append(reponse.text)
  except Exception as e:
    pass
  return li

func(['http://www.baidu.com', 'http://www.google.com', 'http://www.bing.com'])
# 比较异常 try 的位置不同,效果也不同
import requests
def	func(url_list):
  li = []
  for i in url_list:
      try:
          reponse = requests.get(i)
          li.append(reponse.text)
  		except Exception as e:
    			pass
  return li

func(['http://www.baidu.com', 'http://www.google.com', 'http://www.bing.com'])


# 得到的结果是text格式的文本文档
reponse = requests.get('url', useragent:xxxxxx)

2. 基本格式

try:
  pass
except ValueError as e:
  pass
except IndexErro as e:
  pass
except Exception as e:
  print(e)
finally: 
  print('final')  # 无论对错都要执行的代码
# e 代表异常信息,是Exception类的对象,有一个错误信息
try:
  int('asdf')
except Exception as e:
  print(e)

try:
  int('asdf')
except ValueError as e:
  print(e)
  
try:
  int('asdf')
except IndexError as e:
  print(e)
  
# 即使遇到return 也会执行finally 
def func():
  try:
    int('1')
    return
  except Exception as e:
    print(e)
  finally:
    print('final')

3. 主动触发异常

try:
  int('123')
  raise Exception('错误信息')   # 主动抛出异常
except Exception as e:
  print(1)
# 打开一个文件,
def func():
  resutl = True
  try:
      with open('x.log', mode='r', encoding='utf-8') as f:
        	data = f.read()
      if 'henry' not in data:
        	raise Exception()
   except Exception as e:
     	result = False 
   return result

4. 自定义异常

# 示例1
class MyException(Exception):
  pass
try:
  raise MyException('haha,错了吧')
except MyException as e:
  print(e)
class MyException(Exception):
  def __init__(self, message):
      self.message = message
try:
  raise MyExceptoin('123')
except MyException as e:
  print(e.message)
posted @ 2019-10-15 21:57  RunningForever  阅读(106)  评论(0编辑  收藏  举报