python学习笔记09

一、上堂回顾

1.默写题目

1.封装函数,将某个字符串中的大写字母转为小写,小写字母转为大写,将新的字符串返回【参数使用默认参数】

#注意1 :明确是否需要设置参数和返回值
#注意2:默认参数操作的形参列表【关键字参数操作的是实参列表】
def customSawp(s="abc"):
  #注意3:在字符串的操作中,但凡涉及到更改字符串的操作,都会生成一个新的字符串
  newStr = s.swapcase()
  return newStr
  #ord()  chr()

2.封装函数,使用二分法在某个列表中查找指定元素,将索引返回,如果未查找到,则返回-1

#注意1 :明确是否需要设置参数和返回值
#以升序为例
def search(l,key):
  #注意2:二分法查找的条件:必须是有序的列表
  #注意3:二分法查找的思路:通过折半缩小查找范围【和中间下标对应的元素进行比对】
  left = 0
  right = len(l) -1
  #处理查找的过程
  while left <= right:
    #获取中间下标
    middle = (left + right) // 2
    if key > l[middle]:
      left = middle + 1
    elif key < l[middle]:
      right = middle - 1
    else:
     # print(middle)
      #break
      #注意4:return的作用:结束函数,携带返回值返回
      #注意5:break和return之间的区别
      return middle
    
"""
#处理查找不到的情况
 if left > right:
    return -1
 
 if key not in l:
    return -1
"""
    return -1

3.举例说明函数的特殊用法

def test():
  pass
#1.变量可以指向函数
f = test
f()
​
#2.函数名也是一个变量
test = 10
#test()
​
#3.函数可以作为参数使用
def fun(f):
  f()
  
fun(test)

4.已知列表list1 = [1,2,3,4,5],使用列表生成式生成一个新的列表,newList = [3,6,9,12,15]

#注意1:[需要生成的列表的元素规律  for循环  判断条件]
#注意2:for循环一般情况下是一个已知的列表
list1 = [1,2,3,4,5]
list2 = [i * 3 for i in list1]
​
#[2,4]
list3 = [i for i in list1 if i % 2 == 0]

2.知识点回顾

作业

def isPrime(num):
  result = True
  for i in range(2,num):
    if num % i == 0:
      result = False
      break
      
  if result and num != 1:
    return True
  else:
    return False
 
​
def getCount(n):
  c = 0
  for x in range(2,n + 1):
    if isPrime(x):
      c += 1      

二、变量的作用域

1.概念

1.1出现的原因

变量的作用域指的是一个变量可以被使用【访问】的范围

程序中的变量并不是在任何地方都可以访问的,访问权限取决于这个变量被定义在什么位置【直接定义,语句中,函数中】

1.2作用范围划分

分类:

a.L:Local,局部作用域

b.E:enclosing,函数作用域【体现在闭包中】

c.G:Global,全局作用域

d.B:Built-in,內建作用域【内置作用域】

1.3变量查找规则

L-->E--->G--->B

注意:全局作用于和內建作用域并没有严格的界限,主要由书写的先后顺序决定查找规则

代码演示:

#1.四种变量由不同的命名                                                 
num3 = 30     #全局作用域                                          
                                                              
num4 = int(2.9)   #内置作用域【系统内置功能返回的值赋值给一个变量】                   
                                                              
def outer():                                                  
    num1 = 10      #函数作用域                                     
    def inner():                                              
        num2 = 20   #局部作用域【局部作用域并不是绝对的】                       
        #结论:在闭包的内部函数中,可以访问全局,内置,函数                            
        print(num1,num2,num3,num4)                            
    return inner                                              
                                                              
f = outer()                                                   
f()                                                           
                                                              
#2.四种变量有相同的命名访问规则:                                            
#结论:如果所有的变量重名的情况下,就近原则                                        
x = 10                                                        
x = int(3.2)                                                  
                                                              
