Python函数

3.1 函数本质及应用场景

截止目前:面向过程编程(可读性差、可重用性差)

对于函数编程:

  1. 本质:将N行代码拿到别处并给他们起一个名字,方便以后通过名字就可以找到这段代码,并执行相关功能

  2. 应用场景:

    • 代码重复执行
    • 代码特别多,超过一屏,可以选择通过函数进行代码分割
  3. 面向过程编程:

    # 面向过程编程 
    user_input = input('请输入角色:')
    
    if user_input == '管理员':    
        import smtplib    
        from email.mime.text import MIMEText    
        from email.utils import formataddr
        msg = MIMEText('管理员,我想演男一号,你想怎么着都行。', 'plain', 'utf-8')    
        msg['From'] = formataddr(["李邵奇", '15776556369@163.com'])    
        msg['To'] = formataddr(["管理员", '344522251@qq.com'])    
        msg['Subject'] = "亲爱的管理员"
        
     	server = smtplib.SMTP("smtp.163.com", 25)    		
        server.login("15776556369@163.com", "qq1105400511")   	     
        server.sendmail('15776556369@163.com', ['管理员', ], msg.as_string())
        server.quit() 
        
    elif user_input == '业务员':    
        import smtplib    
        from email.mime.text import MIMEText    
        from email.utils import formataddr
        msg = MIMEText('业务员,我想演男一号,你想怎么着都行。', 'plain', 'utf-8')    
        msg['From'] = formataddr(["李邵奇", '15776556369@163.com'])    
        msg['To'] = formataddr(["业务员", '业务员'])    
        msg['Subject'] = "亲爱的业务员"
        
    	server = smtplib.SMTP("smtp.163.com", 25)    
        server.login("15776556369@163.com", "qq1105400511")   
        server.sendmail('15776556369@163.com', ['业务员', ], msg.as_string())    
        server.quit() 
        
    elif user_input == '老板':    
        import smtplib    
        from email.mime.text import MIMEText    
        from email.utils import formataddr
        
        msg = MIMEText('老板,我想演男一号,你想怎么着都行。', 'plain', 'utf-8')    
        msg['From'] = formataddr(["李邵奇", '15776556369@163.com'])    
        msg['To'] = formataddr(["老板", '老板邮箱'])    
        msg['Subject'] = "亲爱的老板"
        
    	server = smtplib.SMTP("smtp.163.com", 25)    
        server.login("15776556369@163.com", "qq1105400511")    
        server.sendmail('15776556369@163.com', ['老板邮箱', ], msg.as_string())    
        server.quit()
    
  4. 函数是编程:

    def send_email():    
        import smtplib    
        from email.mime.text import MIMEText    
        from email.utils import formataddr
        
        msg = MIMEText('老板,我想演男一号,你想怎么着都行。', 'plain', 'utf-8')    
        msg['From'] = formataddr(["李邵奇", '15776556369@163.com'])    
        msg['To'] = formataddr(["老板", '老板邮箱'])    
        msg['Subject'] = "情爱的老板"
        
        server = smtplib.SMTP("smtp.163.com", 25)    
        server.login("15776556369@163.com", "qq1105400511")    
        server.sendmail('15776556369@163.com', ['老板邮箱', ], msg.as_string())
        server.quit()
    
    user_input = input('请输入角色:')
    if user_input == '管理员':    
        send_email() 
    elif user_input == '业务员':    
        send_email() 
    elif user_input == '老板':    
        send_email()
    

3.2 函数定义(简单函数)

3.2.1 基本定义函数

  1. 基本形式

    def 函数名():       #函数的定义
        代码            #函数内容
        
    函数名()            #函数的执行
    
  2. 注意

    • 函数如果不被调用,则内部代码永远不会被执行
    • len(计算长度)是python内部写好的一个函数

3.2.2 参数(个数不限制)

3.2.2.1 基本参数知识

def get_list_date(aaa):       #aaa:形式参数(形参)  任意个数
	v = [11,22,33,44]
	print(v[aaa])
    
get_list_date(1)             #1:实际参数(实参)   任意类型
  • 发送邮件问题

    # 假如:管理员/业务员/老板用的是同一个邮箱。 
    def send_email(to):    
        import smtplib    
        from email.mime.text import MIMEText    
        from email.utils import formataddr
        
        msg = MIMEText('导演,我想演男一号,你想怎么着都行。', 'plain', 'utf-8')    
        msg['From'] = formataddr(["李邵奇", '15776556369@163.com'])    
        msg['To'] = formataddr(["导演", to])    
        msg['Subject'] = "情爱的导演"
        
        server = smtplib.SMTP("smtp.163.com", 25)    
        server.login("15776556369@163.com", "qq1105400511")  
        server.sendmail('15776556369@163.com', [to, ], msg.as_string())    
        server.quit() 
    
    def send_email(to):    
        template = "要给%s发送邮件" %(to,)    
        print(template)
     
    user_input = input('请输入角色:')
    if user_input == '管理员':    
        send_email('xxxx@qq.com') 
    elif user_input == '业务员':    
        send_email('xxxxo@qq.com') 
    elif user_input == '老板':    
        send_email('xoxox@qq.com')
    

3.2.2.2 位置传参

  1. 传参:调用函数并传入参数

  2. 要求:严格按照位置进行传参

  3. 位置要求:positional argsument

  4. 基本形式:

    def func(a,b):
        print(a,b)
        
    func(11,22)               #位置都是一一对应的,a = 11,b = 22
    

     

