【old】Python学习笔记
上学期看视频记得,也没学到多少,目前打算一边通过《Python学习手册 第四版》提高核心语法(太厚了 噗),一边学习Python Web开发
然后这里的多任务编程和网络编程是暑假学的
5. 函数
5.1 函数的参数
  ### 可变对象按引用传递,不可变对象按引用传递
  # 避免对可变参数的修改:
  L = [1,2]
  change(L[:]) #
  # 或
  def change(l):
      l = l[:]
  
  ###【默认参数】【必须是不可变对象】
  def power(x,n=2): 
      return x**n
  power(2) #=>4
  power(2,3) #=>8
  
  ###【可变参数】(元祖)
  def sum(*nums): #可以传入0到N个参数,函数内部接收到的是tuple
      s=0
      for x in nums:
          s+=x
      return s
  
  ###【关键字参数】(字典)
  def preson(name,age,**kw): #可以传入0个或多个参数
      print('name:',name,'age:',age,'other',kw)
  person('bin',19,city='zz',job='stu') #=> name:bin age:19 other:{'city':'zz','job':'stu'}
  
  ###【元祖字典的】【拆包】
  a=(1,2,3)
  def func(*args):
      print(args)
  func(a) # => ((1,2,3),) 没有*当作一个值,有*拆成N个值传入
  func(*a) # => (1,2,3) 【拆包,拆成一个一个的值】 字典 传入 **a
5.2 函数式编程
5.2.1 匿名函数
  >>> func = lambda x : x*2 #分号前是参数,分号后是表达式,不用return,自动返回后面的值
  >>> func(2) #=> 4
  ###【简单应用,字典排序,匿名函数作实参】
  info = [{'name':'bin','age':19},{'name':'jin','age':19},{'son':'sname','age':1}]
  info.sort(key=lambda x:x['name'])
  print(info)
5.2.2 高阶函数
就是函数名可以作为参数使用
  ### map(func,seq) 将函数func作用于序列seq的每个元素,并返回一个迭代器
  >>> list(map(lambda x:x*2,[1,2,3])) # => [2,4,6]
  
  ### reduce(func,seq)  把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
  ###reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
  >>> from functools import reduce
  >>> def fn(x, y):
  ...     return x * 10 + y
  ...
  >>> reduce(fn, [1, 3, 5, 7, 9])
  13579
  
  ###filter(func,seq)  filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
  def not_empty(s): #把列表的空字符串去掉
      return s and s.strip()
  
  list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
  # 结果: ['A', 'B', 'C']
  
  ###sorted(seq,key=None,reverse=False)
  >>> sorted([36, 5, -12, 9, -21])
  [-21, -12, 5, 9, 36]
  #还可以接收一个key函数来实现自定义的排序,key作用于每一个元素,并按作用后的seq排序
  >>> sorted([36, 5, -12, 9, -21], key=abs) 
  [5, 9, -12, -21, 36]
  
5.3 作用域
  a=1
  def aa():
      global a  #如果没有global a的话,想要在函数中对a这个全局变量修改,仅仅a=0还不够,因为a是个与全局
      a=0       #变量相同的局部变量,需要用 global a将他声明为全局变量,然后修改
  aa()
  print(a) # => 0
  
  ##如果列表和字典当作全局变量时,可以不用global,直接在函数内部修改。因为列表字典是可变类型可以直接修改
  l=[1,2,3]
  def a():
      l.append(4)
  a()
  print(l) #=> [1,2,3,4]
  ###---------
  a=100
  def test(a):
      a+=a
      print(a) #=>200 没用global,函数外a不变
  #-----------
  a=[100]
  def test(b): #b引用a指向的对象,如果对象是可变类型,下面可以修改全局变量,否则的话,重新指向复制的新的对象
      b+=b #=> 函数外:a => [100,100],
      b=b+b #=> [100]+[100]==>[100,100] 函数外:a => [100]。因为这里右侧新建了一个对象,b作为局部变量重新引用了一个新的对象。
      
      
  #----对象名搜寻顺序----
  #locals -> enclosing function -> globals -> builtins
  #局部       闭包的外函数的局部变量    全局          内建
5.4 闭包
闭包就是内部函数引用了外部函数的临时变量,并且外部函数返回了内部函数的引用
  def outer(x):
      def wrapper(y):
          print(x+y)
      return wrapper
  a = outer(1)#a现在是wrapper指向函数的引用
  a(1)#2
  a(2)#3
  
  ###【闭包无法修改外部函数的局部变量】
  def outer():
      n = 1
      def wrapper():
          n -= 1 #error,
          n = 2 #相当于新定义了一个局部变量 n = 2
      return wrapper
  
  ##通过nonlocal修改外部函数局部变量
  def outer():
      n = 1       #将n定义为列表也可以,解决这个问题
      def wrapper():
          nonlocal n
          n -= 1
          print(n)
      return wrapper
  a = outer()
  a()#输出0
  ###闭包执行完成后,仍然能保持住当前的执行环境
  a()#输出-1
  a()#输出-2
  
  
  ###【注意事项】
  # 当闭包内引用了一个后期会发生变化变量时
  # 1.
  def outer():
      a = 1
      def inner():
          print(a)
      a = 2
      return inner
  a = outer()
  a()#输出了2,因为inner后又修改了
  
  ## 2. 
  def outer():
      l = []
      for i in range(1,4):
          def inner():
              return i*i
          l.apend(inner)
      return l
  f1,f2,f3 = outer()
  print(f1(),f2(),f3())#9,9,9
  #原因就在于返回的函数引用了变量i,但返回的函数并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9
  
  #[解决:]
  def outer():
      def f(j):
          def inner():
              return j*j
          return inner
      fs = []
      for i in range(1, 4):
          fs.append(f(i)) # f(i)立刻被执行(是一个数值,而不是函数),因此i的当前值被传入f()
      return fs
5.5 装饰器
就是不修改原函数的情况下,添加新的功能
  ###【装饰器原理】
  def w1(func):
      def wrapper():
          print('这是新加功能')
          func()
      return wrapper
  
  def f1():
      print('---f1---')
  
  f1 = w1(f1)
  f1() # 将会添加一个print
  
  
  
  ### 【使用@】
   
                     
                    
                