def outerFunc():                                              
    x2 = 20                                                   
    def innerFunc():                                          
        x1 = 30                                               
        print(x)                                              
    return innerFunc                                          
                                                              
f1 = outerFunc()                                              
f1()                                                          
                                                              
#注意:全局金额局部使用较多,在闭包存在的情况下使用到函数作用域                              
                                                              
                                                              
#3.注意问题                                                       
#if语句                                                         
if True:                                                      
    msg = "abc"                                               
print(msg)                                                    
                                                              
#while语句                                                      
n = 0                                                         
while  n < 2:                                                 
    msg1 = "fhajgh"                                           
    n += 1                                                    
print(msg1)                                                   
                                                              
#函数                                                           
def test():                                                   
    msg2 = "hello"                                            
#print(msg2)                                                  
                                                              
#结论:Python中只有模块【module】,类【class】和函数【def,lambda】 会引入新的作用域      
# 其他的代码块,比如if语句,while语句,for语句,try-except语句是不会引入新的作用域的         
# 【在这些语句中定义的变量,在语句外面也可以进行访问】                                  
                                                              
#在函数内部定义的变量,仅限于在函数内部使用,一旦出了函数,该变量则将不存在【内存中被销毁或者被释放】           
def show(a,b):                                                
    sum = a + b                                               
                                                              
show(10,20)                                                   
print(sum)                                                    

2.全局变量和局部变量

全局变量:变量定义在函数外面,在当前整个py文件中都可以任意访问

局部变量:变量定义在函数中,只能在当前函数中访问

代码演示:

#4.全局变量和局部变量                                 
total = 0      #全局变量                         
                                             
def sum(num1,num2):                          
    total = num1 + num2            #局部变量     
    print("函数内部的局部变量:",total)                
    print("全局变量:",total)                     
                                             
print("函数外部的全局变量:",total)                    
                                             
sum(10,20)                                   
                                             
#注意:尽量避免全局变量和局部变量重名的情况  【当重名,在函数内部会优先访问局部变量】 

3.global和nonlocal关键字的使用

3.1global

代码演示:

num = 1
def fun1():
    #需求:访问全局num
    #解决办法:在访问全局变量之前作出声明
    global num   #告诉编译器,此处的num是全局的
    print(num)     #1     #UnboundLocalError: local variable 'num' referenced before assignment
    num = 123
    print(num)   #123
​
fun1()
​
#如果在函数内部出现了和全局变量重名的局部变量,而在局部变量定义之前要访问全局变量,则需要使用global关键字对全局变量进行声明
​
a = 10
def test():
    global a
    a = a + 1
    print(a)
​
test()

3.2nonlocal

代码演示:

#注意;nonlocal使用在闭包中
#讨论变量名重名的情况
x = 0  #全局作用域
​
def outer():
    x = 1   #函数作用域
​
    def inner():
        #结论:将变量的局部作用域修改为函数作用域
        nonlocal x
        x = 2    #局部作用域
        print("inner:",x)
​
    inner()
​
    print("outer",x)
​
outer()
print("global",x)
​
"""
inner:2
outer:1   ----->2【添加nonlocal x的声明】
global:0
"""

三、迭代器

1.可迭代对象

概念:可以直接作用于for循环的对象【实体】被称为可迭代对象:Iterable

分类:可以直接作用于for循环的数据类型:

​ a.集合数据类型,包含list,tuple,dict,set,string

​ b.generator,包含()生成器和yield的生成器

判断:isinstance() 可以用来判断一个对象【实体】是否是可迭代对象

instance:对象,实体,实例

代码演示:

#第一步:导入模块
from collections  import  Iterable
#import  collections
​
#isinstance(数据,Iterable)
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({},Iterable))
print(isinstance(set([]),Iterable))
print(isinstance("hello",Iterable))
print(isinstance((x for x in range(10)),Iterable))
​
print(isinstance(10,Iterable))
print(isinstance(True,Iterable))