3.2.2.3 关键字传参

  1. 关键字参数:keyword argsument
  2. 基本形式
def func(a,b):
    print(a,b)
    
func(b = 11,a = 22)        #按照关键字进行传参,可以交换位置
  1. 注意:open(打开文件)是python内部写好的一个函数,运用的就是关键字传参

  2. 关键字传参和位置传参可以混合使用

    • 位置参数必须在关键字参数的前面
    • 位置参数的个数 + 关键字参数个数 = 总参数个数
    • 一个参数不能传入多次

3.2.2.4 默认参数:可传可不传

  1. 基本形式

    def func(a,b = 9):          #b就是默认参数,默认值为9
    #func函数接受两个参数,调用函数进行传值时,默认参数可传可不传,不传则使用默认值,传则使用传的值
        print(a,b)
    
    func(123)                   #a = 123,b使用默认值,即b = 9
    func(11,22)                 #a = 11,b = 22
    
  2. 对于默认值,如果是可变类型(对于函数的默认值慎用可变类型)

    # 如果要想给value设置默认是空列表
    
    # 不推荐(坑)
    def func(data,value=[]): 
        pass 
    
    # 推荐
    def func(data,value=None):
        if not value:
            value = []
    
  3. 面试题

    def func(a,b=[]):
        b.append(a)
        return b
    
    l1 = func(1)
    l2 = func(2,[11,22])
    l3 = func(3)
    
    print(l1,l2,l3)
    # [1,3]   [11,22,2]   [1,3]
    

