-
练习1 - 声明一个电脑类属性:品牌、颜色、内存大小方法:打游戏、写代码、看视频a.创建电脑类的对象,然后通过对象点的方式获取、修改、添加和删除 它的属性b.通过attr相关方法去获取、修改、添加和删除它的属性class Computer: def __init__(self,brand,color,ram): self.brand = brand self.color = color self.ram = ram def play_game(self): print("play game") def write_code(self): print("write code") def view_video(self): print("view video") def __str__(self): return str(self.__dict__) # 传入自定义参数computer_one=Computer('Acer','black','4G')#a.对象点的方式获取、修改、添加和删除它的属性print(computer_one) #{'brand': 'Acer', 'color': 'black', 'ram': '4G'}computer_one.brand = "Lenovo"computer_one.color = "yellow"computer_one.ram = "8G"print(computer_one) #{'brand': 'Lenovo', 'color': 'yellow', 'ram': '8G'}computer_one.storage = "1T"print(computer_one) #{'brand': 'Lenovo', 'color': 'yellow', 'ram': '8G', 'storage': '1T'}del computer_one.colorprint(computer_one) #{'brand': 'Lenovo', 'ram': '8G', 'storage': '1T'}#b.通过attr相关方法去获取、修改、添加和删除它的属性computer_two = Computer('Acer','black','4G')a = getattr(computer_two,"brand")b = getattr(computer_two,"color")c = getattr(computer_two,"ram")print(a,b,c) #Acer black 4Gsetattr(computer_two,"brand","Lenovo")setattr(computer_two,"color","blue")setattr(computer_two,"ram","8G")print(computer_two) #{'brand': 'Lenovo', 'color': 'blue', 'ram': '8G'}delattr(computer_two,'brand')print(computer_two)#{'color': 'blue', 'ram': '8G'}setattr(computer_two,'strorage','2T')print(computer_two)#{'color': 'blue', 'ram': '8G', 'strorage': '2T'}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253练习2 - 声明一个人的类和狗的类:狗的属性:名字、颜色、年龄狗的方法:叫唤人的属性:名字、 年龄、狗人的方法:遛狗a.创建人的对象名字叫小明,让他拥有一条狗 ,然后让小明去遛狗class Dog: def __init__(self,name,age,color): self.name = name self.age = age self.color = color def barking(self): print("Dog barking")class Person: def __init__(self,name,age,dog): self.name = name self.age = age self.dog = dog def walking_the_dog(self,dog): print("%s 正在遛一只名字为%s,颜色为%s的狗"% (self.name,dog.name,dog.color)) dog.barking()dog1 = Dog("沙皮", 2, "黄色")p1 = Person("小明", 20, dog1)p1.walking_the_dog(dog1)''' 小明 正在遛一只名字为沙皮,颜色为黄色的狗 Dog barking '''123456789101112131415161718192021222324252627282930练习3 - 声明一个矩形类属性: 长、宽方法:计算周长和面积a.创建不同的矩形,并且打印其周长和面积class Rectangle: def __init__(self,length,width): self.length = length self.width = width def perimeter(self): return (self.length + self.width) * 2 def area(self): return self.length * self.width rec1 = Rectangle(20, 30)print(rec1.perimeter(), rec1.area())rec2 = Rectangle(10, 20)print(rec2.perimeter(), rec2.area())1234567891011121314151617练习4 - 创建一个学生类属性:姓名,年龄,学号,成绩方法:答到,展示学生信息创建一个班级类: 属性:学生,班级名方法:添加学生,删除学生,点名, 获取班级中所有学生的平均值, 获取班级中成绩最好的学生class Student: def __init__(self, name, age, id,score): self.name = name self.age = age self.id = id self.score=score def answer(self): print(self.__dict__) def __str__(self): return str(self.__dict__)class Class: def __init__(self, name, students:list): self.name = name self.students = students def add_student(self,stu:Student): self.students.append(stu) def del_student(self,stu:Student): self.students.remove(stu) def call_student(self,stu:Student): stu.answer() def average_score(self): sum=0 average=0 for stu in self.students: sum+=stu.score average=sum/len(self.students) return average def best_student(self): students.sort(key= lambda item:item.score,reverse=True) return students[0].name def __str__(self): return str(self.__dict__)stu1 = Student("小明", 22, "stu01", 98)stu2 = Student("小李", 24,"stu02", 89)stu3 = Student("小赵", 28,"stu03", 78)stu4 = Student("小张", 26,"stu04", 93)stu5 = Student("小王", 22,"stu05", 86)stu6 = Student("小钱", 26,"stu05", 95)students = [stu1, stu2, stu3, stu4, stu5]python_class = Class("python1807", students)print(python_class)stu6 = Student("小钱", 26, "stu05", 95)#添加学生python_class.add_student(stu6)print(python_class)#删除学生python_class.del_student(stu6)print(python_class)#求平均成绩print(python_class.average_score())#最优秀的学生print(python_class.best_student())#点名python_class.call_student(stu1)''' 结果为:{'name': 'python1807', 'students': [<__main__.Student object at 0x000002421A404B00>, <__main__.Student object at 0x000002421A404B38>, <__main__.Student object at 0x000002421A404B70>, <__main__.Student object at 0x000002421A404BA8>, <__main__.Student object at 0x000002421A404BE0>]}{'name': 'python1807', 'students': [<__main__.Student object at 0x000002421A404B00>, <__main__.Student object at 0x000002421A404B38>, <__main__.Student object at 0x000002421A404B70>, <__main__.Student object at 0x000002421A404BA8>, <__main__.Student object at 0x000002421A404BE0>, <__main__.Student object at 0x000002421A404D68>]}{'name': 'python1807', 'students': [<__main__.Student object at 0x000002421A404B00>, <__main__.Student object at 0x000002421A404B38>, <__main__.Student object at 0x000002421A404B70>, <__main__.Student object at 0x000002421A404BA8>, <__main__.Student object at 0x000002421A404BE0>]}88.8小明{'name': '小明', 'age': 22, 'id': 'stu01', 'score': 98}
-
原文链接:https://bbs.huaweicloud.com/blogs/124474一、python基础 000、Pycharm IDE安装及注册激活笔记(1) 001、Pycharm IDE 安装及注册激活笔记(2) 002、Python基础一 003、Python基础二 004、Python基础数据类型(一) 005、Python基础数据类型(二) 006、Python小数据池、代码块深入剖析 007、Python深浅Copy 008、Python 基础数据类型补充以及编码 009、Python 文件的操作二、python函数 001、 Python 函数初识 002、Python 函数进阶 003、Python 装饰器函数 004、Python 迭代器(函数名使用,新版格式化输出) 005、Python 生成器,内置函数1 006、Python 内置函数II,匿名函数 007、Python 递归函数三、python模块 1、Python 认识模块 001、 什么是模块 002、 模块的导入和使用 2、Python 常用模块一 001、 re模块 002、 time(时间)模块 003、 random(随机数)模块 004、 os(操作系统相关)模块 005、 sys(Python解释器相关)模块 006、 序列化模块 007、 collections(集合)模块 3、Python 常用模块二和包 001、 hashlib 模块 002、 configparse 模块 003、 loggong 模块 004、 包四、正则表达式五、python 异常和异常处理 001、 python 中的异常和错误 002、 python 异常的处理六、python 面向对象 001、 python 面向对象思想的导入 002、 python 初识类和对象 003、 python 类的相关知识 004、 python 对象的知识 005、 python 命名空间与对象的组合 006、 python 初识面向对象的小结 007、 python 面向对象三大特征之继承 008、 python 面向对象三大特征之多态 009、 python 面向对象三大特征之封装 010、 python 面向对象其他知识 011、 python 面向对象isinstance和issubclass 012、 python 面向对象之反射 013、 python 类和对象相关的内置函数七、python 网络编程 001、 python 网络编程之序言 002、 python 网络编程之网络基础 003、 python网络编程之网络协议 004、 python网络编程之套接字的初使用 005、 python网络编程之黏包 006、 python网络编程之Socket相关方法八、python 并发编程 001、 python并发编程之操作系统介绍 002、 python并发编程之进程理论 1)、进程理论知识之操作系统背景知识 2)、进程理论知识之什么是进程 3)、进程理论知识之进程调度 4)、进程理论知识之进程的并发与并行 5)、进程理论知识之同步|异步|阻塞|非阻塞 6)、进程理论知识之进程的创建与结束 003、 python并发编程之进程操作 1)、进程操作之multiprocess模块及创建 2)、进程操作之同步控制--锁 3)、进程操作之进程间通信--队列 4)、进程操作之数据共享--Manager 5)、进程操作之进程池--Pool 004、 python并发编程之线程理论 1)、线程概念的引入背景 2)、线程的理论知识 3)、进程和线程的关系 4)、线程的特点 5)、线程的使用场景及内存中的线程 6)、用户级线程和内核级线程 005、 python并发编程之线程操作 1)、Threading 模块 2)、线程锁 3)、进程队列 4)、标准模块concurrent.futures 006、 python并发编程之协程 1)、协程的引入 2)、协程的介绍 3)、协程之Greenlet模块 4)、协程之Gevent模块 007、 python IO模型 1)、IO模型之IO模型介绍 2)、IO模型之阻塞IO(blocking IO) 3)、IO模型之非阻塞IO(non-blocking IO) 4)、IO模型之多路复用IO(IO multiplexing) 5)、IO模型之异步IO(Asynchronous I/O) 6)、IO模型之模型比较分析 7)、IO模型之selectors模块九、python 数据库 001、 python数据库之初识数据库 002、 python数据库之初识MYSQL数据库 003、 python数据库之表操作mysql中的存储引擎 004、 python数据库之表操作中表介绍 005、 python数据库操作之表创建 006、 python数据库操作之mysql中的数据类型 007、 python数据库操作之mysql完整约束性 008、 python数据库操作之表操作中删除表结构 009、 python数据库操作之表操作中多表结构的创建与分析 010、 python数据库操作之作业 011、 python数据库操作之数据增/删/改 012、 python数据库操作之单表查询 013、 python数据库操作之连表查询 014、 python数据库操作之连表查询中的子查询 015、 python数据库操作之综合练习 016、 python Mysql数据库常见的函数 017、 python数据库之索引原理 018、 python数据库之索引的数据结构 019、 python数据库之聚集索引与辅助索引 020、 python数据库之索引管理 021、 python数据库之测试索引 022、 python数据库之正确索引 023、 python数据库之联合索引和覆盖索引 024、 python数据库之查询优化神器-explain 025、 python数据库之性能分析explain 026、 python使用python操作MySQL数据库 027、 python数据库中数据的备份 028、 pythonMySQL练习题参考答案十、python 前端开发HTML/CSS/JS 001、 python前端开发之HTML 002、 python前端开发之CSS介绍及引入方式 003、 python前端开发之CSS选择器 004、 python前端开发之CSS盒模型 005、 python前端开发之CSS标准文档流及元素 006、 python前端开发之CSS浮动 007、 python前端开发之CSS定位 008、 python前端开发之CSS Background 009、 python前端开发之javascript介绍 010、 python前端开发之javascript语法 011、 python前端开发之javascript面向对象 012、 python前端开发之jQuery介绍 013、 python前端开发之JS对象与jQuery对象的比较 014、 python前端开发之jQuery绑定事件及操作标签 015、 python前端开发之jQuery动画效果 016、 python前端开发之jQuery事件操作
-
Python基础环境搭建Python的运行环境从官网下载相应版本,下载安装anaconda,下载使用docker安装pypy,官网Python包管理直接使用pip使用conda使用虚拟环境使用景象加速(https://pypi.tuna.tsinghua.edu.cn/simple)创建一个stenv目录,然后进入到stenv目录 创建虚拟环境 python3 -m venv . 激活虚拟环境 source bin/activate #windows中直接执行activate.bat 这虚拟环境就创建完成 退出虚拟环境 终端执行命令:deactivate123456789将Python运行起来使用终端直接作为脚本在编译器运行打包为可执行程序 (pyinstaller -F source)基础语法快速入门''' 基本命名方式 module_name, 模块 package_name, 包 ClassName, 类 驼峰 method_name, 方法 ExceptionName, 异常 function_name, 函数 下划线 GLOBAL_VAR_NAME, 全局变量 instance_var_name, 实例 function_parameter_name, 参数 local_var_name. 本变量 ''' """ 关键字 and exec not assert finally or break for pass class from print continue global raise def if return del import try elif in while else is with except lambda yield """ #基本变量 a = 3 b = 3.5 c = "hello" d = ['1',123,3.5] #条件判断,使用4个空格缩进,不使用tab if a == 3: print("a is 3") else: print("a is not 3") #循环 for i in range(3): print(i) #函数 def add(a,b): """ 实现两个数相加 :param a: 加数 :param b: 被加数 :return: 返回相加结果 """ return a + b #类 class StMath(object): """ 实现数学计算的类 """ def __init__(self,a_in): """ 初始化方法 :param a_in: 初始化数值 """ super().__init__() self.a = a_in def add(self,B): """ 实现两个math对象相加 :param B: 被加math对象 :return: 相加结果 """ return StMath(self.a + B.b)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475基本类型数字类型高精度!高精度!高精度!重要的事说三遍字符串基本操作#增删改查 content = "abcxabcyabc" print(content+"123") print(content[:2]+content[4:]) print(content.replace("abc","python")) print(re.sub("abc","python",content)) #使用正则表达式替换 print(content.find("xyz",2)) #或"xyz" in content print(re.findall("abc",content))123456789101112编码问题python3中,文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str和bytes,正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串一个乱码问题演示"你好".encode("utf-8").decode("gbk") #str,bytes再一个事例 "你好".encode("unicode-escape").decode() ord('你')12345Listlist具有范型特征(讲完对象再回顾排序)#增删改查 a = [1,2,3,4,5,6,7] #增加元素 a.append(8) #删除元素 a.remove(3) #查找元素 a.index(6) #修改元素 a[4] = 10 #切片操作,会忽略结束元素 a[2:5] #注意不会包括索引5的元素 a[::-1] #反序操作 #便利操作 for v in a: print(v) #如果属性要索引 for i,v in enumerate(a): print(i,v)1234567891011121314151617181920212223字典#增删改查 stu_dict = {"name":"jack","age":21,"s**":100} #增加 stu_dict["phone"] = "18000000000" #删除 del stu_dict["phone"] #修改 stu_dict["name"] = "lucy" #stu_dict.update({}) #查询 stu_dict.get("name") #和stu_dict["name"]区别1234567891011使用函数函数是python的一等公民,变为:运行时创建能赋值能传参能返回函数的参数不可变对象str,int,number都是不可变对象,采用值传递a = 20 def change_value(x): x = 100 change_value(a) print(a) #结果仍然是201234567可变对象list,dict是可变对象,采用引用传递def change_list(x): x.append(20) y = [1,2,3] change_list(y) print(y) # 结果是1,2,3,201234567定位参数和关键字参数定位参数必须按照次序,关键字参数可以任意打乱次序,可以赋默认值def extract_content(tag_name,start_pos = 20) print("tag_name is ::::::",tag_name)12*args, **karges使用args和kargs传入不定长参数,args捕获的定位参数被组织为元组,kargs捕获的参数被组织为字典def extract_content(*args,**kargs): print(args) print(kargs) extract_content("a",3.5,[1,2,3],name="jack",age="22")123456数组加上*号传入会被args解包后逐个捕获list_args = [1,2,3,4,5,6] extract_content(*list_args)123函数的注解可以给参数和返回值附加元数据,对于复杂数据支持的时候可以提高易读性,提升开发效率,Python自身不做检查不做校验,不会对程序的行为产生影响,仅仅是一种约定def add(add_a:int,add_b:int) -> int: return add_a + add_b print(add(10,20))1234变量的作用阈全局作用域与局部作用域#下面的代码错在什么地方?使用global纠正 m = 10 def show_diff(): print("********show_diff*********") global n = 20 print(m) m = 90 print(n)12345678910函数和闭包#函数和闭包 def create_sum(): sum = 0 def sum_all(a_in): nonlocal sum sum += a_in return sum return sum_all s_custom = create_sum() #本质是什么 #print(s_custom.__closure__[0].cell_contents) print(s_custom(10)) print(s_custom(20)) print(s_custom(30))12345678910111213141516如何做为一等公民?可以赋值p = add print(p(10,20))12可以作为参数传递(linux,spring设计)def download_url(url_str,extract_rule): print("下载了某个网页") result = "<html><head><a href='//www.baidu.com'></a></head></html>" urls = extract_rule(result) print("页面的所有地址是:",urls) def normal_url_rule(result): return re.findall("<a\s+href=\'(.*?)\'",result) def no_http_url_rule(result): origin_url = re.findall("<a\s+href=\'(.*?)\'",result) return ["http:"+ url for url in origin_url] download_url("",no_http_url_rule)123456789101112131415做为返回值def math_rule(): def rule(a,b): return a+b return rule rule = math_rule() print(rule(20,30))123456789装饰器装饰器的本质,函数的嵌套调用import time #装饰器 def download_html(): time.sleep(1) print("执行了下载操作") def record_time(download_func): def record_wrapper(): start_time = time.time() download_func() end_time = time.time() print("下载经过了时间",end_time - start_time) return record_wrapper decorate_download = record_time(download_html) decorate_download()123456789101112131415161718192021使用语法糖,更直观的使用体验:@record_time def download_html(): time.sleep(1) print("执行了下载操作") download_html()1234567装饰器中传递参数:def record_time(level): def decorate(download_func): def record_wrapper(*args,**kargs): print("下载网址是:",args) print("日志等级是",level) start_time = time.time() download_func() end_time = time.time() print("下载经过了时间",end_time - start_time) return record_wrapper return decorate @record_time(level=9) def download_html(): time.sleep(1) print("执行了下载操作")1234567891011121314151617面向对象面向对象的基本特点,封装、继承、多态,抽象用来设计类的层次结构面向对象基础self,方法重写,@classmethod @staticmethod,内置方法重写class Person(object): """ 定义抽象基类 """ def __init__(self,score): self.score = score self.__name = "jack" #加上两个下划线,表示私有方法 @classmethod def from_file(cls,file_name): """ 从文件读取学生成绩 :param file_name: 文件名 :return: """ score = open("score.txt").read() return cls(score) @staticmethod def extract_address(): return "no.90" def run(self): print("person run!!!!") def __add__(self, other): return Student(self.score + other.score) class Student(Person): """ 学生信息类 """ def __init__(self,score): super().__init__(score) def ask(self): print("ask a question!!") def run(self): super().run() print("student run!!",self.score) # p = Person(85) # p.run() s = Student.from_file("test.txt") print(Student.extract_address()) s.run()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051抽象层构建抽象基类中的抽象方法必须在子类中实现,否则子类无法实例化。#抽象接口 from abc import ABC,abstractmethod class Person(ABC): """ 定义抽象基类 """ def __init__(self): pass @abstractmethod def run(self): pass class Student(Person): def __init__(self): super().__init__() def ask(self): print("ask a question!!") def run(self): print("run run run1!!")1234567891011121314151617181920212223动态特性运行过程中动态判断属性,设置属性,可以结合配置文件灵活实现类的加载,修改hasattrsetattrhasattrpackage = __import__('st_python_base') student_class = getattr(package,'Student') s = student_class(90) s.run()12345当出现未知访问属性的时候,进行处理 def __getattr__(self, item): print('getattr')12内存管理关于引用计数import weakref def over(): print("student is over!!!") x = st_python_base.Student(10) ender = weakref.finalize(x,over) y = x123456789关于深复制和浅复制注意直接赋值,copy,deepcopy的区别?from copy import copy from copy import deepcopy class Student(object): def __init__(self): self.course = [1,2,3,4,5] self.name = "jack" s1 = Student() s2 = deepcopy(s1) s1.course.append(12) print(s2.course)123456789101112131415上下文管理with…as…的本质class StTools(object): def __enter__(self): print("进入上下文块。。。。") return self def __exit__(self, exc_type, exc_val, exc_tb): print("从上下文块退出") def make_sign(self): print("test!!!") with StTools() as st: st.make_sign()12345678910111213141516关于迭代器和生成器理解yield和senddef s(): print('begin test') a = yield 10 print(a) b = yield 20 print('end test!')
-
1.一个程序如何在网络上找到另一个程序?首先,程序必须要启动,其次,必须有这台机器的地址,我们都知道我们人的地址大概就是国家\省\市\区\街道\楼\门牌号这样字。那么每一台联网的机器在网络上也有自己的地址,它的地址是怎么表示的呢?就是使用一串数字来表示的,例如:100.4.5.6什么是IP地址:IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。 IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。什么是端口:"端口"是英文port的意译,可以认为是设备与外界通讯交流的出口。在windows上查看端口占用的情况:netstat -aon|findstr "49157"因此ip地址精确到具体的一台电脑,而端口精确到具体的程序。2.osi七层模型1)、引子须知一个完整的计算机系统是由硬件、操作系统、应用软件三者组成,具备了这三个条件,一台计算机系统就可以自己跟自己玩了(打个单机游戏,玩个扫雷啥的)如果你要跟别人一起玩,那你就需要上网了,什么是互联网?互联网的核心就是由一堆协议组成,协议就是标准,比如全世界人通信的标准是英语,如果把计算机比作人,互联网协议就是计算机界的英语。所有的计算机都学会了互联网协议,那所有的计算机都就可以按照统一的标准去收发信息从而完成通信了。2)、osi七层模型人们按照分工不同把互联网协议从逻辑上划分了层级:3.socket概念1)、socket层2)、理解socketSocket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。站在你的角度上看待socket:其实站在你的角度上看,socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。 也有人将socket说成ip+port,因为ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序。 所以我们只要确立了ip和port就能找到一个应用程序,并且使用socket模块来与之通信。4.套接字(socket)的发展史套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。 1)、基于文件类型的套接字家族套接字家族的名字:AF_UNIXunix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信2)、基于网络类型的套接字家族套接字家族的名字:AF_INET(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)5.tcp协议和udp协议TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
-
关键词匹配利器FlashText在实际开发工作中经常遇到,根据词表或映射表,查找或替换文本中内容,比较简单处理方法就是逐词匹配,这种处理方式不是高效的,而且代码写起来也会感觉很啰嗦,使用FlashText能够很好的帮助我们解决这个问题。提取文本中字典涉及的关键词并将多个词归一化为某个关键词from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> # keyword_processor.add_keyword(, )>>> keyword_processor.add_keyword(‘Big Apple’, ‘New York’)>>> keyword_processor.add_keyword(‘Bay Area’)>>> keywords_found = keyword_processor.extract_keywords(‘I love Big Apple and Bay Area.’)>>> keywords_found>>> # [‘New York’, ‘Bay Area’]替换词组>>> keyword_processor.add_keyword(‘New Delhi’, ‘NCR region’)>>> new_sentence = keyword_processor.replace_keywords(‘I love Big Apple and new delhi.’)>>> new_sentence>>> # ‘I love New York and NCR region.’大小写敏感,通过case_sensitive设置>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor(case_sensitive=True)>>> keyword_processor.add_keyword(‘Big Apple’, ‘New York’)>>> keyword_processor.add_keyword(‘Bay Area’)>>> keywords_found = keyword_processor.extract_keywords(‘I love big Apple and Bay Area.’)>>> keywords_found>>> # [‘Bay Area’]获取匹配到字符起始位置,通过span_info设置>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_processor.add_keyword(‘Big Apple’, ‘New York’)>>> keyword_processor.add_keyword(‘Bay Area’)>>> keywords_found = keyword_processor.extract_keywords(‘I love big Apple and Bay Area.’, span_info=True)>>> keywords_found>>> # [(‘New York’, 7, 16), (‘Bay Area’, 21, 29)]获取关键词提取时提取信息,包含匹配字符及归一化关键词>>> from flashtext import KeywordProcessor>>> kp = KeywordProcessor()>>> kp.add_keyword(‘Taj Mahal’, (‘Monument’, ‘Taj Mahal’))>>> kp.add_keyword(‘Delhi’, (‘Location’, ‘Delhi’))>>> kp.extract_keywords(‘Taj Mahal is in Delhi.’)>>> # [(‘Monument’, ‘Taj Mahal’), (‘Location’, ‘Delhi’)]>>> # NOTE: replace_keywords feature won’t work with this.不包含多词归一化的关键词提取>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_processor.add_keyword(‘Big Apple’)>>> keyword_processor.add_keyword(‘Bay Area’)>>> keywords_found = keyword_processor.extract_keywords(‘I love big Apple and Bay Area.’)>>> keywords_found>>> # [‘Big Apple’, ‘Bay Area’]增加多词词典>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_dict = {>>> “java”: [“java_2e”, “java programing”],>>> “product management”: [“PM”, “product manager”]>>> }>>> # {‘clean_name’: [‘list of unclean names’]}>>> keyword_processor.add_keywords_from_dict(keyword_dict)>>> # Or add keywords from a list:>>> keyword_processor.add_keywords_from_list([“java”, “python”])>>> keyword_processor.extract_keywords(‘I am a product manager for a java_2e platform’)>>> # output [‘product management’, ‘java’]删除关键词>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_dict = {>>> “java”: [“java_2e”, “java programing”],>>> “product management”: [“PM”, “product manager”]>>> }>>> keyword_processor.add_keywords_from_dict(keyword_dict)>>> print(keyword_processor.extract_keywords(‘I am a product manager for a java_2e platform’))>>> # output [‘product management’, ‘java’]>>> keyword_processor.remove_keyword(‘java_2e’)>>> # you can also remove keywords from a list/ dictionary>>> keyword_processor.remove_keywords_from_dict({“product management”: [“PM”]})>>> keyword_processor.remove_keywords_from_list([“java programing”])>>> keyword_processor.extract_keywords(‘I am a product manager for a java_2e platform’)>>> # output [‘product management’]查看关键词词条数>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_dict = {>>> “java”: [“java_2e”, “java programing”],>>> “product management”: [“PM”, “product manager”]>>> }>>> keyword_processor.add_keywords_from_dict(keyword_dict)>>> print(len(keyword_processor))>>> # output 4查看词条是否在词典中>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_processor.add_keyword(‘j2ee’, ‘Java’)>>> ‘j2ee’ in keyword_processor>>> # output: True>>> keyword_processor.get_keyword(‘j2ee’)>>> # output: Java>>> keyword_processor[‘colour’] = ‘color’>>> keyword_processor[‘colour’]>>> # output: color获取词典中所有关键词>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_processor.add_keyword(‘j2ee’, ‘Java’)>>> keyword_processor.add_keyword(‘colour’, ‘color’)>>> keyword_processor.get_all_keywords()>>> # output: {‘colour’: ‘color’, ‘j2ee’: ‘Java’}设置或增加词分隔符,这个方法更适用于英文文本>>> from flashtext import KeywordProcessor>>> keyword_processor = KeywordProcessor()>>> keyword_processor.add_keyword(‘Big Apple’)>>> print(keyword_processor.extract_keywords(‘I love Big Apple/Bay Area.’))>>> # [‘Big Apple’]>>> keyword_processor.add_non_word_boundary(’/’)>>> print(keyword_processor.extract_keywords(‘I love Big Apple/Bay Area.’))>>> # []
-
先一句话总结Python中继承、抽象基类和接口三者之间的关系:Python中的接口机制可通过抽象基类实现,接口的实现有赖于继承机制。一、继承继承是面向对象编程语言的三大特性之一(其他两个是封装、多态),所谓继承是指子类自动具有父类所定义的方法和属性,而无需子类再重复定义同名的方法或属性,因此继承的最大优势之一是可以提高代码的复用程度。1. 常见数列案例这里以高中数学中一个重要的概念——数列来简介Python的继承概念。数列是一组数值组成的序列,该序列中的每一个值都取决于数列的前一项或多项,例如:对于等差数列,数列中从第二项开始,每一项都由前一项加上一个固定的常量得到;对于等比数列,数列中从第二项开始,每一项都由前一项乘上一个固定的常量得到;对于斐波那契数列,数列中从第三项开始,每一项都有其前两项之和相加得到。如果现在需要使用面向对象特性对上述各个不同类型的数列进行代码抽象,则可以想到三个数列类必然都支持下列类似功能的方法:初始化方法:用于初始化数列的前若干项;遍历支持方法:可以支持以可迭代的方式遍历出数列的项;数列项生成方法:按照一定的规则根据前若干项生成任意项。如果不采用继承的方式,则最终实现的各数列类必然代码重复度很高。2. 常见数列实现针对上述讨论,下面考虑使用继承实现各个数列类:首先,定义一个通用数列父类Progression,在其中实现数列的共有方法及实用方法;然后,继承Progression类再根据数列通项生成规则分别在等差、等比、斐波那契数列中重写父类方法或定义全新方法。数列基类在数列基类中:__init__初始化方法接收两个参数,start用以指定数列第一项的值,num用以指定默认打印的数列项数,分别用于初始化_current和_num的值;_advance方法用于按照数列通项规则生成任意项;__iter__和__next__方法用以支持Python的迭代器协议(具体请见Python中for循环运行机制探究以及可迭代对象、迭代器详解),用于数列的遍历;__str__方法用于将数列对象转换为列表,并返回该列表的字符串表示形式。class Progression: """数列基类""" def __init__(self, start=0, num=10): """ 将当前数列的第一项初始化为0 :param start: 数列第一项,默认为0 :param num: 打印数列时的默认显示项数 """ self._current = start self._num = num def _advance(self): """用于根据数列前若干项进行任意项的生成,该方法应该被子类重写""" self._current += 1 def __next__(self): """迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常""" if self._num > 0: ans = self._current self._advance() self._num -= 1 return ans else: raise StopIteration def __iter__(self): """迭代器协议方法,返回对象自身""" return self def __str__(self): """返回对象的字符串表示形式""" return str(list(self))123456789101112131415161718192021222324252627282930313233等差数列在等差数列的实现中,由于继承了Progression类,所以:__init__方法中调用了父类初始化方法,从而对继承自父类的_current以及默认打印的数列项数_num进行了初始化,另外还对该类特有的等差数列常量_increment进行了初始化;_advance方法按照等差数列通项规则对父类同名方法进行了重写;__next__、__iter__和__str__方法继承自Progression类,无需重复编写代码。class ArithmeticProgression(Progression): """等差数列""" def __init__(self, start=0, increment=1, num=10): """ 创建一个新的等差数列 :param increment: 等差常量,默认为1 :param start: 数列首项,默认为0 :param num: 打印数列时的默认显示项数 """ super().__init__(start=start, num=num) self._increment = increment def _advance(self): # 重写父类同名方法 """根据等差数列通项规则,生成任意项""" self._current += self._increment12345678910111213141516等比数列在等比数列的实现中,由于继承了Progression类,所以:__init__方法中调用了父类初始化方法,从而对继承自父类的_current以及默认打印的数列项数_num进行了初始化,另外还对该类特有的等比数列常量_base进行了初始化;_advance方法按照等比数列通项规则对父类同名方法进行了重写;__next__、__iter__和__str__方法继承自Progression类,无需重复编写代码。class GeometricProgression(Progression): """等比数列""" def __init__(self, start=1, num=10, base=2): """ 创建一个新的等比数列 :param base: 等比常量,默认值为2 :param start: 数列首项,默认为1 :param num: 打印数列时的默认显示项数 """ super().__init__(start=start, num=num) self._base = base def _advance(self): """根据等比数列通项规则,生成任意项""" self._current *= self._base12345678910111213141516斐波那契数列在斐波那契数列的实现中,由于继承了Progression类,所以:__init__方法中调用了父类初始化方法,从而对继承自父类的_current以及默认打印的数列项数_num进行了初始化,另外还对该类特有的假想第0项_prev进行了初始化;_advance方法按照斐波那契数列通项规则对父类同名方法进行了重写;__next__、__iter__和__str__方法继承自Progression类,无需重复编写代码。class FibonacciProgression(Progression): """斐波那契数列""" def __init__(self, first=0, second=1, num=10): """ 创建一个新的斐波那契数列 :param first: 数列第一项,默认为0 :param second: 数列第二项,默认为1 :param num: 打印数列时的默认显示项数 """ super().__init__(start=first, num=num) self._prev = second - first # 假想在第一项之前存在的第零项 def _advance(self): """根据斐波那契数列通项规则,生成任意项""" self._prev, self._current = self._current, self._prev + self._current12345678910111213141516下面是对上述几个数列实现类的测试结果:if __name__ == '__main__': print('默认数列Progression:') print(Progression(num=5), end='\n'*2) # [0, 1, 2, 3, 4] print('等差数列ArithmeticProgression:') print(ArithmeticProgression(start=10, increment=3, num=7), end='\n'*2) # [10, 13, 16, 19, 22, 25, 28] print('等比数列GeometricProgression:') print(GeometricProgression(start=4, base=3, num=9), end='\n'*2) # [4, 12, 36, 108, 324, 972, 2916, 8748, 26244] print('斐波那契数列FibonacciProgression:') print(FibonacciProgression(first=2, num=12)) # [2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199]123456789101112二、抽象基类仔细分析上述代码可知,基类Progression仅是为了作为ArithmeticProgression、GeometricProgression以及FibonacciProgression的基类,虽然可以通过实例化Progression得到一个对象,但这意义不大,因为其仅是ArithmeticProgression的一种特殊情况,即第一项为0,等差常量为1的等差数列。在支持面向对象编程范式的语言中,对Progression这种仅作为基类用于指定多个子类所需实现的方法的类,有一个专门的术语——抽象基类。在Python3中想要定义一个抽象基类,可通过如下步骤实现:在定义抽象基类前,从模块abc中导入类ABCMeta和方法abstractmethod;在定义抽象基类时:在抽象基类名后指定metaclass为ABCMeta;在抽象基类需被子类继承后实现的方法(一般称为抽象方法)前使用@abstractmethod。例如:如前所述,对于Progression方法,按照上述流程将其定义为抽象基类的代码如下:from abc import ABCMeta, abstractmethodclass Progression(metaclass=ABCMeta): """数列基类""" def __init__(self, start=0, num=10): """ 将当前数列的第一项初始化为0 :param start: 数列第一项,默认为0 :param num: 打印数列时的默认显示项数 """ self._current = start self._num = num @abstractmethod def _advance(self): """用于根据数列前若干项进行任意项的生成,该方法应该被子类重写""" def __next__(self): """迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常""" if self._num > 0: ans = self._current self._advance() self._num -= 1 return ans else: raise StopIteration def __iter__(self): """迭代器协议方法,返回对象自身""" return self def __str__(self): """返回对象的字符串表示形式""" return str(list(self))123456789101112131415161718192021222324252627282930313233343536可以看出,上述代码中我们将_advance定义成了抽象方法,因为该方法一方面在所有子类中都必须存在,另一方面该方法在所有子类中的实现又都完全不同。需要指出的是,对于抽象基类(如:Progression)不能直接对其通过实例化创建对象,否则会报这样的错误:TypeError: Can't instantiate abstract class Progression with abstract methods _advance。三、接口接口是一种编程机制,这种机制可以确保不同的代码编写者可以:遵循相同的代码签名,如:方法名称(_advance)、参数、返回值;使用不同的算法实现具体代码,如:根据等差、等比、斐波那契数列的通项生成规则实现_advance方法。接口机制的好处在于,可以:实现不同代码编写者之间的协作,如:应用架构者可以对整体框架做搭建,而将具体实现留给实施人员,这有点像你的老板一般会告诉你要做根据手头的资源某几件事情以及期望结果是什么,而你和你的同事需要通过一定的过程努力将每一件事具体实施好;实现代码间的松耦合,各个接口的实现人员无需了解其他人员对接口的内部具体实现。Python中,对于接口的具体实现,只要在子类中继承抽象基类,然后实现其中的所有抽象方法即可。下面还是以上述的数列类为例演示接口实现的过程:from abc import ABCMeta, abstractmethodclass Progression(metaclass=ABCMeta): """数列基类""" def __init__(self, start=0, num=10): """ 将当前数列的第一项初始化为0 :param start: 数列第一项,默认为0 :param num: 打印数列时的默认显示项数 """ self._current = start self._num = num @abstractmethod def _advance(self): """用于根据数列前若干项进行任意项的生成,该方法应该被子类重写""" def __next__(self): """迭代器协议方法,返回数列中的下一项,当已至数列最后一项则抛出StopIteration异常""" if self._num > 0: ans = self._current self._advance() self._num -= 1 return ans else: raise StopIteration def __iter__(self): """迭代器协议方法,返回对象自身""" return self def __str__(self): """返回对象的字符串表示形式""" return str(list(self))class FibonacciProgression(Progression): """斐波那契数列""" def __init__(self, first=0, num=10, second=1): """ 创建一个新的斐波那契数列 :param first: 数列第一项,默认为0 :param second: 数列第二项,默认为1 :param num: 打印数列时的默认显示项数 """ super().__init__(start=first, num=num) self._prev = second - first # 假想在第一项之前存在的第零项 def _advance(self): """根据斐波那契数列通项规则,生成任意项""" self._prev, self._current = self._current, self._prev + self._currentif __name__ == '__main__': print(FibonacciProgression(first=2, num=12)) # [2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, 199]
-
基本语法1.1.1第一个注释print(“hello,python”) # 第二行注释string_demo = “你好!”string_demoprint (3,4)def find_all (self) :‘’‘Return all itms.’’’return self.find(‘all’)1.1.2行与缩进if True:print(“True”)else:print(“False”) # 行与缩进必须一致一般都是默认空格四个print(“False”) # 语法错误,同级缩进不一致注意在python中不能用tab键盘,以及tab与空格键混用1.1.3语句换行python 代码建议不超过80个 ,过长在外侧添加一对圆括号string = (“python 是一种面向对象、解释型计算机程序设计语言,”“有Guido van R ossum 于19**低发明”“pyton源代码同样遵循GPL协议”)但是在有{}、【】、或()链接的多行语句会进行隐式链接,就不需要再用上面的方法进行换行。total = [‘irem_one,’ ‘total_two’,‘total_three’‘total_for’]变量和数据类型1.1变量与赋值变量相当于购物车,用来存储数据,然后有python再对这些数据进行累加num_one = 10 # num_one 就是一个变量,就好比一个购物车,存储的数据是10num_two =89 # num_two 也是一个变量,存储的数据是89把 num_one 与 num_two 两个‘购物车’进行累加,放到result变量中result = num_one + num_two1.2变量的类型不同大小的商品用不同大小的‘购物车’因此变量分为不同的数据类型变量的数据类型:数字型 、 布尔型、 字符串型、 列表型、 元组型、 字典型数字型分为:整形 、 浮点型、 复数整形:0101 80 -21 2x50 15503浮点型: 3.15 、 5.1E-10 -2.5e-15复数型:3.12+1.2j 、 -1.2-15j布尔型;有True 与False 两种 在运算时True被当作1 、False被当作0字符串型:pyrhon 中的字符串被定义为一个字符集合,它被引号所包含。这里的引号可以是单引号、双引号、三引号。字符串具有索引规则,第一个字符的索引是0,第二个字符的索引是1.例子string_one = ‘python’string_two = “python”string_three = ‘’‘python’’’列表和元素类型我们可以将列表和元组当作高中学的普通的“数组”,他们可以保存任意数量任意类型的值,这些值称作元素,。列表中的元素使用[ ]包含,中括号里的值可以任意改变。元组中的值用( )包住,其中的值不可以被修改。list_name = [ 1, 2, ‘hello’ ] # 这是一个列表tuple_name = ( 1,2, ‘hello’ ) #这是一个元组字典类型字典是python中映射的数据类型,有建—组成。字典可以储存不同类型的数据类型的元素,元素使用大括号{ } 来包含。 通常情况下,字典的键会以字符串或者数值的形式来表示,而值可以是任意类型。dict_name = { “name” :" zhangsan ‘’ ,’’ :18} #这是一个字典上述是dict_name 是一个字典类型,它储存了两个元素,第一个与元素的键为name,值为zhangsan ;第二个元素的键为age,值为18在python中,只要定义一个变量,并且该变量储存了数据,那么变量的数据类型就已经确立了。系统会自动辨别变量的数据类型,不需要开发者标注说明。使用:type(变量的名字) 命令来查看数据类型。number = 5.2type(number)<class ’ float’>number 的数据类型为5.2 ,系统会自动判断number的数据类型为float。
-
用户输入内容将以下程序保存为 io_input.py :def reverse(text): return text[::-1] def is_backtext(text): return text == reverse(text) something = input("请输入文字: ") if is_backtext(something): print("是回文") else: print("不是回文")123456789输出:python io_input.py 输入文字: abc 不是回文 python io_input.py 输入文字: moom 是回文1234567我们使用切片功能翻转文本。我们已经了解了我们可以通过使用 seq[a:b] 来从位置 a 开 始到位置 b 结束来对序列进行切片。我们同样可以提供第三个参数来确定切片的步长 (Step)。默认的步长为 1 ,它会返回一份连续的文本。如果给定一个负数步长,如 -1 , 将返回翻转过的文本。input()函数可以接受一个字符串作为参数,并将其展示给用户。尔后它将等待用户输入内 容或敲击返回键。一旦用户输入了某些内容并敲下返回键, input() 函数将返回用户输入的 文本。我们获得文本并将其进行翻转。如果原文本与翻转后的文本相同,则判断这一文本是回文。文件你可以通过创建一个属于 file 类的对象并适当使用它的 read 、 readline 、 write 方法 来打开或使用文件,并对它们进行读取或写入。读取或写入文件的能力取决于你指定以何种 方式打开文件。最后,当你完成了文件,你可以调用 close 方法来告诉 Python 我们已经完 成了对该文件的使用。案例(保存为 io_using_file.py ):poem = '''编程是很有趣的事件, 如果你想让你的工作也变得有趣的话: 使用Python!'''# 打开文件以编辑('w'riting) f = open('poem.txt', 'w',encoding='utf-8') # 向文件中编写文本 f.write(poem) # 关闭文件 f.close()# 如果没有特别指定, # 将假定启用默认的阅读('r'ead)模式 f = open('poem.txt') while True: line = f.readline() # 零长度指示 EOF if len(line) == 0: break # 每行(`line`)的末尾 # 都已经有了换行符 #因为它是从一个文件中进行读取的 print(line, end='') # 关闭文件 f.close()123456789101112131415161718192021222324输出:python io_using_file.py 编程是很有趣的事件,如果你想让你的工作也变得有趣的话: 使用Python!1234它是如何工作的首先,我们使用内置的 open 函数并指定文件名以及我们所希望使用的打开模式来打开一个 文件。打开模式可以是阅读模式( ‘r’ ),写入模式( ‘w’ )和追加模式( ‘a’ )。我们还 可以选择是通过文本模式( ‘t’ )还是二进制模式( ‘b’ )来读取、写入或追加文本。实际 上还有其它更多的模式可用, help(open) 会给你有关它们的更多细节。在默认情况 下, open() 会将文件视作文本(text)文件,并以阅读(read)模式打开它。在我们的案例中,我们首先采用写入模式打开文件并使用文件对象的 write 方法来写入文 件,并在最后通过 close 关闭文件。接下来,我们重新在阅读模式下打开同一个文件。我们不需要特别指定某种模式,因为“阅读 文本文件”是默认的。我们在循环中使用 readline 方法来读取文件的每一行。这一方法将会 一串完整的行,其中在行末尾还包含了换行符。当一个空字符串返回时,它表示我们已经到 达了文件末尾,并且通过 break 退出循环最后,我们最终通过 close 关闭了文件。现在,你可以检查 poem.txt 文件的内容来确认程序确实对该文件进行了写入与读取操作。encoding=utf-8当我们阅读或写入某一文件或当我们希望与互联网上的其它计算机通信时,我们需要将我们 的 Unicode 字符串转换至一个能够被发送和接收的格式,这个格式叫作==“UTF-8”==。我们可以在 这一格式下进行读取与写入,只需使用一个简单的关键字参数到我们的标准 open 函数中: encoding=‘utf-8’Unicode 有“统一码”“万国码”“国际码”等多种译名。
-
python列表练习题===================一、创建列表1.创建一个列表,命名为names,往里面添加陈贤贤、大财神、飞鱼、WuYing、阿阳和Black元素。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print(names)12结果[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]2.列表文字的添加names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print('我建的学习群有', len(names), '个学生在微信群里面') print('我建的学习群有' + str(len(names)) + '个学生在微信群里面') for item in names: print(names) print('我在渡劫也加入了微信群') names.append('我在渡劫') print('现在我的微信群是', names)12345678910结果:我建的学习群有 6 个学生在微信群里面 #6的前后都有空格存在我建的学习群有6个学生在微信群里面 # 6个前后没有空格存在陈贤贤大财神飞鱼WuYing阿阳Black我在渡劫也加入了微信群现在我的微信群是 [‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’, ‘我在渡劫’]二、在列表中插入元素1.往names列表中的最后一个元素Black前面插入一个张四岁。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.insert(-1, "张四岁") print(names)123结果[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘张四岁’, ‘Black’]2.往names列表中最前面的元素陈贤贤前面插入张四岁names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.insert(0, '张四岁') print(names)123结果[‘张四岁’, ‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]3.往names列表中中间部位的元素飞鱼前面插入张四岁names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.insert(2, '张四岁') print(names)123结果[‘陈贤贤’, ‘大财神’, ‘张四岁’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]4.往names列表中大财神后面插入一个子列表[“老男孩”,“老女孩”]。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.insert(2, ["老男孩", "老女孩"]) print(names)123结果:[‘陈贤贤’, ‘大财神’, [‘老男孩’, ‘老女孩’], ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]三、改变列表中的某一个元素的名称1.把names列表中WuYing的名字改成中文。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names[names.index("WuYing")] = "吴莹" print(names)123结果:[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘吴莹’, ‘阿阳’, ‘Black’]2.把names列表中飞鱼的名字改成数字666names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names[names.index('飞鱼')] = 666 print(names)123结果:[‘陈贤贤’, ‘大财神’, 666, ‘WuYing’, ‘阿阳’, ‘Black’]3.修改特定元素names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names[3] = "吴莹" print(names)123结果:[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘吴莹’, ‘阿阳’, ‘Black’]4.批量修改元素名names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names[0:2] = 'abcd' # 将索引0-2替换为abcd,切片之后迭代处理 print(names)123结果:[‘a’, ‘b’, ‘c’, ‘d’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]四、确定列表中元素的位置(索引值)1.返回names列表中阿阳的索引值(下标)。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print(names.index("阿阳"))12结果:4五、两个列表的合并1.创建新列表numbers,依次包含1,2,3,4,2,5,6,2等数,并把新列表合并到names列表中。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] numbers = [1, 2, 3, 4, 2, 5, 6, 2] names.extend(numbers) # extend()方法表示合并 print(names)1234结果:[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’, 1, 2, 3, 4, 2, 5, 6, 2]六、取出列表中指定元素1.取出names列表中索引4-7的元素。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black", 1, 2, 3, 4, 2, 5, 6, 2] print(names[4:8])12结果:[‘阿阳’, ‘Black’, 1, 2]2.取出names列表中索引2-10的元素,步长为2。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black", 1, 2, 3, 4, 2, 5, 6, 2] print(names[2:11:2]) # 列表切片“顾头不顾尾”,步长表示在指定范围间隔取值12#结果:[‘飞鱼’, ‘阿阳’, 1, 3, 2]3.取出names列表中最后3个元素。names = ['陈贤贤', '大财神', ['老男孩', '老女孩'], '飞鱼', '吴莹', '阿阳', '张四岁', 'Black', 1, 2, 3, 4, 2, 5, 6, 2] print(names[-3:]) # [-3:]表示取值范围为从列表的倒数第三个到末尾12结果:[5, 6, 2]七、打印特定索引值和元素1.循环names列表,打印每个元素的索引值和元素。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"]1方法1for i in names: print(names.index(i), i)12方法2 enumerate()枚举for index, i in enumerate(names): print(index, i)12结果:0 陈贤贤1 大财神2 飞鱼3 WuYing4 阿阳5 Black2.循环names列表,打印每个元素的索引值和元素,当索引值为偶数时,把对应的元素改成-1。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black", 1, 2, 3, 4, 2, 5, 6, 2] for index, i in enumerate(names): if index % 2 == 0: names[index] = -1 print(index, i) print(names)123456结果:[-1, ‘大财神’, -1, ‘WuYing’, -1, ‘Black’, -1, 2, -1, 4, -1, 5, -1, 2]3.names列表里有3个2,请返回第二个2的索引值,不要人肉,要动态找。names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black", 1, 2, 3, 4, 2, 5, 6, 2]1方法1 循环count = 0 for index, i in enumerate(names): # print(index,i) if i == 2: count += 1 while count == 2: print(index) break else: continue12345678910方法2print(names.index(2, names.index(2)+1))1结果:104.现有商品列表如下:products = [["iphone", 6888], ["MacPro", 14800], ["小米6", 2499], ["Coffee", 31], ["Book", 60], ["Nike", 699]]1需打印出以下格式:------ 商品列表 ------0 iphone 68881 MacPro 148002 小米6 24993 Coffee 314 Book 605 Nike 699products = [["iphone", 6888], ["MacPro", 14800], ["小米6", 2499], ["Coffee", 31], ["Book", 60], ["Nike", 699]] print("--------- 商品列表 --------") for index, i in enumerate(products): print("%s %s %s" % (index, i[0], i[1]))1234结果:--------- 商品列表 --------0 iphone 68881 MacPro 148002 小米6 24993 Coffee 314 Book 605 Nike 6995.根据products列表写一个循环,不断询问用户想买什么,用户选择一个商品编号,就把对应的商品添加到购物车里,最终用户输入q退出时,打印购买的商品列表。products = [["iphone", 6888], ["MacPro", 14800], ["小米6", 2499], ["Coffee", 31], ["Book", 60], ["Nike", 699]] shop_car = [] # 用户购物车 shop_cost = 0 # 用户花费的金额 exit_log = False # 标志位,默认设为False,退出 while not exit_log: print("------ 商品列表 ------") for index, i in enumerate(products): print("%s %s %s" % (index, i[0], i[1])) user_choice = input("\n输入你想购买的产品序号(按“q”退出):") if user_choice.isdigit(): # 判断用户输入的是否是数字 user_choice = int(user_choice) # 强制转换为数字 if user_choice >=0 and user_choice < len(products): # 判断用户购买的商品是否在商品列表中 shop_car.append(products[user_choice]) # 加入购物车 shop_cost += products[user_choice][1] # 计算费用 print("\n %s 已经加入你的购物车\n"%products[user_choice]) else: print("抱歉,此商品不存在\n") elif user_choice == "q": # 用户选择退出 if len(shop_car) > 0: # 判断用户是否购买了商品 print("\n------ 你的购物车 ------") for index, i in enumerate(shop_car): # index和i为临时变量,与前一个for循环里index和i作用的列表不同,故可重用 print("%s %s" % (i[0], i[1])) print("\n你此次购物的花费合计是:%s元\n" % shop_cost) exit_log = True # 退出购物 else: exit_log = True # 未购买商品,不打印购物车商品,直接退出 else: # 输入不合法 exit_log = True123456789101112131415161718192021222324252627282930313233346.打印列表本身names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print(names)12结果:[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]7.依顺序打印列表中所有元素names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"]1方法一print(names[0]) print(names[1]) print(names[2]) print(names[3]) print(names[4])12345方法二for i in names: print(i)12结果:[‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]8.调取一个列表元素的方法names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print(names[3])12结果:WuYing八、统计列表中元素的个数names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] print(len(names))12结果:6九、增加列表中元素的方法:append方法score = [] print(score) score.append(80) print(score) names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.append(1705) names.append('HZH') print(names) print(names.append('HZH')) # 无返回值,names.append1234567891011结果:[][80][‘陈贤贤’, ‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’, 1705, ‘HZH’]None十、列表转换成字符串names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] a = "、".join(names) print(a)123结果:陈贤贤、大财神、飞鱼、WuYing、阿阳、Black十一、删除元素1.按照元素删除names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names.remove('飞鱼') print(names)123结果:[‘陈贤贤’, ‘大财神’, ‘WuYing’, ‘阿阳’, ‘Black’]2.按照索引删除names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names = names.pop() # 不写索引就删除最后一个之外所有其他的 print(names) ‘’‘12345结果:Blacknames = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names = names.pop(2) # 保留第3个,删除所有其他的 print(names)12345结果:飞鱼names = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] names = names.clear() # 清除列表 print(names)12345结果:Nonenames = ["陈贤贤", "大财神", "飞鱼", "WuYing", "阿阳", "Black"] for i in range(len(names)): # 一个一个地删除 print(i) del names[0] print(names)123456结果:0[‘大财神’, ‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]1[‘飞鱼’, ‘WuYing’, ‘阿阳’, ‘Black’]2[‘WuYing’, ‘阿阳’, ‘Black’]3[‘阿阳’, ‘Black’]4[‘Black’]5[
-
线程 --> 锁1、锁与GILGIL 是python 解释器全局锁2、同步锁多个线程抢占资源的情况:from threading import Thread import os,time def work(): global n temp=n time.sleep(0.1) n=temp-1 if __name__ == '__main__': n=100 l=[] for i in range(100): p=Thread(target=work) l.append(p) p.start() for p in l: p.join() print(n) #结果可能为99import threading R=threading.Lock() R.acquire() ''' 对公共数据的操作 '''同步锁的引用:from threading import Thread,Lock import os,time def work(): global n lock.acquire() temp=n time.sleep(0.1) n=temp-1 lock.release() if __name__ == '__main__': lock=Lock() n=100 l=[] for i in range(100): p=Thread(target=work) l.append(p) p.start() for p in l: p.join() print(n) #结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全互斥锁与join的区别:#不加锁:并发执行,速度快,数据不安全 from threading import current_thread,Thread,Lock import os,time def task(): global n print('%s is running' %current_thread().getName()) temp=n time.sleep(0.5) n=temp-1 if __name__ == '__main__': n=100 lock=Lock() threads=[] start_time=time.time() for i in range(100): t=Thread(target=task) threads.append(t) t.start() for t in threads: t.join() stop_time=time.time() print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:0.5216062068939209 n:99 ''' #不加锁:未加锁部分并发执行,加锁部分串行执行,速度慢,数据安全 from threading import current_thread,Thread,Lock import os,time def task(): #未加锁的代码并发运行 time.sleep(3) print('%s start to run' %current_thread().getName()) global n #加锁的代码串行运行 lock.acquire() temp=n time.sleep(0.5) n=temp-1 lock.release() if __name__ == '__main__': n=100 lock=Lock() threads=[] start_time=time.time() for i in range(100): t=Thread(target=task) threads.append(t) t.start() for t in threads: t.join() stop_time=time.time() print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 is running Thread-2 is running ...... Thread-100 is running 主:53.294203758239746 n:0 ''' #有的同学可能有疑问:既然加锁会让运行变成串行,那么我在start之后立即使用join,就不用加锁了啊,也是串行的效果啊 #没错:在start之后立刻使用jion,肯定会将100个任务的执行变成串行,毫无疑问,最终n的结果也肯定是0,是安全的,但问题是 #start后立即join:任务内的所有代码都是串行执行的,而加锁,只是加锁的部分即修改共享数据的部分是串行的 #单从保证数据安全方面,二者都可以实现,但很明显是加锁的效率更高. from threading import current_thread,Thread,Lock import os,time def task(): time.sleep(3) print('%s start to run' %current_thread().getName()) global n temp=n time.sleep(0.5) n=temp-1 if __name__ == '__main__': n=100 lock=Lock() start_time=time.time() for i in range(100): t=Thread(target=task) t.start() t.join() stop_time=time.time() print('主:%s n:%s' %(stop_time-start_time,n)) ''' Thread-1 start to run Thread-2 start to run ...... Thread-100 start to run 主:350.6937336921692 n:0 #耗时是多么的恐怖 '''3、死锁与递归锁进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁死锁:from threading import Lock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:递归锁:from threading import RLock as Lock import time mutexA=Lock() mutexA.acquire() mutexA.acquire() print(123) mutexA.release() mutexA.release()典型问题:科学家吃面死锁问题:import time from threading import Thread,Lock noodle_lock = Lock() fork_lock = Lock() def eat1(name): noodle_lock.acquire() print('%s 抢到了面条'%name) fork_lock.acquire() print('%s 抢到了叉子'%name) print('%s 吃面'%name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print('%s 抢到了叉子' % name) time.sleep(1) noodle_lock.acquire() print('%s 抢到了面条' % name) print('%s 吃面' % name) noodle_lock.release() fork_lock.release() for name in ['哪吒','egon','yuan']: t1 = Thread(target=eat1,args=(name,)) t2 = Thread(target=eat2,args=(name,)) t1.start() t2.start()递归锁解决死锁问题:import time from threading import Thread,RLock fork_lock = noodle_lock = RLock() def eat1(name): noodle_lock.acquire() print('%s 抢到了面条'%name) fork_lock.acquire() print('%s 抢到了叉子'%name) print('%s 吃面'%name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print('%s 抢到了叉子' % name) time.sleep(1) noodle_lock.acquire() print('%s 抢到了面条' % name) print('%s 吃面' % name) noodle_lock.release() fork_lock.release() for name in ['哪吒','egon','yuan']: t1 = Thread(target=eat1,args=(name,)) t2 = Thread(target=eat2,args=(name,)) t1.start() t2.start()
-
-
一个玩得好的朋友突然大晚上的给我布置作业,吓得我精神抖擞。他的原话是:感觉发现新大陆了,利用小海龟画的,上次玩海龟已经是几个月之前的事情了https://blog.csdn.net/hanhanwanghaha/article/details/106211876话不多说,上代码!动态时钟from turtle import *from datetime import *# 移动到指定位置def skip(step): penup() forward(step) pendown()# 画指针def drawpointer(name, length): reset() skip(-length * 0.1) begin_poly() forward(length * 1.1) end_poly() handForm = get_poly() register_shape(name, handForm)# 初始化def init(): global hrpointer, minpointer, secpointer, weektext # 设置turtle Logo模式,朝北 mode("logo") drawpointer("hrpointer", 90) drawpointer("minpointer", 130) drawpointer("secpointer", 140) hrpointer = Turtle() hrpointer.shape("hrpointer") minpointer = Turtle() minpointer.shape("minpointer") secpointer = Turtle() secpointer.shape("secpointer") secpointer.pencolor("red") for pointer in hrpointer, minpointer, secpointer: pointer.shapesize(3, 1, 1) pointer.speed(0) # 文字输出 weektext = Turtle() weektext.hideturtle() weektext.penup()# 设置表盘形状def setupClock(radius): #绘制表的外框 reset() # clockPanel = Turtle() pensize(7) pencolor("blue") for i in range(60): skip(radius) if i % 5 == 0: forward(20)#画长刻度线 skip(-radius - 20)#回到中心点 else: dot(5) skip(-radius) right(6)# 星期文本def Week(t): week = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] return week[t.weekday()]# 日期文本def Date(t): y = t.year m = t.month d = t.day return "%s %d %d" % (y, m, d)# 绘制表针动态显示def tick(): t = datetime.today() second = t.second + t.microsecond * 0.0000001 minute = t.minute + second / 60.0 hour = t.hour + minute / 60.0 secpointer.setheading(6 * second) minpointer.setheading(6 * minute) hrpointer.setheading(30 * hour) tracer(False) weektext.forward(65) weektext.write(Week(t), align="center", font=("Courier", 14, "bold")) weektext.back(130) weektext.write(Date(t), align="center", font=("Courier", 14, "bold")) weektext.home() tracer(True) # 间隔100ms调用一次 ontimer(tick, 100)def main(): #打开/关闭海龟画,并为更新图纸设置延迟 tracer(False) init() setupClock(160) tracer(True) tick() mainloop()if __name__ == '__main__': main()代码借鉴(部分添加修改):https://www.jb51.net/article/151049.htm算出某月星期几的所有日期from datetime import date, timedelta, datetimeimport calendar# 输入想要获取的年月份cal = calendar.month(2020, 9)print(cal)m = datetime.now().month y = datetime.now().year ndays = (date(y, m + 1, 1) - date(y, m, 1)).days day_one = date(y, m, 1)last_day = date(y, m, ndays)delta = last_day - day_one data_list = []for i in range(delta.days + 1): p = (day_one + timedelta(days=i)).strftime('%Y-%m-%d') pp = datetime.strptime(str(p), '%Y-%m-%d') one = pp.isoweekday() print(type(one), one) if one == 1: #此处的1为星期一 d2 = pp.strftime('%Y-%m-%d') data_list.append(d2)print("2020年9月份所有的星期一的日期为", data_list)#实时获取当前时间 转换为str字符串now = datetime.now()print('当前时间为 :', now)1234567891011121314151617181920212223242526272829运行结果
-
前言 本篇章主要介绍哈夫曼树及哈夫曼编码,包括哈夫曼树的一些基本概念、构造、代码实现以及哈夫曼编码,并用Python实现。1. 基本概念 哈夫曼树(Huffman(Huffman(Huffman Tree)Tree)Tree),又称为最优二叉树,指的是带权路径长度最小的二叉树。树的带权路径常记作:WPL=∑nk=1wklkWPL=\sum _{k=1} ^ {n} w_kl_kWPL=k=1∑nwklk 其中,nnn为树中叶子结点的数目,wkw_kwk为第kkk个叶子结点的权值,lkl_klk为第kkk个叶子结点与根结点的路径长度。 带权路径长度是带权结点和根结点之间的路径长度与该结点的权值的乘积。有关带权结点、路径长度的概念请参阅这篇博客。 对于含有nnn个叶子结点的哈夫曼树,其共有2n−12n-12n−1个结点。因为在构造哈夫曼树的过程中,每次都是以两颗二叉树为子树创建一棵新的二叉树,因此哈夫曼树中不存在度为1的结点,即n1=0n_1=0n1=0,由二叉树的性质可知,叶子结点数目n0=n2+1n_0=n_2+1n0=n2+1,所以n2=n0−1n_2=n_0-1n2=n0−1,总结点数目为n=n0+n1+n2=n+n−1=2n−1n=n_0+n_1+n_2=n+n-1=2n-1n=n0+n1+n2=n+n−1=2n−1。2. 构造过程及实现 给定nnn棵仅含根结点的二叉树T1,T2,…,TnT_1,T_2,\dots,T_nT1,T2,…,Tn,它们的权值分别为w1,w2,…,wnw_1,w_2,\dots,w_nw1,w2,…,wn,将它们放入到一个集合FFF中,即F={T1,T2,…,Tn}F=\{T_1,T_2,\dots,T_n\}F={T1,T2,…,Tn};然后在集合FFF中选取两棵权值最小的根结点构造一棵新的二叉树,使新二叉树的根结点的权值等于其左、右子树根结点的权值之和;再然后将选中的那两个结点从集合FFF中删除,将新的二叉树添加到FFF中;继续重复上述操作,直至集合FFF中只剩一棵二叉树为止。 比如F={(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)}F=\{(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)\}F={(A,3),(B,7),(C,2),(D,11),(E,13),(F,15),(G,9)},它构造出来的哈夫曼树就是下面这棵二叉树: 代码实现:class HuffmanTreeNode(object): def __init__(self): self.data = '#' self.weight = -1 self.parent = None self.lchild = None self.rchild = Noneclass HuffmanTree(object): def __init__(self, data_list): self.nodes = [] # 按权重从大到小进行排列 for val in data_list: newnode = HuffmanTreeNode() newnode.data = val[0] newnode.weight = val[1] self.nodes.append(newnode) self.nodes = sorted(self.nodes, key=lambda node: node.weight, reverse=True) print([(node.data, node.weight) for node in self.nodes]) def CreateHuffmanTree(self): # 这里注意区分 # TreeNode = self.nodes[:] 变量TreeNode, 这个相当于深拷贝, TreeNode变化不影响nodes # TreeNode = self.nodes 指针TreeNode与nodes共享一个地址, 相当于浅拷贝, TreeNode变化会影响nodes TreeNode = self.nodes[:] if len(TreeNode) > 0: while len(TreeNode) > 1: letfTreeNode = TreeNode.pop() rightTreeNode = TreeNode.pop() newNode = HuffmanTreeNode() newNode.lchild = letfTreeNode newNode.rchild = rightTreeNode newNode.weight = letfTreeNode.weight + rightTreeNode.weight letfTreeNode.parent = newNode rightTreeNode.parent = newNode self.InsertTreeNode(TreeNode, newNode) return TreeNode[0] def InsertTreeNode(self, TreeNode, newNode): length = len(TreeNode) if length > 0: temp = length - 1 while temp >= 0: if newNode.weight < TreeNode[temp].weight: TreeNode.insert(temp+1, newNode) return True temp -= 1 TreeNode.insert(0, newNode)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748493. 哈夫曼编码 在数据通信时,假如我们要发送“ABCDEFG”“ABCDEFG”“ABCDEFG”这一串信息,我们并不会直接以这种形式进行发送,而是将其编码成计算机能够识别的二进制形式。根据编码类型可将其分为固定长度编码和可变长度编码,顾名思义,固定长度编码就是编码后的字符长度都相同,可变长度编码就是编码后的字符长度不相同。这两种类型有什么区别呢?我们来举例说明一下: AAABBBCCCDDDEEEFFFGGG固定长度编码000000000001001001010010010011011011100100100101101101110110110可变长度编码000111010101101010111111101101101110110110 “ABCDEFG”“ABCDEFG”“ABCDEFG”这条信息使用固定长度编码后的长度为21,使用可变长度编码后的长度为14,报文变短,报文的传输效率会相应的提高。但如果传送的字符为“BD”“BD”“BD”,按可变长度编码后的报文为“111”“111”“111”,但是在译码是就会出现“BBB”,“BD”,“DB”“BBB”,“BD”,“DB”“BBB”,“BD”,“DB”多种结果,因此采用可变长度编码时需要注意任一字符不能是其他字符的前缀,符合这样的可变长度编码称为前缀编码。 报文最短可以引申到二叉树路径最短,即构造前缀编码的实质就是构造一棵哈夫曼树,通过这种形式获得的二进制编码称为哈夫曼编码。这里的权值就是报文中字符出现的概率,出现概率越高的字符我们用越短的字符表示。 以下表中的字符及其出现的概率为例来实现哈夫曼编码:字符AAABBBCCCDDDEEEFFFGGGHHH出现概率0.010.010.010.430.430.430.150.150.150.020.020.020.030.030.030.210.210.210.070.070.070.08哈夫曼编码101010101010101010000110110110101011101011101011101001010010100111111111101110111011100 代码实现就是在哈夫曼树的基础上加一个编码的函数: def HuffmanEncode(self, Root): TreeNode = self.nodes[:] code_result = [] for index in range(len(TreeNode)): temp = TreeNode[index] code_leaf = [temp.data] code = '' while temp is not Root: if temp.parent.lchild is temp: # 左分支 code = '0' + code else: # 右分支 code = '1' + code temp = temp.parent code_leaf.append(code) code_result.append(code_leaf) return code_result123456789101112131415161718 测试结果如下:if __name__ == '__main__': tree_obj = HuffmanTree([('A', 0.01), ('B', 0.43), ('C', 0.15), ('D', 0.02), ('E', 0.03), ('F', 0.21), ('G', 0.07), ('H', 0.08)]) huf_tree = tree_obj.CreateHuffmanTree() huf_code = tree_obj.HuffmanEncode(huf_tree) for index in range(len(huf_code)): print('{0}: {1}'.format(huf_code[index][0], huf_code[index][1]))123456
-
面向对象的三大特征:封装、继承、多态封装概念:将一个对象的数据隐藏在对象内部,不让在外界直接访问,而是通过对象提供的方法来访问这些隐藏起来的数据,这样就可以在访问方法中添加访问条件限制,目的是对数据的有效组织和数据安全性的保护通俗理解:就是一个东西是自己的,不让外人直接拿到,而是通过向自己借东西的行为来判断是否可以借给他人属性私有化封装约定私有化:加一个下划线在规范上约定不能直接访问语法私有化:加两个下划线在语法上不能通过属性名称直接访问属性私有化是python层面的操作,底层解释器在解释时将两个下划线开头的属性进行了自动转换变成了_类名__属性名的形式,原来的属性名已经不存在了,所以不能直接访问,但是可以通过转换后的语法来访问,但是不推荐私有化属性数据有两个用途:第一可以用在当前类型中的业务流程中,如对象的一个临时计数属性等第二可以使用类型提供的访问私有化属性方法来获取数据参与类外部的运算属性访问方法属性私有化之后,只能在当前类内部访问,为了数据的可用性,一般会提供私有访问属性的操作方法固定语法格式:访问格式修改格式总结:封装,将对象的数据隐藏在内部,不让外界直接访问,而是通过提供的属性访问set/get方法完成数据的访问和赋值,在set/get方法中添加访问条件限制,完成私有数据的保护继承继承主要体现了基于类的代码复用性,通过继承关系关联两个类有了继承关系,在子类中可以使用父类中的公共属性和方法,复用了父类的代码基本语法:class Father: 父类class Son(Father): 子类1234在子类中可以在父类的基础上扩展方法扩展属性:调用父类的初始化方法{子类中编写初始化方法,父类的方法不会直接调用,必须手动调用}def__init__(self,name,age,gender,level) # 初始化父类方法 super().__init__(name,age,gender)123继承关系中,子类也可以通过__bases__属性查看当前类型继承的父类信息方法的覆盖:在继承中,子类中可以重新编写父类中相同名称的属性或者方法,方法的重新编写称为方法的覆盖(子类的方法覆盖了父类同名的方法)或者方法重写(子类重写了父类继承过来的方法)多继承多继承模式下继承顺序,使用了广度优先的查询原则python提供了mro()方法用于确认继承关系中属性和方法的查询操作顺序在子类中使用suoer() 指向的是mro当中的顺序class A: def func0(self): print("我是父类A")class B: def func1(self): print("我是父类B")class C(A,B): def func2(self): self.func0() self.func1() 12345678910多态一个对象的多种状态,多态只是一种表现形式,没有固定格式,体现的是程序运行过程中的状态改变和行为的多样性 可以通过继承关系来完成角色的关系互换 可以通过继承中的方法重写,完成行为方法的切换 可以通过代码结构的设计,完成行为的多样性123拓展__str__与__repr__方法这两个方法都是打印对象的方法其两者的区别在于:str方法是直接打印对象时调用的该方法repr方法是在其他对象中(如列表、元组)中打印时调用例:class User: def __init__(self, name, age, nickname): self.name = name self.age = age self.nickname = nickname # __str__() # 当我们打印对象时自动执行 def __str__(self): """在打印对象时自动调用str放法""" return f"< User user({self.name},{self.age},{self.nickname})>" # repr 当对象在其他对象中 打印时 def __repr__(self): """当对象在其他对象中(列表,元组) 打印时调用的是repr方法""" return f"< User user({self.name},{self.age},{self.nickname})>"# 实例化对象xw = User('小王',18,'小王吧')# 这里调用的是__str__方法print(xw) # <__main__.User object at 0x0000000002662888># 这里调用的是__repr__方法lis = (xw,)print(lis)
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签