zoukankan      html  css  js  c++  java
  • 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)
    
  • 相关阅读:
    GCC编译器原理(三)------编译原理三:编译过程(3)---编译之汇编以及静态链接【2】
    xmind转为markdown
    XMind破解
    读取字符串中的数字
    "Cannot declare member function ...to have static linkage"错误
    error: cannot bind non-const lvalue reference of type
    (C++ Error: Incompatible types in assignment of ‘char*’ to ‘char [2])
    C++中的map
    17 jQuery阶段_操作样式_操作属性_动画_节点操作
    第一部分:网络多任务_day01_网络编程基础
  • 原文地址:https://www.cnblogs.com/borntodie/p/13560210.html
Copyright © 2011-2022 走看看