3.2.2.5 万能参数(*args,**kwargs)

  1. *args

    • 可以接受人以个数的位置参数,并将参数转化为元组(注意实参里面有和没有*的区别)

    • 只能使用位置传参

    • 基本参数

      def func(*args):
          print(args)
          
      func(1,2)                #args = (1,2)
      func((11,22,33))         #args = ((11,22,33),)    
      func(*(11,22,33))        #args = (11,22,33)       循环元组里的元素,加入到元组中
      func(*[11,22,33,44])     #args = (11,22,33,44)    循环列表里的元素,加入到元组中
      #注意实参里有*和没有的区别
      
      #特殊情况:
      def func(a,*args,b):     #a只能使用位置参数,b只能使用关键字参数
          print(a,args,b)
          
      func(1,2,3,4,b = 5)      #a = 1,args = (2,3,4),b = 5  
      
  2. **kwargs

    • 可以接受任意个数的关键字参数,并将参数转化为字典(注意实参里面有**和没有的区别)

    • 只能接受关键字传参

    • 基本形式

      def func(**kwargs):
          print(kwargs)
          
      func(k1 = 1,k2 = 'alex')          #kwargs = {'k1':1,'k2':'alex'}
      func(**{'k1':'v1','k2':'v2'})     #kwargs = {'k1':'v1','k2':'v2'}    
      #注意实参里有**和没有的区别  
      
  3. 综合运用(*args和**kwargs一起使用)

    def func(*args,**kwargs):
        print(args,kwargs)
        
    func(1,2,3,4,k1 = 1,k2 = 2)              #args = (1,2,3,4),kwargs = {'k1':1,'k2':2}
    func(*[1,2,3],**{'k1':'v1','k2':'v2'})   #args = (1,2,3),kwargs = {'k1':'v1','k2':'v2'} 
    
  4. 参数相关重点

    • 定义函数

      #情况一:
      def func(a,b):
          pass
      
      #情况二:
      def func(a,b = None):
          pass
      
      #情况三:
      def func(*args,**kwargs):
          pass
      
    • 调用函数:位置参数 > 关键字参数

  5. 练习题

    # 1. 请写一个函数,函数计算列表 info = [11,22,33,44,55] 中所有元素的和。
    def get_sum():
        info = [11,22,33,44,55]
        data = 0
        for item in info:
            data += item
        print(data)
    
    get_sum()
    
    # 2. 请写一个函数,函数计算列表中所有元素的和。
    def get_list_sum(a1):
       	data = 0
        for item in a1:
            data += item
       	print(data)
        
    get_list_sum([11,22,33])
    get_list_sum([99,77,66])
    v1 = [8712,123,123]
    get_list_sum(v1)
    
    # 3. 请写一个函数,函数将两个列表拼接起来。
    def join_list(a1,a2):
        result = []
        result.extend(a1)
        result.extend(a2)
        print(result)
        
    join_list([11,22,33],[55,66,77]
    
    # 4. 计算一个列表的长度
    def my_len(arg):
    	count = 0
    	for item in arg:
              count += 1
    	print(count)
    
    v = [11,22,33]
    my_len(v)
    len(v)
    
    # 5. 发邮件的示例        
    def send_email(role,to):
        template = "要给%s%s发送邮件" %(role,to,)
        print(template)
     
    user_input = input('请输入角色:')
    if user_input == '管理员':
        send_email('管理员','xxxx@qq.com')
    elif user_input == '业务员':
        send_email('业务员','xxxxo@qq.com')
    elif user_input == '老板':
        send_email('老板','xoxox@qq.com')
    

3.2.3 返回值

  1. 作用

    • 返回值
    • 终止函数的执行
  2. 基本形式

    def func(arg):
    	代码             #函数内容
    	return 9         #返回值为9,默认:return None
    
    val = func('ads')    #设置一个变量接收返回值
    
    #特殊情况:
    def func():
    	return 2,3,'alex'     #返回是一个元组
    
    val = func()
    print(val)                #(2,3,'alex',)
    
  3. 返回值相关重点

    • 函数没有返回值,默认返回:None

    • 函数内部执行过程一旦遇到return就终止

    • return可以返回任意类型

    • 练习题

      # 1. 写函数,计算一个列表中有多少个数字,打印: 列表中有%s个数字。
      #    提示:type('x') == int 判断是否是数字。
      # 方式一:
      def get_list_counter1(data_list):
          count = 0
          for item in data_list:
              if type(item) == int:
                  count += 1
      	msg = "列表中有%s个数字" %(count,)
          print(msg)
          
      get_list_counter1([1,22,3,'alex',8])
      
      # 方式二:
      def get_list_counter2(data_list):
          count = 0
          for item in data_list:
              if type(item) == int:
                  count += 1
      	return count
          
      v = get_list_counter1([1,22,3,'alex',8])
      msg = "列表中有%s个数字" %(v,)
      print(msg)
      
      # 2. 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。
      # 方式一:
      def get_data_list1(arg):
          v = arg[::2]
          return v
      
      data = get_data_list1([11,22,33,44,55,66])
      
      # 方式二:
      def get_data_list2(arg):
          v = []
          for i in range(0,len(arg)):
          	if i % 2 == 0:
          		v.append(arg[i])
         	return v
      
      data = get_data_list2([11,22,33,44,55,66])
      
      # 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'},
       ]
      """
      def a():
          info = []
          with open('a.log',mode='r',encoding='utf-8') as f:
              for line in f:
                  line = line.strip()
                  info.append(line)
          return info
      
      def b():
          info = []
          with open('a.log',mode='r',encoding='utf-8') as f:
              for line in f:
                  line = line.strip()
                  v = line.split('|')
                  info.append(v)
          return info
      
      def c():
          info = []
          with open('a.log',mode='r',encoding='utf-8') as f:
              for line in f:
                  line = line.strip()
                  list = line.split('|')
                  v = {}
                  v['name'] = list[0] 
                  v['pwd'] = list[1]  
                  v['age'] = list[2]  
                  info.append(v)
          return info
      
      date1 = a()
      date2 = b()
      date3 = c()
      print(date1,date2,date3)
      
  4. 数据类型中的方法有没有返回值总结

    • 无返回值

      #示例:
      v = [11,22,33]
      v.append(99) 
      
    • 仅有返回值

      #示例一:
      v = "alex"
      result = v.split('l')
      
      #示例二:
      v = {'k1':'v2'}
      result1 = v.get('k1')
      result2 = v.keys()
      
    • 有返回值 + 修改数据

      #示例:
      v = [11,22,33]
      result = v.pop()          # 将被删除的数据赋值给result
      
    • 常用需要记住的

      1. str

        ①. strip(),返回字符串

        ②. split(),返回列表

        ③. replace(),返回字符串

        ④. join(),返回字符串

      2. list

        ① . append(),无

        ②. insert(),无

        ③. pop(),返回要删除的数据

        ④. remove(),无

        ⑤. find() / index(),返回索引位置的数据

      3. dict

        ①. get,返回缩影键的值

        ②. keys(),返回字典所有的键

        ③. values(),返回字典所有的值

        ④. items(),返回字典所有的键值对

3.2.4 总结

  1. 函数的基本结构:

    #情况一
    def f1():
        函数内容
    f1()
    
    #情况二
    def f2(a):
        函数内容    
    f2(1)
    
    #情况三
    def f3():
        函数内容
        return 
    v1 = f3()
    
    #情况四
    def f4(a1,a2):
        函数内容
        return a1+a2
    v2 = f4(1,7)
    
  2. 函数内部的数据是否会混乱?

    • 函数的内部执行相互之间不会混乱
    • 执行完毕 + 内部元素不被其他人使用 =>销毁

3.3 函数小高级

3.3.1 函数名可以当做变量来使用

#示例一:
def func():
    print(123)
    
func_list = [func, func, func]
# func_list[0]()
# func_list[1]()
# func_list[2]()
for item in func_list:
    v = item()
    print(v)
    
#示例二:
def func():
    print(123)
def bar():
    print(666)

info = {'k1': func, 'k2': bar}
info['k1']()
info['k2']()

#注意区别:
def func():
    return 123

func_list1 = [func,func,func]
func_list2 = [func(),func(),func()]
print(func_list1)
print(func_list2)

3.3.2 函数可以当做参数进行传递

#示例:
def func(arg):
    v1 = arg()
    print(v1)    
def show():
    print(666)
    
result = func(show)
print(result)

面试题

#面试题:多个函数的调用
def func():
    print('话费查询')
def bar():
    print('语音沟通')
def base():
    print('业务办理')
def show():
    print('流量查询')
def test():
    print('人工服务')

info = {
    'f1': func,
    'f2': bar,
    'f3':base,
    'f4':show,
    'f5':test
}
choice = input('请选择要选择功能:')
function_name = info.get(choice)
if function_name:
    function_name()
else:
    print('输入错误')

3.3.2 匿名函数:lambda表达式

  1. 作用:用于简单表达的函数

  2. 基本形式

    #三元运算,为了解决简单的if else的情况
    if 1 == 1:
        a = 123
    else:
        a = 456
    #用三元运算表示:
    a =  123  if 1 == 1 else 456
    
    #lambda表达式,为了解决简单函数的情况
    def func(a1,a2):
        return a1 + a2 
    #用lambda表达式表示:
    func = lambda a1,a2: a1+a2          #隐含了return
    
  3. 重点:

    • lambda表达式只能用一行表示函数
    • 用lambda表达式表示函数时,无法设置新变量,只能用哪个参数做变量
    • 列表多有的方法基本上都是返回None,字符串的所有方法基本上都是返回新值
  4. 练习题

    # 练习题1
    USER_LIST = []
    def func0(x):
        v = USER_LIST.append(x)
        return v 
    result = func0('alex')
    print(result)              #None
    
    # 练习题2
    def func0(x):
        v = x.strip()
        return v 
    result = func0(' alex ')
    print(result)               #'alex'
    
    # 练习题3
    USER_LIST = []
    func1 = lambda x: USER_LIST.append(x)
    v1 = func1('alex')
    print(v1)                    #None
    print(USER_LIST)             #['alex']
    
    # 练习题4
    func1 = lambda x: x.split('l')
    v1 = func1('alex')
    print(v1)                    #['a','ex']
    
    # 练习题5
    func_list = [lambda x:x.strip(), lambda y:y+199,lambda x,y:x+y]
    v1 = func_list[0]('alex ')
    print(v1)                    #'alex'
    v2 = func_list[1](100)
    print(v2)                    #299
    v3 = func_list[2](1,2)
    print(v3)                    #3
    

3.4 函数中高级

3.4.1 函数可以做返回值

#示例:
def func():
    print(123)
def bar():
    return func

v = bar()
v()

3.4.2 闭包

  1. 概念:为函数创建一块区域并为其维护自己数据,方便以后执行时调用

  2. 应用场景:

    • 装饰器
    • SPLAchemy源码
    #示例:
    name = 'oldboy'
    def bar(name):
        def inner():
            print(name)
        return inner
    v1 = bar('alex') # { name=alex, inner }  # 闭包,为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。
    v2 = bar('eric') # { name=eric, inner }
    v1()   # alex
    v2()   # eric
    
    #区分:
    # 不是闭包
    def func1(name):
        def inner():
            return 123
        return inner 
    
    # 是闭包:封装值 + 内层函数需要使用。
    def func2(name):
        def inner():
            print(name)
            return 123
        return inner 
    
  3. 练习题

    #第一题
    name = 'alex'
    def base():
        print(name)
    def func():
     	name = 'eric'
        base()
    func()  # eric
    
    # 第二题
    name = 'alex'
    def func():
     	name = 'eric'
        def base():
        	print(name)
        base()
    func()  # eric
    
    # 第三题
    name = 'alex'
    def func():
     	name = 'eric'
        def base():
        	print(name)
        return base 
    base = func()
    base()   # eric
    
    #注意:函数在何时被谁创建?
    
    #示例:
    # 第四题
    info = []
    def func():
        print(item)   
    for item in range(10):
        info.append(func)
    
    info[0]() # 9
    
  4. 面试题

    #面试题
    info = []
    def func(i):
        def inner():
            print(i)
    	return inner
    for item in range(10):
        info.append(func(item))
    
    info[0]() # 0
    info[1]() # 1  
    info[4]() # 4
    

3.4.3 高阶函数

  1. 把函数当做参数传递
  2. 把函数当做返回值
  3. 注意:对函数进行赋值

3.5 内置函数

函数分为自定义函数赫尔内置函数

3.5.1 强制转换类

  • int() / str() / bool() / list() / tuple() / dict() / set()

3.5.2 输入输出类

  • input() / print()

3.5.3数学相关类

  • abs(),计算绝对值

    v = abs(-1)
    print(v)
    
  • sum(),求和

    v = [1,2,3,4,5,6,7,8]
    print(sum(v))
    

     

  • float(),转换为浮点型(小数)

    v = 55
    v1 = float(55)
    print(v1)        #55.0
    
    • 补充:int(5.5),只保留整数
  • max(),找到最大值

    v = [1,2,311,21,3,]
    result = max(v)
    print(result)
    

     

  • min(),找到最小值

    v = [1,2,311,21,3,]
    result = min(v)
    print(result)
    

     

  • divmod(),去两数相除的商和余

    #示例:
    a,b = divmod(1001,5)
    print(a,b)          #a=200,b=1
    
    • 补充:分页展示数据:

      # 练习题  请通过分页对数据进行展示
      """
      要求:
          每页显示10条数据
          让用户输入要查看的页面:页码
      """
      
      USER_LIST = []
      for i in range(1,836):
          temp = {'name':'你-%s' %i,'email':'123%s@qq.com' %i }
          USER_LIST.append(temp)
      
      # 数据总条数
      total_count = len(USER_LIST)
      
      # 每页显示10条
      per_page_count= 10
      
      # 总页码数
      max_page_num,a = divmod(total_count,per_page_count)
      if a>0:
          max_page_num += 1
      
      while True:
          pager = int(input('要查看第几页:'))
          if pager < 1 or pager > max_page_num:
              print('页码不合法,必须是 1 ~ %s' %max_page_num )
          else:
              start = (pager-1) * per_page_count
              end = pager * per_page_count
              data = USER_LIST[start:end]
              for item in data:
                  print(item)
      

       

  • pow(),指数

    v = pow(2,3)      #相当于2**3
    print(v)         # 8
    

     

  • round() ,保留几位小数,默认保留整数,还会四舍五入

    v = round(1.127,2)       #第二个数代表保留几位小数,默认是None
    print(v)         # 1.13  四舍五入
    

3.5.4 进制转换类

  1. bin():将十进制转换成二进制

    v = 10
    print(bin(v))
    
  2. oct():将十进制转换成八进制

    v = 10
    print(oct(v))
    
  3. int():将其他进制转换成十进制(base默认是10)

    • 二进制转换成十进制

      # 二进制转化成十进制
      v1 = '0b1101'
      result = int(v1,base=2)         #base=2说明读取的是二进制
      print(result)
      
    • 八进制转换成十进制

      # 八进制转化成十进制
      v1 = '0o1101'
      result = int(v1,base=8)
      print(result)
      
    • 十六进制转化成十进制

      # 十六进制转化成十进制
      v1 = '0x1101'
      result = int(v1,base=16)
      print(result)
      

       

  4. hex():将十进制转换成十六进制

    v = '10'
    print(hex(v))
    
  5. 面试题(1字节等于8位)

    # 请将 ip = "192.168.12.79" 中的每个十进制数转换成二进制并通过,连接起来生成一个新的字符串。
    ip = "192.168.12.79" # 001010010 . 001010010 . 001010010 . 001010010
    ip_list = ip.split('.') # ['192','168','12','79']
    result = []
    for item in ip_list:
        result.append(bin(int(item)))
    print(','.join(result))
    
    # 请将 ip = "192.168.12.79" 中的每个十进制数转换成二进制: 
    #          0010100100001010010001010010001010010 -> 十进制的值。
    # 3232238671
    ip = '192.168.12.79'
    v = ip.split('.')
    info = []
    for i in v:
        date = str(bin(int(i)))
        if len(date) > 10:
            date = date[-8:]
        else:
            count = 10 - len(date)
            date = date.replace('0b','0'*count)
        info.append(date)
    val = "".join(info)
    a = int(val,base=2)
    print(a)
    

3.5.5 与类相关类

  1. type():查看数据类型

    class Foo:
        pass
    
    obj = Foo()
    if type(obj) == Foo:
        print('obj是Foo类的对象')
    
  2. issubclass(类,或其基类):判断前一个类是否是后一个类或其基类的子类

    class Base:
        pass
    
    class Base1(Base):
        pass
    
    class Foo(Base1):
        pass
    
    class Bar:
        pass
    
    print(issubclass(Bar,Base))
    print(issubclass(Foo,Base))
    
  3. isinstance(对象,类或其基类):判断一个对象是否是一个类或其基类的实例(对象)

    • 注意:判断一个对象是否是一个类的实例(对象),一定要用type,不要使用instance
    class Base(object):
        pass
    
    class Foo(Base):
        pass
    
    obj = Foo()
    print(isinstance(obj,Foo))  # 判断obj是否是Foo类或其基类的实例(对象)
    print(isinstance(obj,Base)) # 判断obj是否是Foo类或其基类的实例(对象)
    
  4. super().方法名():

    • 单继承:根据self对象所属的类的继承关系,按照顺序依次找方法并执行(找到第一个为止)【这只是表象】
    • 多继承:不是根据父类的继承顺序来查找函数,而是根据mro的顺序来查找函数
    class A:
        def func(self):
            print('A')
    
    class B(A):
        def func(self):
            print('B')
            super().func()
    
    class C(A):
        def func(self):
            print('C')
            super().func()
    
    class D(B,C):
        def func(self):
            print('D')
            super().func()
    
    D().func()
    

     

    class Base(object):
        def func(self):
            super().func()  # 根据self对象所属类的继承关系,按照顺序挨个找func(除去此func函数)方法并执行(找到第一个为止)
            print('base.func')
    
    class Bar(object):
        def func(self):
            print(bar3)
    
    class Foo(Base,Bar): # Foo -> Base -> Bar
        pass
    
    obj = Foo()
    obj.func()
    

3.5.6 编码相关

  1. chr():将十进制数字转换成ascii编码中对相应的字符串

  2. ord():根据字符在ascii编码中找到对应的十进制

  3. 应用实例(随机验证码的生成)

    #应用:生成随机验证码
    import random          # 导入一个模块 
    def get_random_code(length=6):
        data = []
        for i in range(length):
            v = random.randint(65,90)
            data.append(chr(v))
        return  ''.join(data)
    
    code = get_random_code()
    print(code)
    

3.5.7 高级的内置函数

  1. zip():拉链,拉链方法一一对应(算不上高级)

    val = zip(('a','b','c'),(1,2,3))
    print(list(val))
    #---> [('a',1),('b',2),('c',3)]
    

     

  2. map(函数,可迭代对象):一起执行

    • 循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行得到的结果保存到行的列表中(可强制转换list,也可for循环遍历),并返回
    #示例一(常规函数):
    def func(v):
        return v + 100
    v1 = [11,22,33,44]
    result = map(func,v1)
    print(result)
    
    #示例二(lambda):
    v1 = [11,22,33,44]
    result = map(lambda x:x+100,v1)
    print(list(result))
    
  3. filter(函数,可迭代对象):进行筛选

    • 对于可迭代对于可迭代对象中的元素进行筛选,最终获取符合条件的序列。

      #示例:
      v1 = [11,22,33,'asd',44,'xf']
      
      def func(x):
          if type(x) == int:
              return True
          return False
      result = filter(func,v1) 
      print(list(result)) # [11, 22, 33, 44]
      
      # 用lambda表达式:
      result = filter(lambda x: True if type(x) == int else False ,v1)
      print(list(result))
      # 相当于:
      result = filter(lambda x: type(x) == int ,v1)
      print(list(result))
      
  4. reduce(函数,可迭代对象):得到结果

    • 与map和filter不同,reduce在最新的py3版本中移除内置函数,需要执行时调用,另外输入是两个值,作用是输入一堆元素,输出一个值

    • 用传给reduce中的函数func(有两个参数)先对第一、二个元素进行操作,得到的结果再与第三个数据用func函数运算,最后得到一个结果

      import functools   
      #【reduce 在python3的内置函数中被移除,需要导入functools 】
      v1 = ['wo','hao','e']
      
      def func(x,y):
          return x+y
      result = functools.reduce(func,v1) 
      print(result)
      
      result = functools.reduce(lambda x,y:x+y,v1)
      print(result)
      

3.5.8 其他内置函数

  1. len():计算长度
  2. open():打开文件
  3. range():
  4. id():查看内存地址

3.6 作用域

3.6.1 分类

  1. 全局作用域:在python中,相当于一个py文件

    • 全局作用域中的变量称为全局变量
    • 全局变量必须大写(潜规则)
  2. 局部作用域:在python中,相当于一个函数

    • 局部作用域中的变量称为局部变量
    • 局部变量则用小写
USER_LIST = [11,22,3]         #全局变量
def func():
    name = 'asdf'             #局部变量
    USER_LIST.append(12)
    USER_LIST.append(name)
func()
print(USER_LIST)

3.6.2 递归

  • 递归就是自己调用自己。(效率低)

    def func():
        print(1)
        func()
        
    func()
    
    # 递归的返回值
    def func(a):
        if a == 5:
            return 100000
        return = func(a+1) + 10
    v = func(1)
    print(v)
    
    name = 'alex'
    def func():
        def inner():
            print(name)
         return inner
    v =func()
    

3.6.3 总结

  1. 在python中,一个函数就是一个作用域

  2. 在作用域中查找数据规则:

    • 优先在自己作用域里面找数据
    • 自己没有就去‘父级’中找,没有就去‘父级’的‘父级’中找,直到找到全局作用域
    • 如果最后找到全局作用域中也没有就会报错
    • 寻找时注意:父级作用域中的只是到底是什么
    #示例一:
    x = 10
    def func():
        x = 9
        print(x)           
        def x1():
            x = 8
            print(x)
    func()               # 9
    
    #示例二:
    x = 10
    def func():
        x = 9
        print(x)
        def x1():
            x = 8
            print(x)
        x1()
    func()               # 9   8
    
    #示例三:
    x = 10
    def func():
        x = 9
        print(x)
        def x1():
            x = 8
            print(x)
        print(x)
        x1()
    func()               # 9   9   8 
    
    #示例四:
    x = 10
    def func():
        x = 9
        print(x)
        def x1():
            x = 8
            print(x)
        x1()
        print(x)
    func()               # 9   8   9 
    
    #示例五:
    x = 10
    def func():
        x = 9
        print(x)
        def x1():
            print(x)
        x1()
        print(x)
    func()               # 9   9   9
    
    #示例六:
    x = 10
    def func():
        x = 8
        print(x)
        def x1():
            print(x)
        x = 9
        x1()
        x = 10
        print(x)
    func()               # 8   9   10
    
    #示例七:
    x = 10
    def func():
        x = 8
        print(x)
        def x1():
            print(x)
        x1()
        x = 9
        x1()
        x = 10
        print(x)
    func()               # 8   8   9   10
    
  3. 对于自作用域:

    • 只能找到‘父级’中的值,默认无法重新为‘父级’的变量进行重新赋值

    • 如果非要对’父级‘变量进行重新赋值,使用呢global / nonlocal 进行强制赋值

      • global:直接找到指定的全局变量,在进行重新赋值,其他的不改
      • nonlocal:只找到‘父级’的变量,进行重新赋值,其他的不改
      • 建议:一般不用,以免造成代码混乱
    #global示例:
    name = 'oldboy'
    def func():
        name = 'alex'
        def inner():
            global name      #直接找到全局的name
            name = 'abc'     #再进行重新赋值
        inner()
        print(name)          #'alex'
    func()
    print(name)              #'abc'
    
    #nonlocal示例:
    name = "oldboy"
    def func():
        name = 'alex'
        def inner():
            nonlocal name    #找到上一级的name
            name = 'abc'     #再进行重新赋值
        inner()
        print(name)          #'abc'
    func()
    print(name)              #"oldboy"
    

3.7 推导式

3.7.1 列表推导式

  1. 目的:方便生成一个列表

  2. 格式:

    v1 = [i for i in 可迭代对象 ]
    v2 = [i for i in 可迭代对象 if 条件 ]      #条件为true才进行append
    
    # 示例:
    v1 = [ i for i in 'alex' ]  
    v2 = [i+100 for i in range(10)]
    v3 = [99 if i>5 else 66  for i in range(10)]
    
    def func():
        return 100
    v4 = [func for i in range(10)]
    
    v5 = [lambda : 100 for i in range(10)]
    result = v5[9]()
    
    v6 = [lambda :i for i in range(10)]
    result = v6[5]()
    

    面试题

    # 新浪微博面试题
    v7 = [lambda x:x*i for i in range(10)] 
    # 1.请问 v7 是什么?
    # 2.请问 v7[0](2) 的结果是什么?
    
    # 面试题
    def num():
        return [lambda x:i*x for i in range(4)]  # 此时i已经变成了3
    # num() -> [函数,函数,函数,函数]
    print([ m(2) for m in num() ]) # [6,6,6,6]  
    

3.7.2 集合推导式

  1. 目的:方便生成一个集合

  2. 格式

    v1 = { i for i in 'alex' }
    

3.7.3 字典生成器

  1. 目的:方便生成一个字典

  2. 格式:

    v1 = { 'k'+str(i):i for i in range(10)}
    

3.7.4 生成器推导式

# 列表推导式,立即循环创建所有元素
"""
def func():
    result = []
    for i in range(10):
        result.append(i)
    return result