2.迭代器

概念:不但可以直接作用于for循环,还可以使用next()获取元素值,同时符合这两个条件的数据被称为迭代器【Iterator】

目前而言:只有生成器是迭代器

判断:isinstance() 可以用来判断一个对象【实体】是否是迭代器

代码演示:

from collections import  Iterator
​
​
#isinstance(数据,Iterable)
print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({},Iterator))
print(isinstance(set([]),Iterator))
print(isinstance("hello",Iterator))
print(isinstance((x for x in range(10)),Iterator))  #True
​
print(isinstance(10,Iterator))
print(isinstance(True,Iterator))
​
#可以使用iter()可以将可迭代对象转换为迭代器【除了生成器之外的可迭代对象】
#总结:可迭代对象不一定是迭代器,迭代器肯定是可迭代对象
list1 = [435,5,4]
a = iter(list1)
print(next(a))
​
#next()获取迭代器中的元素,当所有的元素获取完毕之后,继续调用next,会出现StopIteration
list2 = [435,5,4]
b = iter(list2)
#工作原理
while True:
    try:
        # 获取下一个值
        x = next(b)
    except StopIteration:
        print("元素已经获取完成")
        break
​
#等价于上面的while
for x in b:
    pass
​
#【面试题】:说明可迭代对象和迭代器之间的区别和联系

四、装饰器【掌握】

代码演示:

def now():
    print("拼搏到无能为力,坚持到感动自己")
​
#now()
#f = now   #变量可以指向函数,函数名也是一个变量,所以变量可以当做函数调用
#f()
​
#思考问题:给now函数增加功能,比如:求和,但是不能修改now函数----》装饰器
​
#概念:假设我们要增强now函数的功能,但是又不希望修改now函数,这种在代码运行期间动态给函数增加功能的的方式被称为装饰器
#本质:装饰器实际上就是一个闭包【将需要装饰的函数作为参数传给闭包,然后将装饰之后的结果返回】
#好处:在不用修改原代码前提下增加函数的功能【动态性】
#1.简单的装饰器
#a.书写闭包
#b.给外部函数设置参数
def outer(fun):
    def inner():
        #c.在内层函数中调用需要被装饰的函数
        fun()
        #d.增加新的功能
        print("hello world")
    return inner
​
#e.使用闭包
f = outer(now)    #函数可以作为参数使用
f()
​
#注意:增加的功能可以写在原函数调用的前面或者后面,没有严格的区分
#注意:outer被称为装饰器,inner被称为装饰器的工作核心
​
#练习:给下面的函数增加功能,打印九九乘法表
def show():
    for i in range(10):
        print(i)
​
show()
def outer1(f):
    def inner1():
        f()
        #增加新的功能
        for i in range(1,10):
            for j in range(1,i + 1):
                print("%dx%d=%d"%(j,i,i*j),end=" ")
            print("")
    return inner1
​
f1 = outer1(show)
f1()
​
​
#2.有参数的装饰器
def getAge(age):
    print(age)
​
#问题:使用getAge得到年龄,但是输入的是负数则会得到不符合常理的结果
getAge(10)   #10
getAge(-5)   #-5
​
#需求:在不修改原代码的基础上,进行数据的过滤:当用户输入的age为负数的时候 ,将其置为0
def wrapper(f):
    #注意;当原函数有参数,装饰器的作用是为了操作原函数中的参数,给inner设置参数
    def inner(num):
        #增加新的功能:过滤数据
        if num < 0:
            num = 0
        f(num)
    return  inner
​
f2 = wrapper(getAge)
f2(10)
f2(-5)
​
"""
总结:通过这样的方式,将边界检查的逻辑隔离到单独的函数中,一般使用装饰器操作
"""
​
#3.使用 @  标识符将装饰器直接应用到函数
#格式:@装饰器的名字【外部函数的函数名】
#注意;使用@之后,装饰器必须先被定义,然后再使用到原函数,此时原函数也相当于被增加新功能
def wrapper1(f):
    def inner(num):
        if num < 0:
            num = 0
        f(num)
    return  inner
