python基础笔记

基础语法

1.变量的命名
  • 如果设计多个单词,建议使用creat_sutdent,而不是CreatStudent,虽然后者也合法,但是不建议
  • 如果名字过长,可以缩写,然后在后面进行注释,如:ymd = “2021-11-3” #ymd is year_month_day
  • 多个一起赋值a, b, c = 2, 4, 5,等号左右数量要对应
2.字符串
  • id()方法可以查询变量的地址

  • dir()方法可以查询变量的所有方法

  • encode可以进行编码解码,将字符串转为bytes

  • 引号和双引号的配合使用:

    new_str = "hello world "" hhhhhh"  #不会报错
    new_str = "hello "world" hhhhhh"  #会报错,这种引号里夹引号的要用不同的引号"hello 'world' hhhhhh"
    print(new_str)
    
  • 字符串的max和min函数可以取出当前数据中的最大最小值
    print(max(“今天是11月3日!”)) #返回月

  • 字符串的capitalize方法,capitalize()将字符串的第一个字母变成大写,其他字母变小写。

    str = "this is string example from runoob....wow!!!"
    print ("str.capitalize() : ", str.capitalize())
    #结果:str.capitalize() :  This is string example from runoob....wow!!!
    
3.列表
  • 列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。

    print([1, 2, 3] + [4, 5, 6])	#结果是[1, 2, 3, 4, 5, 6],将两个列表组合
    print(['Hi!'] * 4)	#结果是	['Hi!', 'Hi!', 'Hi!', 'Hi!'],将['Hi!']列表乘以4次
    
  • 对于python列表+= 和+操作的一些区别:

    #方式一:+=的操作
    >>> a = []
    >>> a += "a"
    >>> a
    ["a"]
    
    #方式二:+的操作
    >>> a = []
    >>> a = a + "a"
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: can only concatenate list (not "str") to list
    >>>
    

    原因:
    python中列表的+=相当于执行的是extend(后续会讲extend和append的区别)操作,在上述代码中也就是将右侧的字符串"a"添加到了变量a中,所以命令行下调用a时,显示的是有一个值为"a"的列表;
    但是对列表执行+操作时,操作数必须是列表,所以就出现了上面的情况。而且+操作会生成一个新的对象,而+=还是操作的原来的对象,如:

    #方式一:+=的操作,列表前后地址相同,所以+=还是操作的原来的对象
    >>> a = [1]
    >>> id(a)
    2535493303944
    >>> a += [2,3,4]
    >>> a
    [1, 2, 3, 4]
    >>> id(a)
    2535493303944
    
    #方式二:+的操作,列表前后地址变化了,所以+操作会生成一个新的对象
    >>> a = [1]
    >>> id(a)
    2535493303944
    >>> a = a + [2,3,4]
    >>> a
    [1, 2, 3, 4]
    >>> id(a)
    2535493303752
    
  • 对于extend (扩展) 与 append (追加)与insert (插入)的区别:

    # extend (扩展) 操作:
    >>> li = ['a', 'b', 'c']  
    >>> li.extend(['d', 'e', 'f'])   
    >>> li  
    ['a', 'b', 'c', 'd', 'e', 'f']  
    >>> len(li)                      
    6  
    >>> li[-1]  
    'f'  
    
    # append (追加)操作:
    >>> li = ['a', 'b', 'c']  
    >>> li.append(['d', 'e', 'f'])   
    >>> li  
    ['a', 'b', 'c', ['d', 'e', 'f']]  
    >>> len(li)                      
    4  
    >>> li[-1]  
    ['d', 'e', 'f']
    
    # insert (插入)操作:
    >>> li = ['a', 'b', 'c']
    >>> li.insert(1, 'd')
    >>> li
    ['a', 'd', 'b', 'c']
    >>> li.insert(1, ['d','gggg'])
    >>> li
    ['a', ['d', 'gggg'], 'd', 'b', 'c']
    

    Lists 的两个方法 extend 和 append 看起来类似,但实际上完全不同。
    extend 接受一个参数,这个参数总是一个 list(extend只能接收列表),并且把这个 list 中的每个元素添加到原 list 中。
    append可以接收任何数据类型的参数,并将参数作为一个元素添加到原来的list。
    insert是将元素添加到指定index下,需要两个参数

  • 对于copy()和=赋值的区别:

    a = [1, 2, 3]
    b = a.copy()
    c = a
    a.append(4)
    print(a)		# [1, 2, 3, 4]
    print(b)		# [1, 2, 3]
    print(c)		# [1, 2, 3, 4]
    #原因:赋值的变量与原始变量享有相同的内存空间(a和c地址相同),而copy函数是创建新的列表(a和b地址不同)
    
  • 浅拷贝copy和深拷贝deepcopy:

    #但是!!!!如果列表a中还有一层列表,情况就特殊点
    #浅拷贝
    a = [[1, 2, 3], [6, 7, 8]]
    b = a.copy()
    b[0].append(4)  #对第二层元素进行操作
    print(a)  # [[1, 2, 3, 4], [6, 7, 8]]
    print(b)  # [[1, 2, 3, 4], [6, 7, 8]]
    #深拷贝
    import copy
    a = [[1, 2, 3], [6, 7, 8]]
    b = copy.deepcopy(a)	#深拷贝的调用必须导入copy模块使用,浅拷贝可以b = copy.copy(a),也可以a.copy()
    b[0].append(4)
    print(a)		#[[1, 2, 3], [6, 7, 8]]
    print(b)		#[[1, 2, 3, 4], [6, 7, 8]] 
    

    结论:深拷贝:与原始变量内存空间不相同,不共享数据。浅拷贝:浅拷贝是对最外层的数据创建一个新的内存空间来存储,而对内层的数据内存地址进行引用

