相关推荐recommended
python 入门基础 Introduction to Python Fundamentals
作者:mmseoamin日期:2024-01-21

文章目录

      • 注释
        • 单行注释
        • 多行注释
        • pass
        • 字符串格式化
          • format
          • %
          • f-string(py3.6之后可用)
          • 数据结构
            • int
            • str
            • bool
            • float
            • 列表(list)
            • 字典(dict)
            • 集合
            • 枚举
            • 迭代器
            • 其他
            • 元组(tuple)
            • 数值运算
            • 流程控制
            • 文件操作
            • 函数
            • 面向对象
              • 方法
              • 继承与多态
              • 对象复制
                • 上下文管理
                • 异常
                • 模块
                • 属性
                • 异步
                • 网络

                  注释

                  单行注释
                  # 注释
                  print(0)
                  
                  多行注释
                  '''
                  这是一个注释
                  '''
                  print(0)
                  

                  pass

                  补充语法的完整性,什么都不做

                  if 1 > 1:
                      pass
                  else:
                      print("123")
                  

                  字符串格式化

                  format
                  info = '我叫{0},我的年龄是{1}岁'.format('张三',101)
                  info = '我叫{},我的年龄是{}岁'.format('张三',101) # 按照顺序填入值
                  info = '我叫{name},我的年龄是{age}岁'.format(name='张三',age=101) # 不常用,相当于{}内的是一个变量名
                  
                  %
                  info = '我叫%s,我的年龄是%d岁' %('张三',101)
                  
                  f-string(py3.6之后可用)
                  name = '张三'
                  age = 101
                  info =  f'我叫{name},我的年龄是{age}岁'
                  

                  数据结构

                  数据类型的转换:目标类型(值),如int(‘1’),将浮点值转换为整型值会丢失精度

                  • 函数中修改全局变量的值需要用global关键字再次声明全局变量,以表明修改的是全局变量而不是声明的局部变量

                    • num = 10
                      def add():
                          global num
                          num += 10
                      add()
                      print(num) # 20
                      
                    • nonlocal用法与global类型,但常用于嵌套函数中

                      • def demo1():
                            num = 10
                            def demo2():
                                nonlocal num
                                num += 10
                            demo2()
                            return num
                        print(demo1()) # 20
                        
                        int
                        a = 1
                        b = 2
                        
                        str
                        name = 'zhangsan'
                        hobby = 'PLAY'
                        age = '18'
                        res = name.upper() # 大写
                        res = hobby.lower() # 小写
                        age.isdecimal() # 返回true or false,判断是可以转换为数字
                        name.isalpha() # 判断是否是字母
                        age.isdigit() # 判断是否是数字
                        age.isalnum() # 判断是否是数字字母混合
                        name.startswith('zhang') # 判断是否是zhang开头
                        name.endswith('san') # 判断是否是san结尾
                        name.replace('zhang','li') # 替换旧值为新值
                        addr = '河南省 郑州市 郑东新区'
                        res = addr.split(' ') # 切割返回一个list ['河南省', '郑州市', '郑东新区']
                        res = addr.split(' ',maxsplit=1) # 切割返回一个list,从左到右只切割一次 ['河南省', '郑州市 郑东新区']
                        res = addr.rsplit(' ') # 从右往左切割
                        addr = '_'.join(res) # 将列表res中的值以_连接
                        addr = addr.strip()/rstrip()/lstrip() # 去除字符串两端/右边/左边空白
                        add.partition(' ')/rpartition(' ') # 将字符串按照空格切割成元组,从左到右/从右往左
                        len(name) # 获取长度
                        name[0] # z 获取单个字符
                        name[-1] # n
                        name[1:2] # h
                        name[:1] # z
                        name[5:] # san
                        s = 'ang' in name # 判断字符串是否包含某个子序列
                        
                        bool

                        当类型转换为bool时,只有0、空字符串、空列表、空元组、空字典以及None转为False,其他都为True

                        a = True
                        b = False
                        
                        float
                        a = 3.14
                        
                        列表(list)

                        长度可变,可以存放任意类型的数据,有序

                        # 列表初始化
                        l = [] # 方式1
                        ll = list() # 方式2
                        # 添加元素
                        l.append(1) # 向列表尾部添加元素
                        l.extend([2,3,4]) # 向列表尾部添加多个元素
                        l.index(1,5) # 向列表中索引位置为1的位置添加元素
                        # 删除元素
                        l.remove(2) # 删除元素指定的元素,若删除的元素在列表中出现多次就删除最先出现的元素
                        del l[1] # 删除列表中索引为1的元素
                        l.clear() # 清空列表
                        # 反转列表,在原列表中调整元素的顺序,不会产生新的列表
                        l = reversed(l)
                        # 获取指定元素在列表中出现的次数
                        l.count(3) # 统计的元素不存在,不会报错,会返回0
                        # 弹出元素,并从列表中删除
                        l.pop() # 默认弹出列表末尾的元素,可以指定要弹出元素的索引,如l.pop(1),列表为空或超出索引会报错
                        # 合并列表
                        t = [34,32]
                        lis = t + l
                        # 复制列表中的元素
                        # 将list对象与正整数相乘会复制列表中的元素,复制的次数取决于参与运算的正整数
                        print(t*2) # [34,32,34,32]
                        
                        字典(dict)

                        存放键值对,val可以是任何类型,key只能是可hash类型,key不可重复

                        # 初始化
                        d = {'name':'张三','age':11}
                        dd = dict(age=18)
                        dd['name'] = 'lisi'
                        # items返回一个迭代器,使用for循环可以获取到每个键值对,items返回的是一个元组列表
                        for k,v in d.items():
                            print(f'{k}:{v}')
                        # 删除
                        del d['name']
                        '''
                        更新update(),可以接收多种参数,
                        1、关键字参数,直接将参数名作为key参数值为val
                        2、另外一个字典,将另一个字典中的键值对复制到当前字典对象中,若key已存在将覆盖当前字典中的val
                        3、序列对象,tuple、list
                        '''
                        d.update(name='wangwu')
                        d.update({'name':'wangwu'})
                        d.update((('name','wangwu'),))
                        # 合并字典,ChainMap合并对象中出现相同的key时只会返回第一个key的值,
                        # ChainMap对象的删除、设置等操作只对ChainMap中的第一个字典对象有效
                        from collections import ChainMap
                        cm = ChainMap(d,dd)
                        # 计数器Counter,key存储某个序列中的元素,val存储元素出现的次数
                        c = Counter('123112') # 返回一个特殊的字典
                        print(c.most_common()) # 返回一个列表,将按照元素出现次数进行降序排列
                        
                        集合

                        不能有重复元素,有序

                        # 初始化
                        s = set([1,2,3,6]) # 初始化之后可以使用add、remove方法来修改元素
                        f = frozenset([1,2,3]) # 初始化之后不能再修改
                        ss = {1,2,3,4} 
                        # 合并集合
                        s = s.union(ss) # 方式1
                        print(s) # {1,2,3,4}
                        s = s | ss # 方式2
                        print(s) # {1,2,3,4}
                        # 包含关系
                        s.issuperset(ss) # False 当前集合是否为另一个集合的父集(超集),即另一个集合中的所有元素是否都出现在当前集合中,或两个集合的元素完全相同
                        s.issubset(ss) # True 当前集合是否为另一个集合的子集,即当前集合的元素全部在另一个集合中,或两个集合的元素全部相同
                        # 交集,获取集合的共有元素
                        s.intersection(ss) # {1,2,3}将计算结果存放到新的集合中,并返回给调用方
                        s.intersection_update(ss) # 添加_update后缀的作用是更新当前集合并存储结果
                        s = s & ss
                        # 差集,获取当前集合与其他集合存在差异的元素
                        ss.difference(s) # {4}
                        ss.difference_update(s)
                        ss = ss - s
                        # 异或,排除集合之间的共同元素之后,所剩下的元素
                        s.symmetric_difference(ss) # {4, 6}
                        s.symmetric_difference_update(ss)
                        s = s ^ ss
                        
                        枚举
                        from enum import Enum,IntEnum
                        # 枚举需要使用class关键字定义,且必须从Enum或其子类派生
                        # 枚举默认是可以出现重复的成员值,使用@unique装饰器,就不能出现重复成员值,否则会报错
                        class MyEnum(Enum):
                            SINGLE = 1
                            MUTIL = 2
                        # 调用
                        e = MyEnum.SINGLE
                        # 只能使用int值的枚举
                        class MyEnum(IntEnum):
                            SINGLE = 1
                            MUTIL = 2
                        
                        迭代器
                        # iter()函数是将传入的对象转换为迭代器
                        # next()函数可以在一个迭代器上多次调用,每次调用都会返回一个元素,若没有可以返回的元素,就会报错
                        i = iter([1,2,3])
                        while True: # 1 2 3
                            try:
                                print(next(i))
                            except StopIteration:
                                break
                        # yield只能在函数内部使用,当函数中存在yield时,函数就会返回一个迭代生成器对象
                        def t():
                            yield 1
                            yield 2
                        t = t()
                        print(next(t)) # 1
                        print(next(t)) # 2
                        def t():
                            x = yield 1 # 赋值语句从右往左执行,调用第一次next时输出1,第二次调用next时会将yield 1替换为None
                            yield x
                        t = t()
                        print(next(t)) # 1
                        print(next(t)) # None
                        # 自定义迭代器,只要类型中实现下面两个方法即可
                        # __iter__方法由iter函数调用
                        # __next__方法由next函数调用
                        class MyIter:
                            def __iter__(self):
                                pass
                            def __next__(self):
                                pass
                        
                        其他
                        # 自定义序列
                        # 实现下面三个方法就可以以索引的方式访问元素
                        def __getitem__(self,index)
                        def __setitem__(self,index,val)
                        def __delitem__(self,index)
                        # 获取序列的长度,可以是类型对象占用的空间或对象包含的元素个数
                        def __len__(self) # 当对象传递给len函数后调用
                        # 切片obj[start:end:step]
                        a = [1,2,4,6,7]
                        print(a[:2]) # [1, 2]
                        print(a[2:]) #[4, 6, 7]
                        print(a[::2]) # [1, 4, 7]
                        print(a[:-1]) # [1, 2, 4, 6]
                        # in/not in检查元素是否存在某个序列
                        print(1 in a) # true
                        print(3 not in a) # true
                        
                        元组(tuple)

                        不可变,有序

                        # 初始化
                        t = tuple([1,2])
                        tt = (1,2)
                        ttt = (1,)
                        

                        数值运算

                        运算符说明运算符说明
                        +加,用于数值类型进行加法运算,字符串类型用于拼接**指数
                        -//整除运算符,只保留整数部分
                        *乘,字符串str与整型n之间使用表示,重复str获取n次并拼接%取余
                        /== 、!= 、 >、 < 、>= 、<=比较运算符
                        &按位与,两者都为1才是1^异或,两者相等结果为0,不等为1
                        按位或,一个为1,就是1~
                        >>向右移动若干二进制位<<向左移动若干二进制位
                        and逻辑与,所有参与运算的表达式都为True才为Trueor逻辑或,所有参与运算的表达式有一个True就为True
                        is判断两个变量是否为同一对象not使表达式产生相反的bool值
                        in判断类型是否包含某个成员表达式1 if 条件 else 表达式2类似三目运算符
                        # 随机数
                        from random import randrange,randint,choice,random,sample,shuffle
                        randrange(start,stop=None,step=1) # 生成含头不含尾的随机数
                        randint(start,stop=None,step=1) # 生成含头含尾的随机数
                        choice((1,2,4) # 从序列中随机取出一个元素
                        random() # 生成一个0~1的随机数
                        sample((1,2,3,4,5)) # 从序列中随机取出多个元素组成一个新的序列
                        shuffle([1,2,3,4]) # 打乱列表中的元素
                        # 数学函数
                        from math import floor,ceil,round,abs
                        ceil(11.1) # 12 向上取整
                        floor(11.1) # 11 向下取整
                        ''' 
                        四舍六入,当尾数小于5,直接舍去,当尾数大于5,前一位进1,当尾数等于5
                        且5之后的任意数位都为0,若前一位是偶数就直接舍去,否则进1,5之后的任意数位不为0
                        就会舍去尾数,且前一位进1
                        '''
                        round(1.86501) # 1.87 
                        abs(-1) # 1 绝对值
                        '''
                        排序
                        iterable表示要进行排序的序列
                        key可以引用一个函数,通过此函数可以返回自定义的用于排序的值
                        reverse表示是否将排序好的值进行翻转,默认为False
                        '''
                        sorted(iterable,key,reverse) # sorted(['a','werw','yd'],key=len) 返回['a','yd','werw']
                        

                        流程控制

                        # 多分支 
                        if 条件1:
                            符合条件1的代码
                        elif 条件2:  # 可以有多个
                            符合条件2的代码
                        else:
                            不符合1和2的代码
                        # 单分支
                        if 条件1:
                            符合条件1的代码
                        # 双分支
                        if 条件1:
                            符合条件1的代码
                        else:
                            不符合1和2的代码
                        while 判断条件:
                            代码块
                        for 变量列表 in 迭代器对象:
                            代码块
                        # for常与range函数一起使用,range可以产生一组有序的整数序列
                        range(start,end,step) # range(2,8,2) 输出 2、4、6
                        # 循环代码中break跳出循环,continue跳过本次循环执行下一次循环
                        

                        文件操作

                        # os 操作系统模块
                        os.getcwd() # 获取当前文件路径
                        os.listdir() # 获取当前目录下的所有文件,并将其写入list
                        os.mkdir('tmp') # 创建一层目录,一般采用相对路径
                        os.rmdir('tmp') # 删除空目录,采用相对路径
                        os.makedirs('/tmp/test') # 创建多级目录
                        os.removediirs('/tmp/test') # 删除嵌套目录
                        
                        • mode参数

                          • 字符描述
                            r读取,不指定mode参数时默认为r
                            w写入文件,写入前会清空文件
                            x创建一个新的文件并允许写入
                            a将数据追加到文件末尾,不会清空文件
                            b以二进制形式读写文件
                            t以文本方式读写文件
                            +打开一个文件进行读取和写入
                          • # 打开文件从而进行读写操作
                            '''
                            :param file:指定要进行操作的文件名
                            :param encoding:指定编码格式,只用于文本模式
                            :param buffering:指定缓冲区大小
                            :param newline:指定如何处理换行符,只用于文本模式,有效值:None、空字符串、\r,\n.\r\n
                            :param errors:指定如何处理编码错误
                            '''
                            with open(file,mode='r',buffering=-1,encoding=None,errors=None,
                                newline=None,closefd=True,opener=None) as f:
                                f.read() # 读取,读取全部内容到内存中
                                f.readline() # 逐行读取
                                f.readlines([size]) # 以列表形式读取size行,若未指定则读取所有行
                                for l in f: # 通过迭代器获取行
                                    print(l)
                                f.write('zhangsan') # 写入
                                f.tell() # 获取当前文件指针的位置
                                f.seek(偏移量,起始位置) # 偏移量,单位字节,起始位置:0文件头,默认、1,当前位置、2,文件尾部
                                f.close() # 关闭文件
                            import io
                            s = io.StringIO() # 读写文本文件
                            b = io.BytesIO() # 读写二进制文件
                               
                            

                            函数

                            # 函数的定义
                            def 函数名(参数列表):
                                函数体 
                            # 函数调用
                            函数名(参数)
                            def f(a):
                                """
                                函数的文档:定义在函数体内的第一个多行注释
                                :param a
                                :return
                                """
                            f.__doc__ # 获取注释内容
                            # a表示位置参数,b表示关键字参数
                            # 向函数传递参数时,先传递位置参数再传关键字参数
                            def fn(a,b=None):
                                pass
                            # 参数列表中出现*,表示此字符之后的参数都必须按关键字传递参数值
                            # 参数列表中出现/,表示此字符之前的参数都必须按位置传递参数值
                            
                            • 可变参数(可以传递0或多个参数)

                              • *args:表示位置参数

                              • **args:表示关键字参数

                              • def f(*args,**xargs):
                                    print(args) # 返回元组
                                    print(xargs) # 返回字典
                                # 若可变的位置参数后出现非可变参数,在调用函数时,可变参数后的非可变参数必须按照关键字函数传递
                                def fn(*args,d):
                                    pass
                                fn(1,2,d=3)
                                
                              • 函数传递

                                • 将函数对象作为参数传递时,不需要带小括号,因为只需要传递函数对象的引用

                                  • def f1(f):
                                        pass
                                    def f2():
                                        pass
                                    f1(f2)
                                    
                                  • 装饰器

                                    • 装饰器是一个返回值是函数的函数

                                    • def f(*args):
                                          def ff():
                                              print('hahah')
                                          return ff
                                      @f
                                      def fff():
                                          print('666')
                                      fff() # hahah
                                      # 闭包
                                      def f1():
                                          def f2():
                                              print('closer')
                                          return f2
                                      # 调用f2
                                      f1()()
                                      
                                    • 内置装饰器

                                      @property # 可以不用添加括号调用方法
                                      @staticmethod # 与self解绑可以直接使用类名调用方法
                                      @classmethod # 传递类本身
                                      
                                    • 匿名函数

                                      • 使用lambda关键字创建,不使用return,表达式的值作为返回值,只能写一行

                                      • print(lambda x:print(x),1),输出1

                                        面向对象

                                        # 创建
                                        class <类名>(基类列表):
                                            <类代码>
                                        class people:
                                            # 在类型被案例化的过程中会调用__init__,__new__方法,多数情况只需要定义__init__方法即可    # 创建对象案例,cls表示要案例化的类型,一般是当前类型
                                            def __new__(cls): # 先调用
                                                # 必须返回对象案例,一般以下述方式产生对象案例
                                                return object.__new__(cls)
                                            # 设置一些属性的初始值
                                            def __init__(self): # 之后调用
                                                pass
                                        p = people() # 类的案例化
                                         # 带参数的构造函数
                                        class animal:
                                            # 可以使用可变参数,这样无论__init__的参数如何变动也不会影响到__new__ 
                                            def __new__(cls,*args,**kwargs):    
                                                return object.__new__(cls) # object.__new__(cls)只接收一个参数
                                            # 若同时定义__new__,__init__,就需要保证两个方法的参数一致,因为在案例化时参数
                                            # 会先传递给__new__再传递给__init__,当两个方法接收的参数不一致时会报错
                                            def __init__(self,color): 
                                                self.color = color
                                        a = animal('red') # 传递参数,self不需要显式传递
                                        
                                        方法
                                        class demo:
                                            # 案例方法,显式参数传递从第二个参数开始
                                            def get_value(self,key):
                                                pass
                                            # 类方法,调用时直接使用类型引用,无须创建类型案例
                                            @classmethod
                                            def get_age(cls,name):
                                                pass
                                            # 静态方法,与类型和案例都无关,不需要隐式定义第一个参数
                                            @staticmethod
                                            def add(a,b):
                                                pass
                                        # 案例方法调用
                                        d = demo()
                                        d.get_value('age')
                                        # 类方法调用
                                        demo.get_age('zhangsan')
                                        # 静态方法调用
                                        demo.add(1,2)
                                        
                                        继承与多态
                                        # 继承:当子类从父类继承后,即拥有父类的功能,也拥有子类自己的功能
                                        # 子类中的方法与父类中的方法重名,会覆盖父类方法
                                        # 父类(基类)
                                        class father:
                                            def run(self):
                                                print('f.run')
                                        # 子类(派生类),子类可以继承多个父类
                                        class son(father):
                                            def run(self):
                                                print('s.run')
                                                father.run(self) # 调用父类的run方法
                                                super().run() # 调用父类的run方法,第二种方式
                                        s = son()
                                        s.run() # 输出s.run f.run
                                        # 多态:一种事物具备多种形态
                                        class Animal:
                                            def run(self):
                                                print(f'{type(self).__name__}对象')
                                        class Tiger(Animal):
                                            pass
                                        class Lion(Animal):
                                            pass
                                        Tiger().run()
                                        Lion().run()
                                        # 检查一个类是否为另一个类的子类
                                        # 参数1是待检查的类
                                        # 参数2可以时一个类,或多个类组成的元组对象
                                        # 当参数2为元组时,其中的类只要有一个是参数1的父类就会返回True
                                        issubclass(cls,cls_or_tuple)
                                        father.__subclasses__() # 获取father类的直接子类
                                        # 初始化派生类型
                                        # 当一个类派生出另一个类时,__init_subclass__方法就会被调用
                                        class person:
                                            # 主要是对派生类进行初始化
                                            def __init_subclass__(cls,**kwargs):
                                                if kwargs:
                                                    for k,v in kwargs.items():
                                                        setattr(cls, k, v)
                                        class doctor(person,name='zhangsan',age=18):
                                            pass
                                        for k,v in vars(doctor).items():
                                            if not k.startswith('__'):
                                                print(f'{k}:{v}')
                                        

                                        对象复制

                                        # id返回对象的唯一标识,若两个变量的标识相同,表明的是引用的同意对象
                                        id(a) == id(b) # 判断两个变量是否引用同一对象
                                        id(a) is id(b) # 同上
                                        # 浅拷贝仅复制对象本身,不会复制对象引用的其他对象 copy()
                                        # 深拷贝不仅复制对象本身,也会递归式的复制对象中引用的其他对象 deepcopy()
                                        # dir()函数可以获取一个列表案例,存放了此对象的成员名称
                                        # __sizeof__方法返回案列占用的内存大小,字节为单位
                                        # __str__将对象转换为字符串,一般返回的字符串比较简短,对象传递给str()时被调用
                                        # __repr__将对象转换为字符串,返回的字符串可以作为python代码执行,对象传递给repr()函数时,被调用
                                        
                                        上下文管理
                                        # with可以创建一个封闭的上下文空间,代码所访问的资源仅在此范围内有效,当代码离开with语句块之后就会释放资源
                                        with 资源1,资源2,...: # 语法
                                            代码
                                        with open('a.txt',mode='r') as f: # as创建别名
                                            pass 
                                        # 自定义类型支持上下文管理,需实现以下两个方法
                                        '''
                                        __enter__:进入上下文范围内调用此方法,若在with中不需要访问任何案例就返回False,
                                        若需要访问某个案例就返回True
                                        '''
                                        '''
                                         __exit__:退出上下文范围调用。方法接收三个异常相关参数
                                        (异常的类型、异常案例的引用以及traceback对象),若在上下文中引发异常,
                                        异常信息会传递给这三个参数,若为发现异常,三个参数都为None。当上下文中引发异常并且此方法
                                        返回None或False时,异常会被再次抛出并终止程序,若返回True,异常不再抛出
                                        '''
                                        

                                        异常

                                        # 捕获异常
                                        try:
                                            # 可能发生异常的代码
                                        except Exception as e: # 若省略except就必须包含finally子句,这时发生异常时会忽略异常
                                            # 发生异常后处理的代码
                                        finally:
                                            # 可选,不论try后边的代码是否引发异常,该子句都会执行,常用与清理代码(如释放文件资源等)
                                        # 抛出指定的异常
                                        raise Exception("foo occurred")
                                        raise RuntimeError from NameError # 从NameError引发RuntimeError
                                        # 自定义异常,派生自exception类
                                        class CustomException(Exception):
                                            def __init__(self,*args,msg=None):
                                                # 调用基类的构造函数
                                                super().__init__(*args)
                                                # 设置错误信息
                                                self.msg = msg
                                        

                                        模块

                                        将功能相近的函数放到一个文件中,一个py文件就是一个模块,模块名就是文件名去掉后缀

                                        好处:提高代码可复用、可维护性

                                        • 导入模块

                                          • import 模块名 as 别名:导入所有成员,并设置别名

                                          • from 模块名 import 要导入的成员列表:导入部分成员,可以导出单个或多个,成员之间用逗号隔开

                                            • *代表导入所有
                                              • 若模块中设置__all__[]变量,将导入该变量中所列出的成员
                                              • 若未设置,会导入除下划线开头的所有成员
                                              • 上述两种形式都会将模块中的内容加载,若不想其调用,可以在模块内部使用__name__限制模块内的调用,在自己模块中__name__的输出是__main__,否则返回模块的实际名称

                                              • python -m 模块名:运行模块

                                                # 获取当前模块中的所有成员名称
                                                from module import *
                                                dic = globals().copy() # globals返回当前模块中的所有成员名称
                                                for i in dic.keys():
                                                print(i)
                                                
                                              • 动态生成__all__变量,排除以_和py开头的成员

                                                • __all__ = [n for n in globals() if n[0] != '_' and n[:2] != 'py' ]

                                                  当目录下存在__init__.py文件时,该文件可以不写任何代码,只要存在就会视其所在目录为包

                                                  • 当包作为模块被直接运行时,需要在作为包的目录下添加一个__main__.py文件

                                                    import packages # 导入包
                                                    import packages.demo # 导入指定的子模块
                                                    from packages.demo import set # 导入子模块中的指定成员
                                                    # 合并子模块的成员列表
                                                    # 在__init__.py中导入模块的成员
                                                    from .demo1 import _set,age # .表示当前目录下的模块,..代表当前目录的父级目录中的mod模块
                                                    from .demo2 import _get,name
                                                    

                                                    属性

                                                    • 属性系统支持动态操作,所以即使一个空白类,也可以进行属性读写

                                                      • # 空白类
                                                        class demo():
                                                            pass
                                                        d = demo() # 创建案例
                                                        d.age = 18 # 添加属性
                                                        # setattr(obj,name,value)
                                                        setattr(d,'name','zhangsan') # 添加属性
                                                        print(d.age) # 获取属性 18
                                                        # getattr(obj,name[,default])获取不存在且未设置默认值的属性会报错
                                                        print(getattr(d,'name')) # 获取属性 zhangsan
                                                        # __dict__用于存储对象的属性,是一个字典集合,可以直接访问它进行读写属性
                                                        print(d.__dict__) # {'age': 18,'name':'zhangsan'}
                                                        print(d.gender) # 属性不存在发生AttributeError错误
                                                        del d.age # 删除属性,属性被删除后就不能在进行访问
                                                        # delattr(obj,name) 
                                                        delattr(d,'name') # 删除属性
                                                        # hasattr(obj,name)
                                                        hasattr(d,'age') # False 判断属性是否存在
                                                        
                                                      • __slots__

                                                        • 派生类需要重新定义__slots__成员

                                                        • 为类型本身设置属性,且在__slots__中存在该属性,那么该属性对于类型案例就是只读的

                                                        • # 在定义类型时,指定__slots__成员,类型案例就不能再创建__dict__成员
                                                          # 只约束案列不约束类型本身
                                                          class people:
                                                              __slots__ = 'age','name','gender'
                                                              # age = 18 # 报错,类变量与__slots__成员冲突
                                                              # 解决,在__init__中设置,因为__init__在案例创建之后调用
                                                              def __init__(self):
                                                                  self.age = 20 
                                                          p = people()
                                                          p.age = 18
                                                          p.name = 'zhangsan'
                                                          p.classes = 'male' # 报错,没有gender属性
                                                          people.gender = 'male' # 可以设置
                                                          p.gender = 'women' # 报错,只读属性
                                                          
                                                        • 自定义属性访问

                                                          • __getattribute__方法,当案例属性被访问时调用(不论被访问的属性是否存在都会被调用)

                                                          • __getattr__:只在被访问的属性不存在时调用

                                                          • __setattr__:设置属性时调用(不论被访问的属性是否存在都会被调用)

                                                          • __delattr__:当案例属性被删除时调用

                                                          • 描述符

                                                            • 作用:对属性值进行封装,使用描述符时,描述符的案例要存储在当前案例的父级对象的变量字典中

                                                            • 一个类被识别为描述符的条件,即是否存在下列方法

                                                              • __get__:获取属性值时调用

                                                              • __set__:设置属性值时调用

                                                              • __delete__:属性被删除时调用

                                                              • __set_name__:当描述符被案例化并赋值给某个属性时调用

                                                              • property(fget=None,fset=None,fdel=None,doc=None)也可以封装属性值

                                                                异步

                                                                from threading import Thread,Lock
                                                                # 多线程
                                                                '''
                                                                :param group: 保留参数,暂不使用
                                                                :param deamon: 指定新创建的线程是否为守护线程,该线程一般在后台运行
                                                                :param args/kwargs:传递给target参数所引用的函数,若函数无参数,可以忽略 
                                                                :param target: 引用一个函数,在函数中编写需要在新线程中运行的代码,线程启动时调用
                                                                :param name: 指定新线程的名称,一般忽略
                                                                '''
                                                                # 创建线程
                                                                t = Thread(group=None,target=None,name=None,args=(),kwargs=None,*,daemon=None
                                                                # 启动线程
                                                                t.start() # 一个线程案例的生命周期中只能调用一次
                                                                # 由于子线程时异步执行的,主线程不会等待其执行完成,若希望主线程等待子线程执行完成,调用join方法
                                                                t.join() # 等待子线程执行完毕
                                                                # 多个线程访问同一个资源时就需要加锁
                                                                from threading import Thread, Lock
                                                                from time import sleep
                                                                num = 10
                                                                lock = Lock()
                                                                def work():
                                                                    global num  # 全局变量
                                                                    while True:
                                                                        # 方式1
                                                                        # if lock.acquire():  # 加锁
                                                                        #     if num > 0:
                                                                        #         sleep(0.1)
                                                                        #         num -= 1
                                                                        #         print(f'剩余:{num}')
                                                                        #     lock.release()  # 解锁
                                                                        # 方式2
                                                                        with lock:
                                                                            if num > 0:
                                                                                sleep(0.1)
                                                                                num -= 1
                                                                                print(f'剩余:{num}')
                                                                threads = [Thread(target=work) for i in range(3)]  # 创建3个子线程
                                                                for i in threads:
                                                                    i.start()  # 启动子线程
                                                                # 等待事件信号,Event,事件对象可以在不同线程之间访问,调用wait方法会被阻塞,直到事件对象的set方法被调用
                                                                from threading import Thread,Event
                                                                e1 = Event()
                                                                e2 = Event()
                                                                def one():
                                                                    print("downloading one:",end='')
                                                                    for i in range(5):
                                                                        sleep(0.1)
                                                                        print('#',end='')
                                                                    print('done')
                                                                    e1.set() # 完成发送信号
                                                                def two():
                                                                    e1.wait() # 等待信号
                                                                    print("downloading two:", end='')
                                                                    for i in range(5):
                                                                        sleep(0.1)
                                                                        print('#', end='')
                                                                    print('done')
                                                                    e2.set()
                                                                def install():
                                                                    e2.wait()
                                                                    print("installing...")
                                                                    sleep(1)
                                                                    print('success')
                                                                t1 = Thread(target=one)
                                                                t2 = Thread(target=two)
                                                                t3 = Thread(target=install)
                                                                t1.start()
                                                                t2.start()
                                                                t3.start()
                                                                '''
                                                                downloading one:#####done
                                                                downloading two:#####done
                                                                installing...
                                                                success
                                                                '''
                                                                # 异步,若函数内部调用了异步函数,那么该函数也要用async关键字定义
                                                                async def fn(): # 定义
                                                                    pass
                                                                await fn() # 调用
                                                                

                                                                网络

                                                                # TCP服务端通信流程
                                                                # 创建Socket对象
                                                                import socket
                                                                s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_TCP)
                                                                # 绑定地址和接口
                                                                s.bind(('127.0.0.1', 8888))
                                                                # 监听客户端连接请求
                                                                s.listen()
                                                                # 接收客户端的连接,产生一个新的Socket对象,此对象专门用于与客户端进行通信
                                                                cli,addr = s.accept() # cli与客户端进行通信,addr包含客户端的地址和端口
                                                                # 向客户端发送信息或接收来自客户端的信息
                                                                while True:
                                                                    data = cli.recv(1024) # recv读取来自客户端的数据,并设置缓冲区大小为1024字节
                                                                    if not data:
                                                                        break
                                                                    print(f'客户端消息:{bytes(data).decode()}')
                                                                # 关闭Socket,释放资源
                                                                cli.close()
                                                                s.close()
                                                                # TCP客户端通信流程
                                                                # 创建Socket对象
                                                                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
                                                                # 连接服务器
                                                                s.connect(('127.0.0.1',8888))
                                                                # 连接成功,发送或接收数据
                                                                s.send('hi'.encode())
                                                                # 释放资源
                                                                s.close()
                                                                # UDP服务端
                                                                # 创建Socket对象
                                                                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
                                                                # 调用bind绑定url
                                                                s.bind(('127.0.0.1', 9999))
                                                                # 调用recvfrom方法接收
                                                                while True:
                                                                    data, cli = s.recvfrom(1024)
                                                                    if not data:
                                                                        print("no data")
                                                                        break
                                                                    print(f'接收来自{cli[0]}:{cli[1]}的消息:{data.decode()}')
                                                                # 释放资源
                                                                s.close()
                                                                # UDP客户端
                                                                # 创建Socket对象
                                                                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
                                                                # 调用sendto方法向服务器发送数据
                                                                while True:
                                                                    data = input('输入消息: ')
                                                                    if not data:
                                                                        print("no data")
                                                                        break
                                                                    s.sendto(data.encode(),('127.0.0.1', 9999))
                                                                # 释放资源
                                                                s.close()