​
@wrapper1
def getAge1(age):
    print(age)
​
getAge1(-5)
getAge(10)
​
#4.带有不定长参数的装饰器
def wrapper(fun):
    def inner(*args,**kargs):
​
        fun(*args,**kargs)
​
        print("hello")  #新功能
    return inner
​
@wrapper
def fun1(a,b):
    print(a + b)
fun1(10,20)
​
@wrapper
def fun2(a,b,c):
    print(a * b * c)
fun2(1,2,3)
​
#5.将多个装饰器应用在同一个函数上
def wrapper11(fun):
    def inner(*args,**kargs):
        fun(*args,**kargs)
        print("装饰器11~~~~")
    return inner
​
def wrapper12(fun):
    def inner(*args,**kargs):
        fun(*args,**kargs)
        print("装饰器12~~~~")
    return inner
​
@wrapper11
@wrapper12
def test():
    print("test")
test()
​
"""
test
装饰器12~~~~
装饰器11~~~
"""
​
"""
总结;
1.就近原则【多个装饰器同时出现,谁最后出现,则最先被执行】
2.多个装饰器应用于同一个函数的时候,原函数只被执行一次
"""

五、函数递归

1.概念

一个函数调用本身,被称为函数递归【递归调用】

递归包含了一种隐式的循环,它会重复执行某段代码,。但是这种重复无须用条件控制【但凡使用循环可以解决的问题,一般使用递归解决】

使用递归解决问题需要考虑的因素:

​ a.找到一个临界值【临界条件】

​ b.寻找相邻两次循环之间的关系【公式】

2.使用

1.斐波那契数列

2.求和

代码演示;

#斐波那契数列
"""
1 2 3 4 5 6  7  8  9  10
1,1,2,3,5,8,13,21,34,55,89....
需求:报一个数,输出在数列中对应的数
​
规律:
a.临界值:第一个位置和第二个位置上的数是固定的,都是1
b.公式:第n个位置上的数 = 第n - 1个位置上的数  + 第 n- 2位置上的数
​
num = 5
func(5) = func(4) + func(3)
func(5) = func(3) + func(2) +  func(2) + func(1)
func(5) = func(2) + fun(1)+ func(2) +  func(2) + func(1)  = 5
.....
func(n) = func(n - 1) + func(n - 2)
func(num) = func(num - 1) + func(num - 2)------>公式
"""
​
def func(num):
    if num == 1 or num == 2:
        return 1
    else:
        #都需要通过前面的两个位置上的数进行求和
        result = func(num - 1) + func(num - 2)
        print(num)
        return result
​
print(func(1))  #1
print(func(2))  #1
print(func(10))  #55
​
#使用递归:计算1~某个数之间所有整数的和
def func1(num):
    sum = 0
    n = 1
    while n <= num:
        sum += n
        n += 1
    return sum
print(func1(100))
​
"""
过程分析:求1~5之间的所有整数的和
1+2+3+4+5
sum(1) = 1
sum(2) = sum(1) + 2  = 1 + 2
sum(3) = sum(2) + 3 = sum(1) + 2 + 3  = 1 + 2 + 3
sum(4) = sum(3) + 4 = sum(1) + 2 + 3 + 4  = 1 + 2 + 3 + 4
​
....
sum(n) = sum(n - 1) + n  -----》公式
​
规律:
1.临界值:1
2.公式:sum(n) = sum(n - 1) + n
​
"""
def sum(num):
    if num == 1:
        return  1
    else:
        return sum(num - 1) + num
​
#总结:使用递归函数的好处代码简单,缺点:过深的调用会导致栈溢出【内存泄漏】

 

猜你喜欢

转载自blog.csdn.net/weixin_42569562/article/details/81436166