4.字典
  • dict.keys()函数以列表返回一个字典所有的键。
    #dict.keys()是获取字典所有的key并返回一个伪列表,如果需要对列表进行操作需要用list()转换使用
    dict = {'Name': 'Zara', 'Age': 7}
    print("Value : %s" %  dict.keys())  #Value : ['Age', 'Name']
    print(type(dic.keys()))		#<class 'dict_keys'> 
    
  • dict.values()函数以列表返回一个字典所有的value。
    #dict.values()是获取字典所有的value并返回一个伪列表,如果需要对列表进行操作需要用list()转换使用
    dict = {'Name': 'Zara', 'Age': 7}
    print("Value : %s" % dict.values())  #Value : dict_values(['Zara', 7])
    print(type(dict.values()))		#<class 'dict_values'>
    
  • 对于字典value的访问,不建议使用dict[“key”],这样如果没有key会直接报错,
    因此建议使用dict.get(“key”)来操作,这样如果没有key不会报错,会返回None。
    #dict.get(key, default=None)
    dict = {'Name': 'Runoob', 'Age': 27}
    print("Value : %s" % dict.get('Age'))
    print("Value : %s" % dict.get('Sex', "Not Available"))
    print("Value : %s" % dict.get('Apple'))
    #key -- 字典中要查找的键。default -- 如果指定键的值不存在时,返回该默认值。
    #返回指定键的值,如果键不在字典中返回默认值 None 或者设置的默认值。
    #Value : 27
    #Value : Not Available
    #Value : None
    

流程控制与函数