v1 = func()
"""
v1 = [i for i in range(10)]
print(v1)

# 生成器推导式,创建了一个生成器,内部循环为执行
"""
def func():
    for i in range(10):
        yield i
v2 = func()
"""
v2 = (i for i in range(10))
for item in v2:
    print(item)

# 面试题:请比较 [i for i in range(10)] 和 (i for i in range(10)) 的区别?
# 列表是可变类型的数据类型,内部不支持哈希算法,所以在查找时比较费时间
# 元组是不可变类型的数据类型,内部支持哈希算法,所以在查找时时间耗损比较小
import time

l_start = time.time()
list_ = [i for i in range(1000000)]
l_end = time.time()
print(l_end - l_start)
print('*'*30)

d_start = time.time()
dict_ = (i for i in range(1000000))
d_end = time.time()
print(d_end - d_start)

# 0.060662031173706055 列表
# 0.0                  元组

3.8 装饰器

3.8.1 目的

  • 在不改变函数内部代码的基础上,在执行函数之前和之先动执行某个功能

3.8.2 应用场景

  • 想要为函数扩展功能时,可以选择用装饰器

3.8.3 基本装饰器

  1. 基本格式:

    def wrapper(func):
        def inner(*args,**kwargs):
            v = func(*args,**kwargs)
            return v 
        return inner 
    
    # 重点:
        # 第一步:执行wrapper函数并将下面的函数参数传递,相当于:wrapper(index)
        # 第二步:将wrapper的返回值重新赋值给下面的函数名。 即:index = wrapper(index)
    @wrapper 
    def index(*args,**kwargs):
        print(123)
        return 666
    
    print(index)
    
  2. 总结:

    • 编写格式:

      def 外层函数(参数):
          def 内层函数(*args,**kwargs)
          	return 参数(*args,**kwargs)
          return 内层函数
      
    • 应用格式:

      @外层函数
      def index():             #要装饰的函数
          pass
      
      index()
      

       

    • 装饰器的编写:

      # 装饰器的编写
      def x(func):
          def y():
              # 前
              ret = func()
              # 后
              return ret 
         	return y 
      
      # 装饰器的应用
      @x
      def index():
          return 10
      
      # 执行函数,自动触发装饰器了
      v = index()
      print(v)
      
    • 示例:

      def func(arg):
          def inner():
              print('before')
              v = arg()
              print('after')
              return v 
          return inner 
      @func
      def index():
          print('123')
          return '666'
      
      # 示例一
      v1 = index() # 执行index函数,打印123并返回666赋值给v1.
      
      # 示例二
      v2 = func(index) # v2是inner函数,arg=index函数
      index = 666 
      v3 = v2()
      
      # 示例三
      v4 = func(index)
      index = v4  # index ==> inner 
      index()
      
      # 示例四
      index = func(index)
      index()
      

3.8.4 带参数的装饰器

  1. 应用场景:flask框架 / Django缓存 / 写装饰器实现被装饰器的函数要执行N次

    # 第一步:执行 ret = xxx(index)
    # 第二步:将返回值赋值给 index = ret 
    @xxx
    def index():
        pass
    
    # 第一步:执行 v1 = uuu(9)
    # 第二步:ret = v1(index)
    # 第三步:index = ret 
    @uuu(9)
    def index():
        pass
    
  2. 普通装饰器和带参装饰器的区别

    # 普通装饰器
    def wrapper(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs) # 执行原函数并获取返回值
            return data
        return inner 
    
    @wrapper
    def index():
        pass
    
    # 带参数装饰器 
    def x(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                data = func(*args,**kwargs) # 执行原函数并获取返回值
                return data
            return inner 
    	return wrapper 
    
    @x(9)
    def index():
        pass
    
  3. 练习题

    # 习题一:
    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,把每次结果添加到列表中,最终返回列表。
    def xxx(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                v = []
                for i in range(counter):
                    data = func(*args,**kwargs) # 执行原函数并获取返回值
                    v.append(data)
                return v
            return inner
        return wrapper
    
    @xxx(5)
    def index():
        return 8
    v = index()
    print(v)
    
    # 习题二:
    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,并返回最后一次执行的结果【面试题】
    def xxx(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                for i in range(counter):
                    data = func(*args,**kwargs) # 执行原函数并获取返回值
                return data
            return inner
        return wrapper
    
    @xxx(5)
    def index():
        return 8
    v = index()
    print(v)
    
    # 习题三:
    # 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次,并返回执行结果中最大的值。
    def xxx(counter):
        def wrapper(func):
            def inner(*args,**kwargs):
                value = 0
                for i in range(counter):
                    data = func(*args,**kwargs) # 执行原函数并获取返回值
                    if data > value:
                        value = data 
                return value
            return inner
        return wrapper
    
    @xxx(5)
    def index():
        return 8
    v = index()
    print(v)
    

3.9 迭代器

3.9.1 基本知识

  1. 用途:对某种对象(str list tuple dict set)中的元素进行逐一获取

  2. 表象:具有__iter__方法切每次调用都会获取可迭代对象中的元素(从前到后以一个一个获取)

  3. 示例:

    • 列表转换成迭代器:

      v = iter([1,2,3,4,5,6])
      v = [1,2,3,4,5,6].__iter__()
      
    • 迭代器想要获取每个值:反复调用 val = v.__next_()

      v1 = [11,22,33,44]
      
      # 列表转换成迭代器
      v2 = iter(v1)
      
      # 迭代器获取每个值
      result1 = v2.__next__()
      print(result1) # 11
      result2 = v2.__next__()
      print(result2) # 22
      result3 = v2.__next__()
      print(result3) # 33  
      result4 = v2.__next__()
      print(result4) # 44
      
      result5 = v2.__next__()
      print(result5)    # 报错:Stoplteration    表示已经迭代结束
      
  4. for循环:运用了迭代器

    v1 = [11,22,33,44]
    
    # 1.内部会将v1转换成迭代器
    # 2.内部反复执行 迭代器.__next__()
    # 3.取完不报错
    for item in v1:
        print(item)
    

3.9.2 可迭代对象

  1. 表象:可以被for循环的对象就可以称为可迭代对象

  2. 如何让一个对象变成可迭代对象?

    • 在类中实现__iter__方法并且返回一个迭代器(生成器)

      # 示例一:
      class Foo:
          def __iter__(self):
              return iter([1,2,3,4])
      
      obj = Foo()
      
      # 示例二:
      class Foo:
          def __iter__(self):
              yield 1
              yield 2
              yield 3
      
      obj = Foo()
      
  3. 注意:只要能被for循环,就去它的内部看__iter__方法

3.10 生成器

3.10.1 基本知识

  1. 可以理解为:函数的变异、特殊的迭代器、特殊的可迭代对象

  2. 生成器的作用:生成数据、迭代

  3. 示例:

    # 生成器函数(内部是否包含yield)
    def func():
        print('F1')
        yield 1
        print('F2')
        yield 2
        print('F3')
        yield 100
        print('F4')
    # 函数内部代码不会执行,返回一个 生成器对象 。
    v1 = func()
    # 生成器是可以被for循环,一旦开始循环那么函数内部代码就会开始执行。
    for item in v1:
        print(item)
    

3.10.2 关键字

  1. yield:判断函数是否是生成器

  2. yield from:从当前生成器函数跳转到其他生成器函数中,执行结束后再回到原函数继续执行下面的代码

    def base():
        yield 88
        yield 99
    
    def func():
        yield 1
        yield 2
        yield from base()   # 跳到base函数
        yield 3
    
    result = func()
    for item in result:
        print(item)       # 1   2   88   99   3
    

3.10.3 总结

  1. 重点:

    • 函数中如果存在yield,那么该函数就是一个生成器函数

    • 调用生成器函数会返回一个生成器

      def func():
          yield 1
      result = func()
      print(type(result)) # <class 'generator'>
      print(result) # <generator object func at 0x0000024845623ED0>
      print(list(result)) # [1]
      # 不管yield返回一个值还是多个值,其类型都是生成器对象,要打印时,可以强制转换成列表,或者for循环
      

       

    • 生成器只有被for循环时,生成器函数你不的代码才会执行,每次循环都会获取yield返回的值

  2. 建议:

    • 生成器函数中最好不要有return

    • 如果需要终止生成器函数中的循环,可以用return

      def func():
          count = 1
          while True:
              yield count
              count += 1
              if count == 100:
                  return
      val = func()
      for item in val:
          print(item)
      
  3. 生成器示例:读取大文件内容

    def func():
        #  分批去读取文件中的内容,将文件的内容返回给调用者。
        cursor = 0
        while True:
            f = open('db', 'r', encoding='utf-8')    # 通过网络连接上redis
            # 代指  redis[0:10]
            f.seek(cursor)
            data_list =[]
            for i in range(10):
                line = f.readline()
                if not line:
                    return
                data_list.append(line)
            cursor = f.tell()
            f.close()  # 关闭与redis的连接
    
            for row in data_list:
                yield row
    
    for item in func():
        print(item)
    

3.11 异常处理

3.11.1 基本格式

try:
    val = input('请输入数字:')
    num = int(val)
except Exception as e:
    print('操作异常')
  • 注意:放在位置的不同有不同的效果。灵活运用,避免程序报错和崩溃

3.11.2 finally的运用

def:
    try:
        int('asdf')
    except Exception as e:
        print(e)
        return 123
    finally:
        print('1')
func()
#即使return  finally最后也会执行

3.11.3 主动触发异常

try:
    int('123')
    raise Exception('dsfsegsdg') #主动触发异常
except Exception as e:
	print('111')

3.11.4 自定义异常(raise)

class MyException(Exception):
    def __init__(self,message):
        super().__init__()
        self.message = message  #在Exception 类中 的初始化 加入一行  self.message = message

try:
    raise MyException('asdf')
except MyException as e:     #此时  e = MyException('asdf)
    print(e.message)
posted @ 2020-08-25 16:02  今天捡到一百块钱  阅读(68)  评论(0编辑  收藏  举报