美文网首页
python(入门、进阶)

python(入门、进阶)

作者: royluck | 来源:发表于2020-10-06 21:10 被阅读0次

    记:2020-10-06

    ==》python基本数据类型:
    python基本数据类型
    • 为什么字符串、列表和元组成为序列,因为它们支持切片和下标索引取值

    ------> 数字:

    9 // 4 // 取整,2
    9%4 // 取余, 1
    9 /3 // 3.0 除数返回默认为double float类型
    
    • 注:这边布尔类型判断,跟js判断空数组有区别 => boolean([]) // true
    bool('') // 0
    bool([]) // False
    bool({}) // False
    bool(()) // False
    bool(None) // False
    
    • 不同进制的表示及转换
    0b10 // 2
    0x 10 // 16
    0o 10 // 8
    bin(10) // 0b1010
    int(0b10) // 2
    oct(10) // 0o12
    hex(10) // 0xa
    

    ------> 字符串:

    '字符串' + '拼接' // '字符串拼接'
    '字符串取值'[-1] // '值'
    '字符串取值'[3:] // '取值'
    '''字符串换行''' // '字符串换行'
     r'字符串特殊字符,不让其转义,如文件地址 D:\xampp' //  '字符串特殊字符,不让其转义,如文件地址 D:\\xampp'
    R'C:\Windows' // 'C:\\Windows'
    '字符串乘数'*2 // '字符串乘数字符串乘数'
    "hellow world"[0:8:2] // 'hlo '
    

    ------> set:

    • 无序性
    • 无重复性
    {1,2,3} - {2} // {1,3} 求差
    {1,2,3} & {2} // {2} 交集
    {1,2,3} | {2} // {1,2,3} 并集
    A={1,2,3,4,5,6} 
    A.add(7) 
    print(A) // {1,2,3,4,5,6,7}
    A={1,2,3,4,5,6} 
    A.discard(6)
    print(A)  // {1,2,3,4,5}
    

    ------> tuple:

    • 不支持增加、删除、编辑
      temp = (1,2,3,True,False)
      temp[2] // 3
      temp.index(2) // 1
      temp.index(True) // 永远返回0
      temp.index(False) // 4

    ------> 常用方法:
    in、 not in、 ord、chr

    3 in {1,2,3} // True
    3 not in (1,2,3) // False
    ord('w')  // 119 返回对应字符的ascii码
    chr(119) // 'w'
    

    ------> 字典:

    • key值必须是不可变类型
    • key值不能重复(如果重复,后面的覆盖前面的)
    • 不属于序列类型
     type({}) // <class 'dict'>
    

    注: 有时候会觉得字典跟我们js的对象有点傻傻分不清,js的对象可以通过obj.name或者obj['name']访问;而python的字典只能通过dict['name']访问,实例只能通过obj.name访问。


    ------> 杂:

    • python变量命名: 小写字母 加 下划线
    • python 每个文件就是一个模块 规范的模块起始 需要加注释
    • python缩进(tab)必须4个空格,否则会报错
    • pass:空语句(占位语句),用于保持代码完整性
    • if else的简写方法:
    if condition
      a 
    else
      b  
    ==>  a or b
    
    • python跟js 在字符串拼接的区别 python要求都是字符串;js如果字符串和数字拼接,会转为字符串
    • 函数参数:参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序,否则程序会报错。
    def function(arg,*args,**kwargs):
        print(arg,args,kwargs)
    
    function(6,7,8,9,a=1, b=2, c=3) // 6 (7, 8, 9) {'a': 1, 'b': 2, 'c': 3}
    
    • 变量命名:字幕、下划线、数字,开头不能为数字,系统关键字不能用在变量名中;
    • 数据类型分为:int str tuple(不可变) 值类型和list set dict(不可变)引用类型

    ==》python运算符:

    ------> 算数运算符:
    + - * / // % **

    2**2 // 4 (2的2次方)  
    

    ------> 赋值预算符:
    == += -= /= %= **= //=

    ------> 比较(关系)运算符:
    == != > < >= <=

    ------> 逻辑运算符:
    and or not

    ------> 成员运算符:
    in not in

    ------> 身份运算符:
    is is not

    is 与 == 区别: is 用于判断两个变量引用对象是否为同一个(同一块内存空间), == 用于判断引用变量的值是否相等。

    ------> 位运算符:
    (把数字当作二进制进行运算)

    & | ^ ~ << >>

    ------> 运算符优先级:

    image.png
    ==》Python项目的组织结构:

    包 模块 类 函数、变量

    • __all__ = []如果用于__init.py文件则限制导出模块,用于普通模块文件,则限制当前模块导出的变量、函数和类; python中模块的all详细使用

    • 建议通过类来管理变量和函数;

    • __init__.py文件用于区分普通文件和包,因此内容可以为空。它的名字就是它上层文件包的名字;
      _init.py的作用:__all__ = []限制导出模块;批量导入包或模块;

    • 导入模块( import module_name):

    使用import module_name 后面只能跟模块名(即文件名);
    import 只能导入模块,不能直接导入模块下的变量;

    import p.m as m
    print(m.a) # a是模块下的变量
    

    import的缺点是命名空间太长;
    import 不能使用相对路径;

    • 导入模块( form ... import ...):

    form import 可以直接导入具体的变量和函数,也可以导入具体的模块;
    from p.m import * # 建议少星号

    • 导入模块,会执行被导入模块的代码;
    • 包和模块是不会重复导入;
    • 注意避免循环导入;
    • 模块内置变量:print(dir())
    import sys
    print(dir(sys)) # 可以传入指定的模块或类
    
    • 常用内置变量:__file____package____name____doc__
      入口文件的 __file____package____name__ 内置变量打印出来的值跟普通模块打印出来是有区别的:入口文件的__name__会被python强制更改为__mian____package__为空; __file__为执行python命令的文件目录地址;而普通模块 __file__为本地绝对地址;
    • python -m m.py python规定模块必须归属于一个包下面;
    • 相对导入和绝对导入:使用.点表示的是相对导入;
    • 顶级包跟入口文件地址有关:__package__
    • 绝对路径必须从顶级包开始,eg: import package2.package4.m
    • import不能使用相对导入,from才可以;
    • 入口文件不能使用相对路径来导入模块(因为python会把入口文件名强制转为__main__,而python相对路径又是通过__name__来识别路径的)

    ==》函数:
    • 函数默认返回None
    • python解析,是自上而下执行的,所以函数调用必须放在函数声明之后(区别:js如果使用函数声明式语法,函数调用是可以放在函数申明之前的(变量提升))
    • 设置python递归次数(默认为995次)
      import sys
      sys.setrecursionlimit(10000)
    • 返回多个值(用逗号分隔,以元组类型返回)
      return data1,data2
    • 变量接受返回值的结果:(方便代码阅读)
      skill1_damage,skill2_damage = damage(3, 6)
      # 上面damage是函数,它返回两个值, 定义两个变量以解包的方式接收函数返回的两个值,通过这种方式,能方便代码的阅读
    • 序列、解包:
      序列:
      a,b,c = 1,2,3
      a = 1,2,3 #a 元组
      a,b,c = 1,1,1 =>a = b = c = 1
      解包:
      u,v,w = a
    • 区分:js函数传参和变量解构赋值不要求元素个数必须相等,而python要求元素个数必须相等
    // js:
    let arr = [1,2,3,4]
    [a,b] = arr // a = 1, b = 2
    [a, ...b] = arr // a = 1, b = [2,3,4]
    
    #python
    a,b = [1,2,3,4] # 报错
    a,*b = [1,2,3,4] # a = 1,b = [2,3,4] 这里的解包,右边数据类型无论是元祖、集合、还是列表,解包回来的b都是列表(list)类型
    
    • 形式参数和实际参数概念;
    • 必须参数(必须传递参数,否则报错);
    • 关键字参数(可以不用考虑参数顺序,提高代码可读性);
    def add(x, y)
      pass
    c = add(y = 1, x = 2)
    
    • 函数默认参数(非默认参数不能跟着默认参数)
      SyntaxError: non-default argument follows default argument
    def add(x = 1,  y = 2) 
      pass
    
    • 函数传参时,具体参数不能跟着关键字参数
      SyntaxError: positional argument follows keyword
    def add(x,y = 6, z = 8):
      pass
    add(10,y = 10, 2) # 报错 argument
    
    • 可变参数(可以接受任意参数)
    def demo(*param):
      print(param)
      print(type(param)) # tuple 无论实参是list,还是tuple、set,这里都是tuple类型
    
    a = [1,2,3]
    demo(*a)
    
    • 必须参数(param1)必须前面(如果跟可变参数混合用):
    def demo(param1, param2 = 3, *param):
      print(param)
      print(type(param))
    
    • 任意数量的关键参数:
    def city_temp(**param):
      print(param)
      print(type(param))
    
    • 遍历字典:
    for key,value in param.items():
      print(key,value)
    
    • 全局变量和局部变量:
      -> 局部变量只是相对概念;
      -> python没有块级作用域;
      -> 作用域链;
      -> 逐级寻找;
      -> python for 循环(因为不存在块级作用域)不属于作用域链,即使它能访问到它的上级变量:
    def demo():
      c=10
      for i in range(0,20):
        a = 10
        c += i
      print(c) # 200
      print(a) # 10
    
    demo()
    

    -> global 关键字:
    (python中,所属函数可以访问全局变量,但是不建议所属函数修改全局变量,如下所示)

    c = 10
    def demo():
      global c
      c = 2
    demo()
    print(c) # 2
    

    ==》类(面向对象):
    • 封装性 继承性 多态性

    • 如何构建一个类:
      -> 类跟对象的关系
      -> 类建议第一字母大写,不建议用下划线链接
      -> 类括号跟函数括号的参数用途不一样(类表示继承,函数表示传参)
      -> 类的内部:
      1、定义变量
      2、定义函数
      -> 实例化类:
      student = Student()

      • 类下面编写函数跟普通函数有区别,必须有self,不能把类下的变量理解为全局变量;
        # python强制要求必须显示指定self
    class Student():
      age = 10
      def print_age(self):
        print(self.age)
    
    • 必须通过self访问内部变量,函数括号必须有self

    • 一个模块下面不建议又声明类,又调用类;建议一个模块只单独声明类,再通过另外一个模块导入类,再调用类;

    • 方法和函数的区别:
      -> 方法: 设计层面
      -> 函数:程序运行,过程式的一种称谓

    • 类是现实世界或思维世界中的实体在计算机中的实现,它将数据以及这些数据上的操作封装在一起;

    • 行为要找对主体(主谓关系)

    • 类就像一个模板,通过模板可以产生很多对象

    • 构造函数:

    def __init__(self)  # 必须带self
        pass
    

    -> 构造函数不能强制返回其他类型,必须(默认None)None,否则报错;

    def __init__(self) 
        return 666 # 会报错
    

    -> Student.__init__()

    • 构造函数作用:初始化对象的属性
    • 类变量 实例变量区别:
      -> 类变量在class下直接定义
      -> 实例变量在__init__()内定义
    class Student():
      name = ''
      age = 0
      def __init__(self,name,age):
        self.name = name 
        self.age = age
    
    • 局部变量不会更改全局变量(变量同名)

    • 实例变量必须通过self(在init内)赋值

    • student1.__dict__ #打印实例对象的变量

    • 寻找链条“
      实例查找 -> 类查找 -> 父类查找(继承过来的父类)

    • 实例方法 类方法 静态方法

    • 实例方法访问类变量和实例变量:
      -> 访问实例变量用self
      -> 访问类变量:
      Student.sum
      self.__class__.sum

    • 类方法:

    @classmethod
    def do_work(cls):
      pass
    
    • 类方法一般用于处理与实例变量无关的值

    • 实例也可以调用类方法,一般建议不要用对象调用类方法
      student1.do_work() # 不建议这么用

    • 静态方法:

    @staticmethod
    def add(a,b):
      pass
    

    -> 静态方法不用像实例方法一样强制传递self和cls参数
    -> 对象和类都可以调用静态方法
    -> 静态方法可以访问类变量

    • 类方法和静态方法不可以访问实例变量

    • 静态方法不建议经常使用,因为它跟类处于弱关系;

    • 方法和变量的内部调用和外部调用:
      ->限制外部调用和更改
      -> 提倡:类下面的变量(包括类变量和实例变量)不要在外部直接修改,例如student1.score = 59而是要通过方法内修改;原因在于可以控制判断保护数据;(只是提倡建议,不强制要求)

    • 公开 私有:
      -> 公开可以在外部访问
      -> 如何变成私有: 加双下划线_类名__变量名

    • 拓展:加双下划线能让实例访问不到属性和方法,如果像__init__左右都加双下划线,就又可以访问到了;

    • python动态语言可以通过点的方式给对象新增变量

    • 面向对象三大特性 继承行 封装性 多态性
      -> 继承性: 避免定义重复的方法和变量;继承实例变量,类变量;

    • 拓展:python支持多继承(不建议使用多继承)

    • 子类调用父类构造函数:

    super(Student,self). __init__(name,age)
    
    • 子类方法调用父类方法:
    super(Student,self). do_homework()
    
    • 拓展:编程开闭原则

    ==》枚举:

    Python中枚举的用法

    • 枚举的好处:
      不可变防止重复
    • 枚举类型 枚举的名字 枚举的值
    print(VIP.YELLOW) # VIP.YELLOW
    print(VIP.YELLOW.value)
    print(VIP.YELLOW.name)
    print(VIP["GREEN"])
    
    • 不能有相同的标签(key),可以相同的值,但是后者只是前者的别名:
    from enum import Enum
    class VIP(Enum):
        YELLOW = 1
        GREEN = 2
        BLUE = 1
    
    print(VIP.YELLOW) # VIP.YELLOW
    print(VIP.BLUE) #  VIP.YELLOW
    print(VIP['BLUE']) # VIP.YELLOW
    
    
    for v in VIP:
      print(v) 
    #打印结果:
    # VIP.YELLOW
    # VIP.GREEN
    
    for v in VIP.__members__.items():
      print(v)
    # 打印结果:
    # ('YELLOW', <VIP.YELLOW: 1>)
    # ('GREEN', <VIP.GREEN: 2>)
    # ('BLUE', <VIP.YELLOW: 1>)
    
    for v in VIP.__members__:
      print(v)
    # 打印结果:
    # YELLOW
    # GREEN
    # BLUE
    
    • 枚举的比较运算符:
      支持:== in
      不支持:> <

    • 枚举的转换

    a = 1
    VIP(a) # VIP.YELLOW
    
    from enum import IntEnum,unique
    @unqiue
    class VIP(IntEnum):
      YELLOW = 1
      GREEN = 1 # 报错
      BLUE = 'str' # 报错
    
    • 枚举类型不能实例化(单例模式)(23种设计模式)

    ==>函数式编程(闭包)

    python一切皆对象

    • 把一个函数当作另外一个函数的返回结果
    • 另外一个函数作为参数,传递到另外函数里
    • 闭包概念跟变量作用域有关
    def curve_pre():
      a = 10
      def curve(x):
        return a*x
      return curve
    
    f = curve_pre()
    f(2)
    f.__closure__
    f.__closure__[0].cell_contents
    
    • 闭包= 函数+环境变换量(把函数和函数变量封装在一个环境里面,让其不受外面影响)
    • 局部变量不能影响外部变量
    • 经典闭包题目:
    def f1():
      a = 10
      def f2()
        a = 8 #python没有认为是一个局部变量(没用引用外部啊= 10)
      return f2
    
    f = f1()
    
    • 闭包的用处,保存上一次执行记录

    • global origin # 声明全局变量

    • 闭包环境变量有保存现场的功能

    origin = 0
    def factory(pos):
      def go(step):
        nolocal pos #声明非本地pos局部变量
        new_pos= pos+step
        origin = new_pos # 否则python会认为等号左边的origin是一个局部变量声明
        return new_pos
      return go
    
    tourist = factory(origin)
    
    • 闭包不改变全局变量
    • 闭包可以实现工厂模式
    • 闭包是常驻内存变量,容易造成内存泄露

    ==>匿名函数(lambda):
    • 只能用于简单表达式(不能代码块)
    def add(x,y):
      return x + y
    # 等同于
    lambda x,y: x+y
    
    • 匿名函数使用场景:
      不能做赋值运算(冒号后面不能是代码块);

    ==>三元表达式:
    x > y ? x: y
    #等同于
    x if x > y else y # 格式:条件为真时返回的结果 if 条件判断 else 条件为假时的返回结果
    

    ==> map、reduce、filter
    • 注:reduce需要导入
    list1 = [1,2,3]
    list2 = [1,2,3]
    def square(x):
      return x * x
    r = map(square, list1)
    print(list(r)) # 需要转换为list格式
    # 等同于
    map(lambda x,y: x + y, list1, list2)
    
    #导入reduce
    from functools import reduce
    
    r = filter(lambda x: x>1, list1)
    
    • 拓展:map/reduce 大数据 编程模型 映射 归约 并行计算 函数式编程

    
    import time
    
    def decorator(func):
        def wrapper():
            print(time.time())
            func()
        return wrapper
    
    def f2():
        print('this is a function')
    
    f = decorator(f2)
    f()
    
    # 语法糖
    # 装饰器最大的用处(相比上面)
    
    @decorator
    def f1():
        print('this is a function')
    
    f1()
    
    • 语法糖只是一种魔术(简化写法,但是不能优化性能)
    • 可以接受定义的复杂,但是不能接受调用的复杂
    • 拓展:装饰器体现了AOP变成思想(从横切面解决问题)

    --> 改造:支持多个参数(上述不能传参)

    def decorator(func):
        def wrapper(*args):
            print(time.time())
            func(*args)
        return wrapper
    
    @decorator
    def f2(param1, param2):
        print(f'this is {param1}')
        print(f'this is {param2}')
    
    f2('roy', 'roben')
    

    --> 再次优化:

    • 装饰器的用途:不改变具体实现,而通过装饰器改变行为
    def decorator(func):
        def wrapper(*args,**kw):
            print(time.time())
            func(*args,**kw)
        return wrapper
    @decorator
    def f2(param1, param2, **kw):
        print(f'this is {param1}')
        print(f'this is {param2}')
        print(kw) # {'a': 1, 'b': 2}
    
    f2('roy', 'roben', a = 1, b =2)
    

    ==>字典映射代替switch case语句:
    day = 0
    
    def get_sunday():
        return 'Sunday'
    
    def get_monday():
        return 'Monday'
    
    def get_tuesday():
        return 'Tuesday'
    
    def get_default():
        return 'Unknow'
    
    switch = {
        0: get_sunday,
        1: get_monday,
        2: get_tuesday,
    }
    
    r = switch.get(day, get_default)() # get方法具有容错性
    print('日期:')
    print(r)
    

    ==>列表推导式:
    • 注:元组比较特殊,因为它是不可变的,所以其返回是一个遍历器
    list = (1,2,3)
    list_new = [i**2 for i in list]
    print(list_new)
    list_new = {i**2 for i in list if i > 1} # 加条件
    print(list_new)
    list_new = (i**2 for i in list if i > 1)
    print(list_new) #返回迭代器
    print(*list_new)
    # 打印结果:
    # [1, 4, 9]
    # {9, 4}
    # <generator object <genexpr> at 0x0000021EF894D148>
    # 4 9
    
    # list_new:generator object
    for i in list_new:
      print(i) # 4 9
    
    
    students = {
        'roy': 18,
        'roben': 20,
    }
    
    b = { value: key for key,value in students.items()}
    print(b)
    # 打印结果:
    # {18: 'roy', 20: 'roben'}
    
    ==>可迭代对象 迭代器(interator)(针对对象来说):
    • for in interable
    • 迭代器是一个可迭代对象,可迭代对象不一定是可迭代器
    class bookCollection:
        def __init__(self):
            self.data = ['data1', 'data2', 'data3']
            self.cur = 0
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.cur >= len(self.data):
                raise StopIteration()
            r = self.data[self.cur]
            self.cur += 1
            return r
    
    books = bookCollection()
    import copy
    books_copy = copy.copy(books) # 浅拷贝 deepcopy 深拷贝
    # 迭代器只有一次性
    for i in books_copy:
        print(i)
    
    # 迭代器可以调用next方法,但是迭代对象不可以调用next方法
    books1 = bookCollection()
    print(next(books1))
    

    ==> 生成器(针对函数来说)
    • 列表存储需要消耗内存
    • 利用生成器解决上述问题
    def gen(max):
        n = 0
        while n<=max:
            n+=1
            yield n
    
    # 解决了内存问题
    g = gen(100)
    print(next(g))
    print(next(g))
    print(next(g))
    
    # 生成器
    g1 = (i for i in range(0, 100))
    

    ==> 非空判断:
    • None 不等于 [] '' 0 False
    # 判空操作
    a = None # False 0 '' []
    if a:
        pass
    
    if not a:
        pass
    
    # 不建议用下面进行判空
    if a is None:
        pass
    

    ==>对象存在不一定是True:
    • 受下述内置函数影响:
    class Test():
        def __len__(self):
            return 0 # 只能返回整型数字 或者 True False
    
        def __bool__(self):
            return False # 只能True False
    

    ==>装饰器的副作用:
    • f1.__name__ help(f1) 打印出来的值不是f1的内容,而是wrapper的内容
    • 解决方法:
    from functools import wraps
    def decorator(func):
        @wraps(func)
        def wrapper(*args):
            print(time.time())
            func(*args)
        return wrapper
    

    ==>walrus operator 海象运算符 (必须python 3.8版本以上)
    a = 'python'
    
    if (b:=len(a)) > 5:
        print('长度大于5:'+ '真实长度为' + str(b))
    

    ==> dataclass(语法糖)
    • 帮助快速创建类的__init__方法
    from dataclasses import dataclass
    
    @dataclass
    class A():
        name: str
        postion: float
    
    a = A('roy', 1.2)
    print(a__repr__()) # A(name='roy', postion=1.2)
    print(a) # A(name='roy', postion=1.2)
    
    • 与普通通过__init__创建类还是有区别的,dataclass默认修改了__repr__方法,因此print打印出的实例对象能看到它具体的属性值

    • 支持传参:

    @dataclass(init=False, repr = False)
    

    相关文章

      网友评论

          本文标题:python(入门、进阶)

          本文链接:https://www.haomeiwen.com/subject/mooawhtx.html