1.集合常用方法
  • 集合的定义:集合(set)是一个无序的不重复元素序列,常用来对两个列表进行交并差的处理

  • 集合相关操作:

    >>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
    >>> print(basket)                      # 这里演示的是去重功能
    {'orange', 'banana', 'pear', 'apple'}
    >>> 'orange' in basket                 # 快速判断元素是否在集合内
    True
    >>> 'crabgrass' in basket
    False
    
    >>> # 下面展示两个集合间的运算. !!!必须两个都是集合!!!
    ...
    >>> a = set('abracadabra')
    >>> b = set('alacazam')
    >>> a                                  
    {'a', 'r', 'b', 'c', 'd'}
    >>> a - b                              # 集合a中包含而集合b中不包含的元素
    {'r', 'd', 'b'}
    >>> a | b                              # 集合a或b中包含的所有元素
    {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
    >>> a & b                              # 集合a和b中都包含了的元素
    {'a', 'c'}
    >>> a ^ b                              # 不同时包含于a和b的元素
    {'r', 'd', 'b', 'm', 'z', 'l'}
    
  • 添加元素

    #add添加方法	s.add(x)
    #将元素 x 添加到集合 s 中,如果元素已存在,则不进行任何操作。
    >>> thisset = set(("Google", "Runoob", "Taobao"))
    >>> thisset.add("Facebook")
    >>> print(thisset)
    {'Taobao', 'Facebook', 'Google', 'Runoob'}
    
    #update方法	 s.update(x)
    #x 可以有多个,用逗号分开。
    >>> thisset = set(("Google", "Runoob", "Taobao"))
    >>> thisset.update({1,3})
    >>> print(thisset)
    {1, 3, 'Google', 'Taobao', 'Runoob'}
    >>> thisset.update([1,4],[5,6])  
    >>> print(thisset)
    {1, 3, 4, 5, 6, 'Google', 'Taobao', 'Runoob'}
    >>>
    
  • 删除元素

    #remove方法	s.remove(x)
    #将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。
    >>> thisset = set(("Google", "Runoob", "Taobao"))
    >>> thisset.remove("Taobao")
    >>> print(thisset)
    {'Google', 'Runoob'}
    >>> thisset.remove("Facebook")   # 不存在会发生错误
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'Facebook'
    >>>
    
    #discard方法	s.discard(x)
    #如果元素不存在,不会发生错误
    >>> thisset = set(("Google", "Runoob", "Taobao"))
    >>> thisset.discard("Facebook")  # 不存在不会发生错误
    >>> print(thisset)
    {'Taobao', 'Google', 'Runoob'}
    
    #pop方法	s.pop()
    #随机删除集合中的一个元素
    thisset = set(("Google", "Runoob", "Taobao", "Facebook"))
    x = thisset.pop()
    
    print(x)  #x为Runoob(被pop出来的元素)
    #多次执行测试结果都不一样。
    #set 集合的 pop 方法会对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除。
    
  • 求差集

    #set.difference(set)
    x = {"apple", "banana", "cherry"}
    y = {"google", "microsoft", "apple"}
    
    #返回一个集合,元素包含在集合x,但不在集合y
    z = x.difference(y)
    print(z)		#{'cherry', 'banana'}
    
  • 求交集

    #set.intersection(set1, set2 ... etc)  可以多个参数
    #set1 -- 必需,要查找相同元素的集合
    #set2 -- 可选,其他要查找相同元素的集合,可以多个,多个使用逗号 , 隔开
    
    x = {"apple", "banana", "cherry"}
    y = {"google", "runoob", "apple"}
    a = {"hello", "apple", "google"}
    
    #返回一个新集合,该集合的元素既包含在集合x又包含在集合y和a中
    z = x.intersection(y, a) 
    print(z)	#{'apple', 'google'}
    
  • 求并集

    #set.union(set1, set2...)		可以多个参数
    #set1 -- 必需,合并的目标集合
    #set2 -- 可选,其他要合并的集合,可以多个,多个使用逗号 , 隔开。
    
    x = {"apple", "banana", "cherry"}
    y = {"google", "runoob", "apple"}
    a = {"hello", "runoob", "Google"}
    z = x.union(y, a) 
    
    #合并多个集合,重复元素只会出现一次:
    print(z) #{'cherry', 'apple', 'runoob', 'banana', 'Google', 'hello', 'google'}
    
  • 是否包含

    #set.isdisjoint(set)
    x = {"apple", "banana", "cherry"}
    y = {"google", "runoob", "facebook"}
    
    #判断集合y中是否有包含集合x的元素
    #返回布尔值,如果不包含返回 True,否则返回 False。
    z = x.isdisjoint(y)
    print(z) #True	因此y中不包含x
    
2.for循环
  • 使用for循环删除列表中的偶数

    list_1 = [3, 6, 8, 9, 25, 36, 100, 105]
        for item in list_1:
            if(item % 2 == 0):
                list_1.remove(item)
        print(list_1)
    
    #result:[3, 8, 9, 25, 100, 105]
    #结果中却还有偶数,因为remove删掉一个元素后,后面的元素会自动覆盖到前一个位置,因此6后面的8就逃过一劫,36后面的100同理
    

    如何解决呢?

    list_1 = [3, 6, 8, 9, 25, 36, 100, 105]
        for item in list_1[::-1]:
            if(item % 2 == 0):
                list_1.remove(item)
        print(list_1)
    
    #result:[3, 9, 25, 105]
    #逆序遍历即可。逆序表示为list[::-1]
    
3.while循环
  • 推导式 难点

    # 列表推导式,20以内所有偶数的平方 
    print([x ** 2 for x in range(20) if x % 2 == 0]) 
    # 运行结果:[0, 4, 16, 36, 64, 100, 144, 196, 256, 324]
    
    # 元组推导式
    print(tuple(x for x in range(10)))  # 结果是生成器对象,使用tuple()函数将其转换为元组 
    # 运行结果:(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    
    # 字典推导式 
    print({x:x**2 for x in range(10)}) 
    # 运行结果:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
    
    # 集合推导式 
    print({x for x in range(10)}) 
    # 运行结果:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    
    #一行实现99乘法表
    print("\n".join("\t".join(["%s*%s=%s" % (x, y, x * y) for y in range(1, x + 1)]) for x in range(1, 10)))
    
4.函数
  • 函数的参数

    #*args与**kwargs是可变类型且*args将参数封装成元组类型,**kwargs将参数封装成字典类型
    def seq(num, num1, num2):
        if num < 88:
            return num1 * num2
        else:
            return num1 + num2
    if __name__ == '__main__':
        # 定义变量tuple1的值为元组(5,2,1)
        tuple1 = (5,2,1)
        
        # *******使用*tuple1可实现对元组tuple1对解包******
        print(*tuple1)		#result: 5 2 1
        
        # 调用函数,传入参数tuple1,并打印函数返回值
        print(seq(*tuple1))  #相当于print(seq(5, 2, 1))
    
  • 综合例子,特别注意!!

    # 带一个*的是元组,带两个星号的是字典。
    def total(a=5, *tuple_num, **dic_id):
        print(type(tuple_num), tuple_num)
        print(type(dic_id), dic_id)
        print('a', a)
        for single_item in tuple_num:
            print('single_item', single_item)
        for key, value in dic_id.items():
            print(key, value)
    
    total(10, 1, 2, 3, Jack=1123, John=2231, Inge=1560)
    
    """result:
    <class 'tuple'> (1, 2, 3)
    <class 'dict'> {'Jack': 1123, 'John': 2231, 'Inge': 1560}
    a 10
    single_item 1
    single_item 2
    single_item 3
    Jack 1123
    John 2231
    Inge 1560
    """
    
  • 函数定义的高级用法(python3.7后才加入)

    def run(name: str, age: int = 33) -> str:
      """
      表示name参数类型为字符串,age参数类型为整型,返回值类型为字符串
      """
        print(name, age)
        return name
    
    run("zhsngsan", 22)
    
  • 全局变量和局部变量

    局部变量:
    1.定义在函数内部的变量称为局部变量(函数的形参也是局部变量)

    ​ 2.局部变量只能在函数内部使用

    ​ 3.局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁

    全局变量:
    1.定义在函数外部,模块内部的变量称为全局变量

    ​ 2.全局变量,所有函数可以直接访问(但函数内部不能直接修改全局变量的绑定关系)

面向对象

1.对象的基础
  • 对象的生命周期

    class class_name(object):
      # 可以在pass里添加动作,达到重写方法的作用
        def __init__(self):
          # 这个是构造函数,具有初始化的作用,也就是当该类被实例化的时候就会执行该函数
            pass
             
        def __del__(self):
          # 这个是析构函数,当使用del删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。
            pass
    
  • 私有函数和变量

    # 1、 _xx 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。若内部变量标示,如: 当使用“from M import”时,不会将以一个下划线开头的对象引入 。
    
    # 2、 __xx 双下划线的表示的是私有类型的变量。只能允许这个类本身进行访问了,连子类也不可以用于命名一个类属性(类变量),调用时名字被改变(在类FooBar内部,__boo变成_FooBar__boo,如self._FooBar__boo)
    
    # 3、 __xx__定义的是特列方法。用户控制的命名空间内的变量或是属性,如init , __import__或是file 。只有当文档有说明时使用,不要自己定义这类变量。 (就是说这些是python内部定义的变量名)
    
    class Cat(object):
        __cat_type = 'cat'  # 创建私有属性
    
        def __init__(self, name, sex):
            self.name = name
            self.__sex = sex  # 构造函数内创建私有属性
    
        def run(self):
            result = self.__run()
            print(result)
    
        def __run(self):
            return f'{self.__cat_type} 小猫 {self.name} {self.__sex}开心地奔跑着'
    
        def jump(self):
            result = self.__jump()
            print(result)
    
        def __jump(self):
            return f'{self.__cat_type} 小猫 {self.name} {self.__sex} 开心地跳着'
    
    cat = Cat(name='花生', sex='boy')
    cat.run()
    cat.jump()
    # cat.__run()  # 会报错
    print(dir(cat))
    
    print(cat._Cat__jump())  # 这样可以调用私有函数
    # print(cat.__sex)  # 会报错
    print(cat._Cat__sex)
    
    """ result
    cat 小猫 花生 boy开心地奔跑着
    cat 小猫 花生 boy 开心地跳着
    ['_Cat__cat_type', '_Cat__jump', '_Cat__run', '_Cat__sex', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'jump', 'name', 'run']
    cat 小猫 花生 boy 开心地跳着
    boy
    """
    
2.装饰器的基本概念
  • 装饰器的概念

    理解装饰器的前提**:1.所有东西都是对象(函数可以当做对象传递) 2.闭包**

    闭包的概念:
    1)函数嵌套
    2)内部函数使用外部函数的变量
    3)外部函数的返回值为内部函数

    下面写一个最为简单的闭包的例子:

    def test(name):
        def test_in():
            print(name)
        return test_in
    
    func = test('whyz')
    func()
    

    装饰器的原型:

    import time
    def showtime(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            print('spend is {}'.format(end_time - start_time))
        return wrapper
    
    def foo():
        print('foo..')
        time.sleep(3)
    
    foo = showtime(foo)
    foo()
    

    不带参数的装饰器:(装饰器,被装饰函数都不带参数)

    import time
    def showtime(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            print('spend is {}'.format(end_time - start_time))
        return wrapper
    
    @showtime  #foo = showtime(foo)
    def foo():
        print('foo..')
        time.sleep(3)
    
    @showtime #doo = showtime(doo)
    def doo():
        print('doo..')
        time.sleep(2)
        
    foo()
    doo()
    

    带参数的被装饰的函数

    import time
    def showtime(func):
        def wrapper(a, b):
            start_time = time.time()
            func(a,b)
            end_time = time.time()
            print('spend is {}'.format(end_time - start_time))
        return wrapper
    
    @showtime #add = showtime(add)
    def add(a, b):
        print(a+b)
        time.sleep(1)
    
    @showtime #sub = showtime(sub)
    def sub(a,b):
        print(a-b)
        time.sleep(1)
    
    add(5,4)
    sub(3,2)
    

    带参数的装饰器(装饰函数),

    实际是对原有装饰器的一个函数的封装,并返回一个装饰器(一个含有参数的闭包函数),
    当使用@time_logger(3)调用的时候,Python能发现这一层封装,并将参数传递到装饰器的环境去

     1 import time
     2 def time_logger(flag = 0):
     3     def showtime(func):
     4         def wrapper(a, b):
     5             start_time = time.time()
     6             func(a,b)
     7             end_time = time.time()
     8             print('spend is {}'.format(end_time - start_time))
     9             
    10             if flag:
    11                 print('将此操作保留至日志')
    12 
    13         return wrapper
    14 
    15     return showtime
    16 
    17 @time_logger(2)  #得到闭包函数showtime,add = showtime(add)
    18 def add(a, b):
    19     print(a+b)
    20     time.sleep(1)
    21 
    22 add(3,4)
    

    类装饰器:一般依靠类内部的__call__方法

     1 import time
     2 class Foo(object):
     3     def __init__(self, func):
     4         self._func = func
     5 
     6     def __call__(self):
     7         start_time = time.time()
     8         self._func()
     9         end_time = time.time()
    10         print('spend is {}'.format(end_time - start_time))
    11 
    12 @Foo  #bar = Foo(bar)
    13 def bar():
    14     print('bar..')
    15     time.sleep(2)
    16 
    17 bar()
    

    使用装饰器的缺点:

    1.位置错误的代码->不要在装饰器之外添加逻辑功能
    2.不能装饰@staticmethod 或者 @classmethod已经装饰过的方法
    3.装饰器会对原函数的元信息进行更改,比如函数的docstring,name,参数列表:

    下面对装饰器第第三个缺点进行剖析,

     1 import time
     2 def showtime(func):
     3     def wrapper():
     4         start_time = time.time()
     5         func()
     6         end_time = time.time()
     7         print('spend is {}'.format(end_time - start_time))
     8 
     9     return wrapper
    10 
    11 @showtime  #foo = showtime(foo)
    12 def foo():
    13     print('foo..')
    14     time.sleep(3)
    15 
    16 def doo():
    17     print('doo..')
    18     time.sleep(2)
    19 
    20 print(foo.__name__)
    21 print(doo.__name__)
    

    结果为:

    wrapper
    doo
    

    由此可以看出,装饰器会对原函数的元信息进行更改,可以使用wraps,进行原函数信息的添加

    注解:wraps本身也是一个装饰器,他能把函数的元信息拷贝到装饰器函数中**使得装饰器函数与原函数有一样的元信息

    以下是一个wraps的例子:

     1 import time
     2 from functools import wraps
     3 def showtime(func):
     4 
     5     @wraps(func)    
     6     def wrapper():
     7         start_time = time.time()
     8         func()
     9         end_time = time.time()
    10         print('spend is {}'.format(end_time - start_time))
    11 
    12     return wrapper
    13 
    14 @showtime  #foo = showtime(foo)
    15 def foo():
    16     print('foo..')
    17     time.sleep(3)
    18 
    19 def doo():
    20     print('doo..')
    21     time.sleep(2)
    22 
    23 print(foo.__name__)
    24 print(doo.__name__)
    

    结果为:

    foo
    doo
    

    常用的内置装饰器:1.staticmethod: 类似实现了静态方法 注入以后,可以直接 : 类名.方法

    *2.property:经过property装饰过的函数 不再是一个函数,而是一个property,*类似实现get,set方法

    1 @property
    2 def width(self):
    3 return self.__width
    4 
    5 @width.setter
    6 def width(self, newWidth):
    7 self.__width = newWidth
    

    3.classmethod: 与staticmethod很相似,貌似就只有这一点区别:
    第一个参数需要是表示自身类的 cls 参数,
    可以来调用类的属性,类的方法,实例化对象等。

3.常见的装饰器及功能
  • classmethod

    将类函数可以不经过实例化而直接被调用(类方法)

    class A(object):
        # 属性默认为类属性(可以给直接被类本身调用)
        num = "类属性"
    
        # 实例化方法(必须实例化类之后才能被调用)
        def func1(self): # self : 表示实例化类后的地址id
            print("func1")
            print(self)
        
        # 类方法,必须@classmethod和cls配套使用
        @classmethod # 类方法(不需要实例化类就可以被类本身调用)
        def func2(cls):  # cls : 表示没用被实例化的类本身,cls替代普通函数中的self
            print("func2")
            print(cls)
            print(cls.num)  # 直接通过cls调用类属性和方法
            cls().func1()
    
        # 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准)
        def func3():
            print("func3")
            print(A.num) # 属性是可以直接用类本身调用的
        
    # A.func1() 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
    A.func2()
    A.func3()
    
  • staticmethod

    class A(object):
        def m1(self, n):
            print("self:", self)
    
        @classmethod
        def m2(cls, n):
            print("cls:", cls)
    
        @staticmethod
        def m3(n):
            pass
    
    a = A()
    a.m1(1) # self: <__main__.A object at 0x000001E596E41A90>
    A.m2(1) # cls: <class '__main__.A'>
    A.m3(1)
    

    在类中一共定义了3个方法。

    m1 是实例方法,第一个参数必须是 self(约定俗成的)。

    m2 是类方法,第一个参数必须是cls(同样是约定俗成)。

    m3 是静态方法,参数根据业务需求定,可有可无。当程序运行时,大概发生了这么几件事(结合下面的图来看)。

    第一步:代码从第一行开始执行 class 命令,此时会创建一个类 A 对象(没错,类也是对象,一切皆对象嘛)同时初始化类里面的属性和方法,记住,此刻实例对象还没创建出来。

    第二、三步:接着执行 a=A(),系统自动调用类的构造器,构造出实例对象 a

    第四步:接着调用 a.m1(1) ,m1 是实例方法,内部会自动把实例对象传递给 self 参数进行绑定,也就是说, self 和 a 指向的都是同一个实例对象。

    第五步:调用A.m2(1)时,python内部隐式地把类对象传递给 cls 参数,cls 和 A 都指向类对象。

4.继承
  • 继承

    继承是一种类间关系,描述一个类从另一个类获取成员信息的类间关系。

    继承必定发生在两个类之间,参与继承关系的双方成为是父类和子类。

    父类提供成员信息,子类获取成员信息。

    子类可以添加父类没的成员

    父类私有成员不可被继承

    # 父类
    class Father(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def hello(self):
            print("hello,武汉加油,我是%s" % self.name)
    
    # 子类继承父类·
    class Son(Father):
        def sing(self):
            print("我是{},我今年{}岁,我会唱歌".format(self.name, self.age))
            self.hello()
    
    son1 = Son(name="小明", age=23)
    son1.sing()
    son1.hello()
    # 我是小明,我今年23岁,我会唱歌
    # hello,武汉加油,我是小明
    # hello,武汉加油,我是小明
    
5.多态
  • 不同的子类对象调用相同的父类方法,产生不同的执行结果

    子类重写父类的方法

    # 先继承,再重构(重写)
    class Person(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.sex = "normal"
    
        def talk(self):
            print("person is talking")
    
    
    class BlackPerson(Person):
        def __init__(self, name, age, strength):   # 先继承,再重构(重写)
            Person.__init__(self, name, age)  # 把子类实例传到父类(父类引用指向子类对象)
            print(self.name, self.age, self.sex)
            print(strength)
    
        def talk(self):		# 相同的talk,父子执行的东西不同,就叫多态
            print("BlackPerson is talking")
    
        def walk(self):
            print("BlackPerson is walking")
           
    b = BlackPerson("will smith", 30, "strong")
    b.talk()
    b.walk()
    
    # will smith 30 normal
    # strong
    # BlackPerson is talking
    # BlackPerson is walking
    
  • super()用法总结:
    super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题

    用super()而不是直接用类名调用父类方法的好处是不用管父类的名字。即使父类改名了,super()的调用依然有效

    使用super()进行父类方法和属性的调用是个好习惯

    # 单继承方式
    class Animal(object):  # 创建动物类
        """动物类"""
        def __init__(self, name):  # 初始化方法
            self.name = name
    
        def eat(self):  # 定义吃食物方法
            print('%s正在吃食物' % self.name)
    
        def play(self):  # 定义玩耍方法
            print('%s正在玩' % self.name)
    
        def sleep(self):  # 定义休息方法
            print('%s正在休息' % self.name)
    
           
    class Dog(Animal):
        """狗类"""
        def __init__(self, name):
            super().__init__(name)              # 定义基类的初始化方法
            print('这是一只%s' % self.name)
    
        def eat(self):                          # 定义狗吃食物的方法
            print('%s正在吃狗粮' % self.name)
    
        def bark(self):                         # 定义狗叫的方法
            print('%s会汪汪叫' % self.name)
    
    dog = Dog('哈士奇')                        # 创建动物类的实例
    dog.eat()                                 # 调用吃食物的方法
    dog.play()                                # 调用玩耍的方法
    dog.bark()                                # 调用狗叫的方法
    
    # 这是一只哈士奇
    # 哈士奇正在吃狗粮
    # 哈士奇正在玩
    # 哈士奇会汪汪叫
    
    # 多继承方式
    class Food(object):
        """实物类"""
        def __init__(self, name):
            print('%s是食物' % name)
    
            
    class Vegetables(Food):
        """蔬菜类"""
        def __init__(self, Vname):
            print('%s是蔬菜' % Vname)
            super().__init__(Vname)
    
    
    class Fruit(Food):
        """水果类"""
        def __init__(self, Fname):
            print('%s是水果' % Fname)
            super().__init__(Fname)
    
    
    class Tomato(Fruit, Vegetables):
        """西红柿类"""
        def __init__(self):
            print('西红柿即是蔬菜又是水果')
            super().__init__('西红柿')
    
    
    print(Tomato.__mro__)		# MRO 列表顺序,即Tomato类继承父类的顺序
    tomato = Tomato()           # 实例化西红柿类
    
    # (<class '__main__.Tomato'>, <class '__main__.Fruit'>, <class '__main__.Vegetables'>, <class '__main__.Food'>, <class 'object'>)
    # 西红柿即是蔬菜又是水果
    # 西红柿是水果
    # 西红柿是蔬菜
    # 西红柿是食物
    
6.类的高级函数
  • __str____getattr____setattr____call__函数

    class Test(object):
    		def __str__(self):
        		"""	如果定义了该函数,当print当前实例化对象的时候,会返回该函数的return信息
    						可用于定义当前类的描述信息"""
            return "这是这个类的描述信息"
    
        def __getattr__(self, item):
        		"""	当调用的属性或者方法不存在时,会返回该方法定义的信息"""
            return "这个item:{}不存在".format(item)
    
        def __setattr__(self, key, value):
            """拦截当前类中不存在的属性与值"""
            self.__dict__[key] = value
            print(self.__dict__)
    
        def __call__(self, *args, **kwargs):
            """本质是将一个类变成一个函数"""
            print("call函数:{}被调用".format(*args))
    
    t = Test()
    print(t)
    print(t.a)
    t.name = "tom"
    print(t.name)
    t("hello")
    
    """
    	这是这个类的描述信息
    	这个item:a不存在
    	{'name': 'tom'}
    	tom
    	call函数:hello被调用
    """
    
  • 实现上述几个方法的链式操作

    class Test2(object):
        def __init__(self, attr=''):
            self.__attr = attr
     
        def __call__(self, name):
            print('key is {}'.format(self.__attr))
            return name
     
        def __getattr__(self, key):
            if self.__attr:
                key = '{}.{}'.format(self.__attr, key)
            else:
                key = key
            print("=======",key)
            return Test2(key)  # 递归操作
     
    t2 = Test2()
    print(t2.a.c('insane'))
    
    # ======= a
    # ======= a.c
    # key is a.c
    # insane
    

异常处理

  • 1.try-except

    """
    try:
        有可能出现异常的代码
    except 异常类型 as 变量
    		处理后的代码
    """
    def test():
        try:
            print(a)
        except Exception as e:
            print("Exception: {}".format(e))
    
    test()
    
    # Exception: name 'a' is not defined
    
  • 2.try-except-except(捕获多个异常,如果前面就捕获到了,后面的except就不执行,类似于if else)

    def test():
        try:
            a = 1 / 0
            print(a)
        except NameError as e:   # 第一种写法,用as e把错误赋值给e
            print("NameError:{}".format(e))
        except ZeroDivisionError:		# 第二种写法,不写as 自定义输出报错内容
            print("ZeroDivisionError: 除数不能为0")
    
    test()
    
    # ZeroDivisionError: 除数不能为0
    
  • 3.try-except-else

    else 与 return 的执行顺序,有return时else是不执行的.无return时, 正常执行else如果发生异常则不执行else

    如果没有异常,则执行else里面的代码,例如:

    def test():
        try:
            a = 10
        except (NameError, ZeroDivisionError) as e:   # 用元组把可能报错的异常类型囊括进去,避免写多行except
            print("Error:{}".format(e))
        else:
            print("No Error :{}".format(a))
           
    test() 
    
    # No Error :10
    
  • 4.try-except-finally

    不管代码是否有异常,最后都会执行finally里面的代码。

    finally 与 return 的执行顺序,即使有return也要执行finally的, 而且是在return 之前执行它

    def test():
        try:
            a = 10
            1 / 0
        except (NameError, ZeroDivisionError) as e:
            print("{}, {}".format(type(e), e))
        finally:
            print("Process over!!")
     
    test()
    
    # <class 'ZeroDivisionError'>, division by zero
    # Process over!!
    
  • 自定义异常

    自定义异常可用于引发一个异常(抛出一个异常),由关键字raise引发。

    class MyError(Exception):   # 自定义异常,继承Exception类
        def __init__(self, length, min_len):
            self.length = length
            self.min_len = min_len
    
        def __str__(self):
            return "你输入的长度是%s,不能少于%s" % (self.length, self.min_len)
    
    
    def main():
        try:
            con = input("请输入密码:")
            l = len(con)
            if l < 6:
                raise MyError(l, 6)  # raise抛出异常,raise+异常类型(message)
        except Exception as e:
            print(e)
        else:
            print("您的密码输入完毕")
      
     main()
    
    # 请输入密码:2
    # 你输入的长度是1,不能少于6
    
    class MyError(Exception):   # 自定义异常,继承Exception类
        def __init__(self, length, min_len):
            self.length = length
            self.min_len = min_len
    
        def __str__(self):
            return "你输入的长度是%s,不能少于%s" % (self.length, self.min_len)
    
    def test():
        con = input("请输入密码:")
        l = len(con)
        if l < 6:
            raise MyError(l, 6)
       
    test()
    
    """请输入密码:123
    Traceback (most recent call last):
      File "/Users/Yang/Documents/Python-Study/全能工程师/01-python基础/exam.py", line 43, in <module>
        test()
      File "/Users/Yang/Documents/Python-Study/全能工程师/01-python基础/exam.py", line 27, in test
        raise MyError(l, 6)
    __main__.MyError: 你输入的长度是3,不能少于6"""
    
  • assert(断言)

    assert断言函数是对表达式布尔值的判断,要求表达式计算值必须为真,如果表达式为假,触发异常;如果表达式为真,不执行任何操作

    函数原型:assert expression

    assert expression
    
    等价于下面的个句式:
    if __debug__:
        if not expression: raise AssertionError
    
    assert也可以用于多个表达式的断言:
    assert expression1, expression2
    

    应用场景

    通常情况传递参数不会有误,但编写大量的参数检查影响编程效率,而且不需要检查参数的合法性。

    排除非预期的结果。

    # 1.判断
    assert 1==2, '1 不等于 2'   # 如果1==2正常,否则抛出异常1 不等于 2
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # AssertionError: 1 不等于 2
    
    # 2.函数的参数检查
    def check_user_info(self, **kwargs):
      	assert len(kwargs) == 4, '参数必须是4个'   # 参数必须是4个,否则异常
    
    # 3.只在Linux下运行
    import sys
    assert ('linux' in sys.platform), "该代码只能在 Linux 下执行"  # 如果系统是Linux正常运行,否则异常
    

模块与文件

1.模块和包
  • 模块(Module)和包(Package)

    # 模块:一个包含所有你定义的函数和变量的文件,其后缀名是 .py ,一个.py文件就是一个模块
    # 包:一定包含 __init__.py模块 的文件夹,一般也会包含其他一些模块和子包
    # 库(lib):库是完成一定功能的代码集合,具体表现可以是包,也可以是一个模块
    # 框架(framework):为解决一个开放性问题而设计的具有一定约束性的支撑结构
    # python内置了一些库,除此之外,还有其他人自己做的一些库,称之为第三方库
    
    # 包和模块导入都是用import
    import package
    # 只会拿到对应包下的__init__中的功能或者当前模块下的功能
    
    # 从包中导入特定模块
    form package import module
    # package:包的来源.  module:目标模块
    form package import module as test # 将导入的模块名改为test
    
    # time模块
    import time
    print(time.ctime())
    # Tue Nov 16 12:40:44 2021
    
  • os模块

    import os
    os.getcwd() 							# 获取当前工作目录
    os.chdir("../test") 			# 改变当前脚本工作目录,相当于shell下的cd命令
    os.rename("毕业论文.txt","毕业论文最终版.txt") # 重新命名文件
    os.remove("毕业论文.txt")  # 删除文件
    os.rmdir("demo") 					# 删除空文件夹
    os.removedirs("demo") 		# 删除空文件夹
    os.mkdir("demo") 					# 创建一个文件夹
    os.listdir("/Documents") 	# 列出文件夹目录里所有的文件和文件夹
    os.chdir("/Documents") 		# 切换到工作目录
    os.name 									# nt -> windows posix -> Linux/Unix或者MacOs
    os.environ 								# 获取到环境配置
    os.environ.get("PATH") 		# 获取到指令路径的环境配置
    
    os.path.abspath(path=) 		# 获取path规范会的绝对路径
    os.path.exists(path=) 		# 如果path存在,返回True
    os.path.isdir(path=) 			# 如果path是文件夹,返回True
    os.path.isfile(path=) 		# 如果path是文件,返回True
    os.path.splitext(path=) 	# 用来将指定路径进行分割,可以获取到文件的后缀名
    
  • sys模块

    import sys
    sys.path() 			# 将你的模块放在这些路径里面,就能用import导入
    """ ['/opt/homebrew/bin',
    '/opt/homebrew/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python39.zip', '/opt/homebrew/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9', '/opt/homebrew/Cellar/python@3.9/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload', '', '/opt/homebrew/lib/python3.9/site-packages', '/opt/homebrew/lib/python3.9/site-packages/IPython/extensions', '/Users/Yang/.ipython']
     """
    
    sys.argv 				# 传递给Python脚本的命令行参数列表
    sys.exit(code) 	# 让程序以指定的退出码结束
    sys.stdin		 		# 可以像input一样,接收用户的输入。
    sys.stdout 			# 标准输出。可以通过修改它来改变默认输出
    sys.stderr 			# 错误输出。可以通过修改它来改变错误输出
    
  • Pexpect模块

    ​ Pexpect 是一个用来启动子程序并对其进行自动控制的纯 Python 模块。 Pexpect 可以用来和像 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。继第一部分《探索 Pexpect,第 1 部分:剖析 Pexpect 》介绍了 Pexpect 的基础和如何使用后,本文将结合具体实例入手,详细介绍 Pexpect 的用法和在实际应用中的注意点。

    详见:https://www.cnblogs.com/mmdln/p/9006274.html

2.文件操作
  • 文件创建和写入

    详见:https://cloud.tencent.com/developer/article/1570492

3.常用函数与高阶函数
  • 加密模块hashlib与base64

    详见:https://www.cnblogs.com/xiao-apple36/p/8744213.html

  • logging模块

    logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:

    • 可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;
    • print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么地方,以及怎么输出。

    详见:https://www.cnblogs.com/Nicholas0707/p/9021672.html

    第一种使用方式:简单配置

    import logging
    LOG_FORMAT = "%(asctime)s %(name)s %(levelname)s %(pathname)s %(message)s "     # 配置输出日志格式
    DATE_FORMAT = "%Y-%m-%d  %H:%M:%S %a "      # 配置输出时间的格式,注意月份和天数不要搞乱了
    
    # logging.basicConfig()函数可以调整日志级别、输出格式等
    logging.basicConfig(level=logging.DEBUG,
                        format=LOG_FORMAT,
                        datefmt=DATE_FORMAT,
                        filename=r"./test.log"      # 有了filename参数就直接写入文件而不是终端
                        )
    
    logging.debug("msg1")
    logging.info("msg2")
    logging.warning("msg3")
    logging.error("msg4")
    logging.critical("msg5")
    
    """
    logging.basicConfig()函数是一个一次性的简单配置工具使,也就是说只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作的,多次调用的设置并不是累加操作。"""
    

    第二种使用方式:日志流处理流程

    import logging
    def log():
        #创建logger,如果参数为空则返回root logger
        logger = logging.getLogger("nick")
        logger.setLevel(logging.DEBUG)  #设置logger日志等级
        #这里进行判断,如果logger.handlers列表为空,则添加,否则,直接去写日志
        if not logger.handlers:
            #创建handler
            fh = logging.FileHandler("test.log",encoding="utf-8")
            ch = logging.StreamHandler()
            
            #设置输出日志格式
            formatter = logging.Formatter(
                fmt="%(asctime)s %(name)s %(filename)s %(message)s",
                datefmt="%Y/%m/%d %X"
                )
            
            #为handler指定输出格式
            fh.setFormatter(formatter)
            ch.setFormatter(formatter)
    
            #为logger添加的日志处理器
            logger.addHandler(fh)
            logger.addHandler(ch)
    
        return logger #直接返回logger
    
    logger = log()
    logger.warning("泰拳警告")
    logger.info("提示")
    logger.error("错误")
    logger.debug("查错")
    
  • 迭代器与生成器

    Python标准库中存在着一些可迭代对象,例如:list, tuple, dict, set, str等。

    可以对这些迭代对象,进行for-in等迭代操作,例如:

    for s in "helloworld":
        print(s)
    

    编译器若想迭代一个对象a,则会自动调用iter(a)获取该对象的迭代器(iterator),如果iter(a)抛出异常,则对象a不可迭代。

    总结迭代器的优缺点:
    优点
    1,提供了一种不依赖索引的迭代取值方式
    2,节省内存
    缺点
    1,只能往后取,不能往前取,而且是一次性的,值取干净之后无法再取值,除非重新得到新的迭代器对象
    不如按索引取值的方式灵活
    2,值取不干净,永远无法预测迭代器的长度

  • 递归函数

    def Recursion(n):
        # 判断参数n是否为1或0,如果是返回1
        if n == 0 or n == 1:
            return 1
        # 否则计算并调用本身进行递归,return返回计算结果
        else:
            return n * Recursion(n - 1)
    
    print(Recursion(5))  #120
    
  • 匿名函数lambda函数

    1.lambda的格式:lambda 参数:表达式

    # 普通函数和lambda的对比
    def sum_func(a, b, c):
        return a + b + c
    
    sum_lambda = lambda a, b, c: a + b + c
    
    print(sum_func(1, 100, 10000))	#10101
    print(sum_lambda(1, 100, 10000)) #10101
    
    # 无参数
    lambda_a = lambda: 100
    print(lambda_a())  #100
     
    # 一个参数
    lambda_b = lambda num: num * 10
    print(lambda_b(5))	#50
     
    # 多个参数
    lambda_c = lambda a, b, c, d: a + b + c + d
    print(lambda_c(1, 2, 3, 4))	#10
     
    # 表达式分支
    lambda_d = lambda x: x if x % 2 == 0 else x + 1
    print(lambda_d(6))	#6
    print(lambda_d(7))	#8
    

    2.把lambda当作参数

    def sub_func(a, b, func):
        print('a =', a)			#a = 100
        print('b =', b)			#b = 1
        print('a - b =', func(a, b))	#a - b = 99
    
    sub_func(100, 1, lambda a, b: a - b)
    

    3.lambda函数与Python内置函数配合使用

    member_list = [
        {"name": "风清扬", "age": 99, "power": 10000},
        {"name": "无崖子", "age": 89, "power": 9000},
        {"name": "王重阳", "age": 120, "power": 8000}
    ]
    new_list = sorted(member_list, key=lambda dict_: dict_["power"])
    print(new_list)
    # [{'name': '王重阳', 'age': 120, 'power': 8000}, {'name': '无崖子', 'age': 89, 'power': 9000}, {'name': '风清扬', 'age': 99, 'power': 10000}]
    
    
    number_list = [100, 77, 69, 31, 44, 56]
    num_sum = list(map(lambda x: {str(x): x}, number_list))
    print(num_sum)
    # [{'100': 100}, {'77': 77}, {'69': 69}, {'31': 31}, {'44': 44}, {'56': 56}]
    
  • map()函数

    map() 会根据提供的函数对指定序列做映射。

    map(function, iterable, …)
    function – 函数,有两个参数
    iterable – 一个或多个序列
    它有两个参数,第一个参数为某个函数,第二个为可迭代对象。

    # example:将列表的每个元素平方,组成新的列表
    # 常规方法
    li1 =   [1,3,4,5,7,10]
    def pow_test(n):
        return n ** 2
    def map_test(fun,array):
        li = []
        for i in array:
            res = fun(i)
            li.append(res)
        return li
    res1 = map_test(pow_test,li1)
    print(res1)
    # 这里的map_test函数的参数fun传入的是一个函数,即这个map_test函数是高阶函数,在map_test函数里调用其他函数,对第二个传入的对象进行处理。两个这里map_test()、pow_test()加在一起实现的功能就是map()函数的作用。
    # 用map()函数处理
    li1 = [1,3,4,5,7,10]
    # 下面两个方法都可以,一个是自定义的pow_test函数,一个是匿名函数lambda(高级用法)
    # res1 = list(map(lambda x:x**2,li1))
    # res1 = list(map(pow_test, li1))
    print(res1)
    # map()函数的第一个参数是一个函数,即匿名函数,这里不需要加括号执行,只是代表对一个参数的处理方式,map()第二个参数是待处理的可迭代对象。map()函数直接处理结果是一个map()函数的内存地址,是一个可迭代类型,需要加list转换为列表。这里map()函数的第一个参数不一定非要写lambda函数,也可以写自定义的函数名。
    
  • filter()函数

    filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。filter:过滤,滤除

    # example: 将列表[1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数
    li = [1, 4, 6, 7, 9, 12, 17]
    def filter_old(n):
        if n % 2 == 1:
            return n
    res = list(filter(filter_old,li))
    print(res)
    
    # 也可以
    li = [1, 4, 6, 7, 9, 12, 17]
    res = list(filter(lambda n:n %2 ==1,li))
    print(res)
    # 这里的lambda函数是一个函数处理逻辑,最终是返回了符合 n %2 ==1条件的n,这里与map函数一样,也需要List将其转换为列表。
    
    # lambda的其他用法
    li = [
        {"name":"jack","age":53},
        {"name":"pony","age":46},
        {"name":"charles","age":53},
        {"name":"richard","age":44}
     
    ]
    v = list(filter(lambda p:p["age"]<45,li))  # lambda也可以做判断
    print(v)
    # 这里lambda返回的就是符合条件的元素p,遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来。
    
  • reduce()函数

    # example,返回列表li = [1,2,3,4,5,6]每个元素相乘最终结果
    # 需要从functools里面import,python3自带的没有reduce
    from functools import reduce
    li = [1,2,3,4,5,6]
    v = reduce(lambda x,y:x*y,li)
    print(v)
    
    
    
  • map()、filter()、reduce()小结

    map(做处理):处理序列中的每个元素,得到的结果是一个‘列表’(内存地址),该‘列表’元素个数及位置与原来一样

    filter(做判断):遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来

    reduce():处理一个序列,然后把序列进行合并操作

    # lambda的处理不同,返回也不同
    test_list = [1, 2, 3, 4, 5, 6]
    print(list(map(lambda x: x ** 2, test_list)))   # 对列表每个元素做处理,返回处理结果
    print(list(map(lambda n: n % 2 == 1, test_list)))  # 对列表每个元素做判断,返回判断结果
    print(list(filter(lambda n: n % 2 == 1, test_list))) # filter对判断结果为True的存入列表
    print(reduce(lambda x, y: x * y, test_list))    # 对整个列表做合并处理
    
    # [1, 4, 9, 16, 25, 36]
    # [True, False, True, False, True, False]
    # [1, 3, 5]
    # 720
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值