欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python基础学习day11函数的进阶

程序员文章站 2022-09-04 21:30:07
1. 默认参数的陷阱(只针对于默认参数是可变的数据类型):如果默认参数使用的是可变类型数据,那么无论调用多少次这个默认参数,都是同一个(id相同)。默认参数的可变数据类型既不在全局也不再局部,定义后不会消失(局部命称空间会消失)。 2. 局部作用域的陷阱:在函数中,如果定义一个变量,但是在定义变量之 ......
  1. 默认参数的陷阱(只针对于默认参数是可变的数据类型):如果默认参数使用的是可变类型数据,那么无论调用多少次这个默认参数,都是同一个(id相同)。默认参数的可变数据类型既不在全局也不再局部,定义后不会消失(局部命称空间会消失)。

    def func(num,nums=[]):
        nums.append(num)
        return nums
    ret1 = func(1)
    print(ret)
    >>>[1]
    ret2 = fun(2)
    print(ret2)
    >>>[1,2]  #将第一次的数据也包含了。
    
    #例:
    def func(a,list=[]):
        list.append(a)
        return list
    ret1 = func(10,)
    print(ret1)         #[10]
    print(func(20,[]))  #[20]  #重新为列表传入参数
    print(func(100))    #[10,100]
    print(ret1)         #[10,100]
    
  2. 局部作用域的陷阱:在函数中,如果定义一个变量,但是在定义变量之前引用这个变量,即使全局变量有此引用的变量,仍然会报错。

    #例1:
    count = 1
    def func():
    	count += 1
        print(count)
    func()
    indentationerror: unindent does not match any outer indentation level
        
    #例2:
    count = 1
    def func():
        print(count)
    func()      #1
    
    #例3:
    count = 1
    def func():
    	print(count)
        count = 1
    func()
    unboundlocalerror: local variable 'count' referenced before assignment
    
  3. global nonlocal

    • global:1.在局部作用域里声明一个全局变量。

      #1.
      num = 0
      def func():
          num = 1
      print(num)    #0
      
      #2.
      def func():
          global num
          num = 1
      print(num)  #会报错。
      
      #3.
      def func():
          global num
          num = 1
      func()
      print(num)  #1
      
      #3.
      num = 0
      def func():
          global num
          num = 1
      func()    
      print(num)    #1
      
      
    • nonlocal:不能够操作全局变量;主要用于内层函数对外层函数的局部变量进行修改。

      def func1():
      	count = 1
          def inner():
              nonlocal count
              count+=1
          inner()
      
  4. 函数名的运用

    • 函数名指向的是函数的内存地址

    • 函数名 + ()就可以执行函数

      #例1:
      def func():
      	print(1)
      f1 = func
      f2 = f1
      f2()     #1
      
      #例2.
      def func1():
          print(1)
      def func2():
          print(2)
      func2 = func1
      func2()    #1
      
    • 函数名可以作为容器类数据类型的元素

      #例3:
      def func1():
          print(1)
      def func2():
          print(2)
      def func3():
          print(3)
      l1 = [func1,func2,func3]
      for i in l1:
          i()   #1 2 3
      
    • 函数名可以作为函数的参数

      def func0(a):
          print(1)
      def func1(x):
          x()
      func1(func0)      #1   
      
    • 函数名可以作为函数的返回值。

      def func1():
          print(1)
      def func2(x):
          return x
      ret = func2(func)
      ret()       #1
      
  5. 格式化输出(3.6版本之后):

    • 基础表达:
    ```python
    
    name = 'python'
    age = '18'
    msg = f'我叫{name},今年{age}'    #在引号前添加一个字符f
    
    ```
    
    • 可以加表达式:

      count = 2
      print(f'最终结果:{count**2}')
      
      name = 'python'
      print(f'我的名字是{name.upper()}')
      
      
      dic = {'name':'python','age':'18'}
      msg = f'我叫{dic["name"]},今年{dic["age"]}'   #注意双引号与单引号的使用,不能产生歧义。
      
      list = ['python','18']
      msg = f'我叫{list[0]},今年{list[1]}' 
      
      
    • 可以结合函数:

      def sum1(a,b):
          return a+b
      print(f'最终结果是{sum1(1,2)}')
      
    • 优点:1.结构更加优化。2.可以结合表达式和函数使用。3.效率更高

  6. 迭代器:

    • 可迭代对象:

      对象:python中一切皆对象。 可迭代:可以进行循环更新的一个值。

      以专业角度来说,内部含__iter__方法的对象即为可迭代对象。如:str、list、tuple、dict、set、range、文件句柄等。

    • 获取对象的所有方法并且以字符串的形式表现:dir()

      s1 = 'qwer'
      print(dir(s1))  #请自测。
      
    • 判断一个对象是否是可迭代对象:

      s1 = 'qwer'
      print('__iter__' in dir(s1))  #true
      
    • 可迭代对象的优点:

      1. 存储的数据能够直接显示,比较直观。
      2. 拥有的方法比较多,操作起来方便。
    • 可迭代对象的优点:

      1. 占内存。

      2. 不能直接通过for循环(不能直接取值),python内部自动将其转换为迭代器(见下文)然后再进行for循环(用next()方法取值,见下文。)。

        l1 = [1,2,3,4]
        for i in l1:
            print(i) #python内部自动将其转换为迭代器然后再进行for循环
        
    • 迭代器:

      迭代器的定义:内部含__iter____next__方法的对象就是迭代器。例如:文件句柄。

    • 判断是否为可迭代器:

      with open ('1.txt',encoding='utf-8',mode='w') as f1:
          print('__iter__' in dir(f1) and '__next__' in dir(f1))
      
    • 可迭代对象可以转换为迭代器:

      s1 = 'qwert'
      obj = iter(s1)
      #或者:
      s1.__iter__()
      print(obj)   #请自测,会返回一个迭代器的内存地址
      
    • 对迭代器进行取值:

      s1 = 'qwert'
      obj = iter(s1)
      next(obj)   #会取出字符串s1的第一个元素
      next(obj)   #会返回字符串s1的第二个元素
      #或:
      obj.__next__()
      
    • 迭代器优点:

      1.节省内存,迭代器在内存中相当于只占一个数据的空间,因为每次取值上一条数据都会在内存释放。迭代器具有惰性机制,next一次,只取一个值,绝不多取。

    • 迭代器的缺点:

      1.不能直观的查看里面的数据。

      2.只能一直向下取值。

      3.速度慢。

    • 可迭代对象与迭代器的对比:

      • 可迭代对象是的操作方法比较多,比较直观,储存数据相对少(几百万个数据,8g内存是可以承受的)的一个数据集。
      • 当侧重于对于数据可以灵活处理,并且内存空间足够,可将数据设置为一个可迭代对象。
      • 迭代器是非常节省内存,可以记录取值位置,可以通过循环加next方法取值,但是不直观,操作方法比较单一的一个数据集。
      • 当数据量过大,可选择将数据设置为一个迭代器。
    • 用while循环模拟for循环对可迭代对象进行取值:(请自测)

      l1 = [1,2,3,4,5,6,7,8]
      obj = iter(l1)
      while 1:
          try:     #try:异常处理
              print(next(obj))
          except stopiteration:
              break