基类、扩展类──页面重构中的模块化设计(五) 由 Ghostzhang 发表于 2010-06-11 19:24 基类 和 扩展类 是这个系列的主要内容,上一篇《 模块化的核心思想──页面重构中的模块化设计...也就是说,当出现多个类似的模块时,基类包含了这些模块的大部分的效果(或者理解为公共的部分),在基类的基础上,我们可以通过添加很少的代码——扩展类,来达到所需要要效果。...……5分钟过去了……差不多有方案了,按上面的思路,基类是包含了大部分的效果的,也就是说基类应该能满足大部分效果的需要,两个模块间差异的地方,可以通过扩展类来完成。...所以我们可以把这两个模块看成的类似模块。另个,以哪个为基类呢?从满足大部分效果这个要求来看,很明显A模块做为基类是要比B模块做为基类更合适的,如果用B模块做基类,那么需要写更多的扩展类来满足A的需要。...效果展示 例子中可以看到,扩展类的定义很少,只是一些简单的定义,像B模块: /* S 消息 扩展 */ .message_nopic{padding-left:0;} /* E 消息 扩展 */ 只需要一句
undefined 引言 前面已经对市场上一些比较热门的性能测试工具进行了对比,这里主要介绍Locust性能测试框架的使用,如果你喜欢编码,学习Python自动化测试的时候,同时又能学习一款性能测试工具...————官方文档:https://locust.io 简单来说: 1、支持分布式; 2、纯python脚本,易上手; 3、扩展性高; 4、单机支持高并发数; 5、WebUI可视化监控...msgpack 是一种快速、紧凑的二进制序列化格式,适用于类似Json的数据。 pyzmq 可用于Locust分布运行在多个进程/机器上。 ...Locust 需要自己编写 python 脚本,压测负载脚本主要包含两个子类UserTask和WebsiteUser,一个用户行为类,用于定义用户的具体行为,一个设置用户性能测试类。...Locust类其实好比一群蝗虫,每个蝗虫就是一个Locust类的实例,而TaskSet类就是蝗虫的大脑,控制着蝗虫的行为。也就是我们测试中实际场景中的任务集合。
启动负载测试时,派生的Locust类的每个实例将开始执行其TaskSet。接下来的情况是每个TaskSet将选择一个任务并调用它。...该类在实例化时创建一个client属性,该属性是一个HTTP client ,支持在请求之间保持用户会话。 client= None 在Locust实例化后创建的HttpSession实例。...的测试,你应该知道一个名为 ApiUser 的类,它是一个普通的 Locust 类,它的 task_set属性是一个 TaskSet 类的子类,而这个子类带有多个 task。...locust= None 当TaskSet实例化后,会引用根Locust类实例。 parent= None 实例化TaskSet时,将引用父TaskSet或Locust类实例。...其中参数 exc 可以是一个Python的异常类或者一个字符串。如果是一个字符串,那么将使用这个字符串来实例化 CatchResponseError 类。
User类 User类表示性能测试的模拟用户,Locust会在运行时创建User类的实例。 wait_time属性 设置等待时间,默认值不等待,立即执行。...Locust支持4种方式设置wait_time属性。 为了便于理解实际意义,我把源码贴在了下面。 weight属性 设置创建类实例的权重,默认每个类创建相同数量的实例。...WebUser类比MobileUser类多三倍概率创建实例。 host属性 设置URL前缀。 一般是在Locust的Web UI或者命令行,通过--host指定URL前缀。...on_start和on_stop方法 测试前初始化和测试后清理。 HttpUser类 开篇文章的示例脚本,没有继承User类,而是继承了它的子类HttpUser: ?...client属性/HttpSession HttpUser类的client属性是HttpSession类的一个实例: ?
,是我们应该思考的问题,本文旨在对locust的特性以及实现进行梳理,方便并对qload以及jmeter进行一个简单的横向对比。...请求的“用户”,继承于User类,这个类在实例时会创建一个client,用于在请求之间保持用户会话; HttpSession:为HttpUser的实例提供client,继承于requests.Session...4.3.2 控制模块 [locust/runners.py] Runner:通过启停和编排“用户”来进行压测,是DistributedRunner的基类; DistributedRunner:和Runner.../rpc] BaseSocket:socket基类,封装了zeromq,提供了1:N特性,每个master与salve之间各维持一个tcp连接,提供master命令下发和salve信息上报能力; Server...:继承BaseSocket,作为压测系统的Server端; Clint:继承BaseSocket,作为压测系统的Client端; Message:消息的封装,序列化与反序列化,数据是通过WorkerRunner
在解析-f参数成功之后(没有指定-f参数则不会启动成功),会去自动的导入该脚本模块;再通过python的自省能力来检查脚本中的VUser类,主要检查继承自Locust且带有task_set属性的子类;一个子类相当于一个...然后新起一个协程来实例化它,实例之后调用它的run方法开始执行该VUser的任务内容,直到所有VUser都实例化完成。...与此同时还会实例化真正的请求客户端,以便于在后面直接可以用来发送请求,而默认Locust发送请求的客户端其实就是requests。...self.client = HttpSession(base_url=self.host) # 实例化发送请求的client 这些准备工作都完成之后,就开始实例化task_set变量对应的类,也就是样例代码中的...WebsiteTasks类(TaskSet的子类);接着会调用TaskSet实例的run方法来执行所有的任务。
简介 Locust是什么? Locust是一个简单易用的分布式用户负载测试工具。它用于web站点(或其他系统)的负载测试,并计算一个系统可以处理多少并发用户。...每个聚集站点上的蝗虫实际上是在它自己的进程中运行的(正确的说是greenlet)。这允许你使用Python编写非常有表现力的场景,而不用回调使代码复杂化。...任务,它们是普通的Python可调用函数,带有一个参数(一个Locust类实例)。...TaskSet类可以嵌套。 HttpLocust类继承自Locust类,并且添加了一个client属性,该属性是HttpSession的实例,可用于发出HTTP请求。...类(以及HttpLocust,因为它是一个子类)还允许您指定任务执行之间的等待时间(wait_time = between(5, 9))以及其他用户行为。
小结 直接子类化内置类型容易出错,因为内置类型的方法通常会忽略用户覆盖的方法。 不要子类化内置类型,用户自己定义的类应该继承collectiions模块中的类。...) ⚠️直接在类上调用实例方法,必须显式传入self参数,因为这样访问的是未绑定方法 处理多重继承的建议 把接口继承和实现继承区分开 创建子类的原因: 继承接口,创建子类型,实现「是什么」关系 继承实现...继承重用代码是实现细节,通常可以换用组合和委托模式 使用抽象基类显式表示接口 创建abc.ABC或其他抽象基类的子类 通过混入重用代码 混入类绝对不能实例化,而且具体类不能只继承混入类。...抽象基类中实现的方法只能与抽象基类及其超类中的方法协作。这表明,抽象基类中的具体方法只是一种便利措施,因为这些方法所做的一切,用户调用抽象基类中的其他方法也能做到。...不要子类化多个具体类 具体类的超类中除了这一个具体超类之外,其余的都是抽象基类或者混入。
智造喵GPT地址: https://chat.plexpt.com/i/511440这里给你提供一个简单的Python+Locust压力测试框架,你可以根据自己的需求来进行修改和扩展。...在脚本中,导入需要的模块和库,例如:```pythonfrom locust import HttpUser, task, between```图片然后,定义一个Locust框架的类,例如:```pythonclass...这个任务可以根据具体的需求进行扩展和修改。...最后,在脚本中实例化Locust框架,并定义一些基本的配置,例如:```pythonif __name__ == '__main__': LocustFramework.host = "http:...现在,你可以在终端中运行这个脚本,并访问`http://localhost:8089`来打开Locust的Web界面,从而对测试任务进行配置和启动。
Locust类 一个Locust类代表一个用户(或者一个集群Locust)。Locust将为每个正在模拟的用户生成(孵化)一个Locust类实例。Locust类通常应该定义一些属性。...启动负载测试时,派生的Locust类的每个实例将开始执行其TaskSet。接下来的情况是每个TaskSet将选择一个任务并调用它。...setup是在任务开始运行之前运行,而teardown是在所有任务完成并退出Locust之后运行的。...HttpLocust类 表示一个HTTP“用户”,该“用户”将被孵化并攻击要加载测试的系统。 此用户的行为由task_set属性定义,该属性应指向TaskSet类。...该类在实例化时创建一个client属性,该属性是一个HTTP client ,支持在请求之间保持用户会话。 client= None 在Locust实例化后创建的HttpSession实例。
Tasks 从上篇文章知道,locustfile里面必须要有一个类,继承User类,当性能测试开始后,会产生一个User类实例,这就是常说的模拟用户。...pass class MyUser(User): tasks = [my_task] wait_time = constant(1) 注意,my_task()函数有一个参数,它是User类的实例...requirements.txt FastHttpUser 从上篇文章可以知道,HttpUser类比User类更常用,它的client属性是HttpSession类(requests.Session子类...)的一个实例,可以使用requests发HTTP请求: # 使用HttpUser from locust import HttpUser,task,constant class MyUser(User...小结 本文严格来说是上篇文章《locustfile中的User类和HttpUser类》的下篇,介绍了核心技术Tasks和Events,并给出了官方推荐的项目结构,最后介绍了比HttpUser性能更好的FastHttpUser
base关键字 base 关键字用于在派生类中实现对基类公有或者受保护成员的访问,但是只局限在构造函数、实例方法和实例属性访问器中: 调用基类上已被其他方法重写的方法。...如果使 用 new 显式隐藏成员,则会取消此警告,并记录要替换为派生版本这一事实。 ? 在子类中用 new 关键字修饰 定义的与父类中同名的方法,叫覆盖。 覆盖不会改变父类方法的功能。...abstract关键字 针对abstract关键字暂时总结了以下五点: 1.用关键字abstract定义的类即为抽象类,且只能作为基类,也不能被实例化。...virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。...static字段和static构造函数 主要来说明执行的顺序: 1、编译器在编译的时候,先分析所需要的静态字段,如果这些静态字段所在的类有静态的构造函数,那么就会忽略字段的初始化;如果没有静态的构造函数
一实一具体表方案适合需要较高查询性能,继承体系层次不太复杂,并且基类包含较少的属性而子类扩展较多属性,并且能够承受一定的数据库空间浪费的情况。 ...一实体一扩展表 所谓一实体一扩展表是指继承体系中的每个实体对应一张数据表,但是,每个子类不冗余包含父类的所有属性,而只是包含扩展的属性和共享的主键值。...一实体一扩展表方案适合继承体系非常复杂,结构易变,并希望最大程度减少数据冗余的情形。 ...分析其原因,是因为,它就和我们在OO中定义继承体系中的类一样,子类只需定义扩展的部分,无需重复包含父类已经定义的属性。 OK,那么,和基类继承映射相比,接口处在一个什么地位呢?...尽管子类继承一个接口(一个抽象基类),但是,每个实现接口的子类实际上重复包含了接口中定义的字段属性,区别是,此时因为基类是接口,不需要持久化,因此,不会有一实体一具体表那样的的数据冗余。
子类只能通过新添加方法来扩展功能,父类和子类都可以实例化,而子类继承的方法和父类是一样的,父类调用方法的地方,子类也可以调用同一个继承得来的,逻辑和父类一致的方法,这时用子类对象将父类对象替换掉时,当然逻辑一致...如果继承的目的是为了多态,而多态的前提就是子类覆盖并重新定义父类的方法,为了符合LSP,我们应该将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,当父类是抽象类时,父类就是不能实例化,所以也不存在可实例化的父类对象在程序里...也就不存在子类替换父类实例(根本不存在父类实例了)时逻辑不一致的可能。...不符合LSP的最常见的情况是,父类和子类都是可实例化的非抽象类,且父类的方法被子类重新定义,这一类的实现继承会造成父类和子类间的强耦合,也就是实际上并不相关的属性和方法牵强附会在一起,不利于程序扩展和维护...总结一句话 —— 就是尽量不要从可实例化的父类中继承,而是要使用基于抽象类和接口的继承。 说的很透彻了。说白了,就是大家都基于抽象去编程,而不要基于具体。
即,需要使用基类类型的指针或引用来指向子类对象,并通过该指针或引用来调用虚函数。 原理:在运行时,程序会根据指针或引用所指向对象的实际类型,在虚函数表中查找并调用相应的函数版本。...由于至少含有一个纯虚函数,抽象类不能被实例化(即不能直接创建该类的对象)。抽象类的主要用途是作为一个基类,为派生类提供一个公共的接口。...注意:一个类即使不包含纯虚函数,只要它的构造函数被声明为protected或private,它也被视为抽象类,因为这样的类不能被直接实例化。...,它不能被实例化,但可以作为基类供其他类继承。...通过基类类型的指针或引用来调用虚函数时,会根据实际的对象类型来调用相应的函数。 抽象类:定义一个只包含纯虚函数的类作为抽象基类,派生类必须实现这些纯虚函数才能被实例化。
类是对象的模板,它定义了对象具有的属性(成员变量)和方法(成员函数)。对象是类的实例化,每个对象都具有类定义的属性和方法。 封装:封装是将数据和方法打包在一个对象中,并对外部隐藏对象内部的细节。...抽象类与接口:抽象类是一种不能被实例化的类,它可以包含抽象方法,需要子类实现。接口是一种纯抽象类,定义了一组方法的签名,需要实现这些方法的具体细节。...3.LSP(里氏替换原则) 子类型必须完全实现基类的接口:子类型应该继承或实现基类的所有属性和方法,以确保能够无缝地替换基类的实例。...子类型不应该删除基类的属性或方法,也不应该引入与基类不兼容的新属性或方法。 子类型可以扩展基类的功能:虽然子类型必须保持对基类的兼容性,但它们可以添加额外的功能或修改基类的实现。...LSP的目标是确保在使用多态性时,代码可以安全地替换基类的实例为子类的实例,而不会引发错误或破坏程序的正确性。
patient1 = Patient("李明",24,"男") #父类Hospital实例化 hospital = Hospital("无锡市人民医院","江苏省无锡市人民大道","三甲") #子类实例调用...这个算法实际上就是合并所有父类的,MRO列表并遵循如下三条准则: ① 子类会由于父类被检查; ② 多个父类会根据他们在列表中的顺序被检查; ③ 如果对于下一个类存在两个合法的选择,应选择第一个父类; 为此我们可以直接使用子类的...4.接口继承 从上面例子中我们可以看出,类的继承有2种含义,一是:子类继承基类的方法,并作出自己的扩展或改变(基类代码的重用);二是:声明某个子类兼容于某基类,父类定义一个接口类,子类继承接口类,并且实现接口类中定义的方法...则开始实例化就会报错。...实际上基类不用进行实例化操作,因为它完全没有意义。
2.继承:代码复用 继承有这样一种能力,就是能使用现有的类的所有功能,并无须重新编写原来的这些类的基础上对这些功能进行扩展。通过继承创建的新类称为子类或派生类,被继承的称为基类。...实现继承可以直接使用基类的属性和方法而无需额外编码,接口继承是指使用属性和方法的名称,但是子必须提供实现的能力。...简化性 多态存在的三个必要条件 继承 重写 父类引用指向子类对象(父类的类型,用子类实例化) 比如: Parent p = new Child(); 当使用多态方式调用方法时,首先检查父类中是否有该方法...多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。...方式三:抽象类和抽象方法 对于多态,可以总结以下几点: 一、使用父类类型的引用指向子类的对象; 二、该引用只能调用父类中定义的方法和变量; 三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候
领取专属 10元无门槛券
手把手带您无忧上云