• 接口测试学习-python第八课(面向对象第二课)


    一、重写父类的方法

    重写包含两种定义,其一是父类的方法不可用了,需要完全重新编写;其二是保留父类方法的同时新增一些功能。

    首先是全部重写,很好理解,就是将整个方法都修改掉。比如下面的类Zll中,定义了一个smile方法,笑的方式是“哈哈哈”。而继承Zll的子类Dcg,笑的方式并不是这个,那么他就重写smile方法。

    1 class Zll(object):
    2     def smile(self):
    3         print('哈哈哈')
    4 
    5 
    6 class Dcg(object):
    7     def smile(self):
    8         print('嘿嘿嘿')

    其次是修改父类方法。就是在保留父类方法的基础上进行添加或者部分修改。如果父类只有一个,那么直接在方法中调用父类方法即可。比如:

    1 class Lw(object):
    2     def smile(self):
    3         Zll.smile()
    4         print('啊啊啊啊')

    但当子类继承了多个父类时,像这样去调用就非常麻烦了,因为还要分辨这个方法属于哪一个父类。这时候可以用super()方法自动查找父类。当有多个父类时,super()会默认从第一个父类开始查找。

    1 class Xz(Zll, Dcg, Lw):
    2     def smile(self):
    3         # Zll().smile()  # 先调用父类的方法,这样可以使用父类的功能
    4         super(Xz, self).smile()  # 可以帮助子类自动找到其父类
    5         # 如果子类继承自多个父类,super自动从第一个开始寻找smile方法
    6         print('呵呵呵呵')  # 重写了父类的方法

    二、经典类和新式类

    经典类和新式类的区别主要有以下两点:

    1、定义时有所不同

    1 class A(object):  # 新式类
    2     pass
    3 
    4 
    5 class A1():  # 经典类
    6     pass

    2、多重继承时,查找方法的方式不同

    在python2中,经典类的查找方式是深度查找,新式类的查找方式是广度查找。到python3默认所有的类都是新式类,所以都默认为广度查找了。如下面代码中,实例化对象d使用方法smile时,因为其类D继承自C,B,A,都是新式类,所以D也是新式类,其查找smile的方法是广度优先也就是C->B->A的顺序查找的。而d1是D1类的实例化对象,D1继承自C1,B1和A1都是经典类,所以D1也是经典类,d1.smile()时查找方法是深度优先也就是C1->A1->B1。

     1 class A(object):
     2     pass
     3 class A1():
     4     pass
     5 
     6 class B(A):
     7     pass
     8 class B1(A1):
     9     pass
    10 
    11 class C(A):
    12     def smile(self):
    13         print('哈哈')
    14 class C1(A1)
    15     def smile(self):
    16         print('haha')
    17 
    18 class D(C,B,A):
    19     pass
    20 class D1(C1,B1,A1):
    21     pass
    22 
    23 d = D()
    24 d.smile()
    25 d1 = D1()
    26 d1.smile

    三,多线程和多进程

    一个进程可以有多个线程,进程是资源的合集,线程是进程中的最小执行单元。用很简单的方式来展示一下串行和并行。并行就是实例化线程,然后一起start开始干活。

     1 import threading
     2 import time
     3 
     4 
     5 def run():
     6     time.sleep(3)  # 做一件事需要三秒
     7     print('哈哈哈')
     8 
     9 for i in range(5):  # 串行,一个人干完另一个人再干活
    10     run()
    11 
    12 for i in range(5):  # 并行
    13     t = threading.Thread(target=run)  # 实例化一个线程
    14     t.start()

    如果我们要比较串行和并行的执行时间,串行的可以直接在程序开始时记录当前时间,结束后记录当前时间,然后相减即可。但是并行不行,因为并行记录的是主线程的时间,其实子线程还在运行中,直接这样记录是不准确的。我们可以用下面的方法,记录每次子线程,然后让主线程等待一下子线程

     1 def run():
     2     time.sleep(3)  # 做一件事需要三秒
     3     print('哈哈哈')
     4 start_time = time.time()
     5 threads = []
     6 for i in range(5):
     7     t = threading.Thread(target=run)
     8     t.start()
     9     threads.append(t)
    10     # t.join()  # 这个就是主线程等待子线程执行结束,但是直接这样是不行的因为每次t里面都是不同的线程
    11 #     这样就变成了串行了,一个干完等待,继续下一个,然后等待
    12 for t in threads:  # 主线程先运行了run()然后就继续往下走了,然后启动了子线程,所以此时主线程就已经在等待中了
    13     t.join()  # 这样就是每个线程都等待一下
    14 end_time = time.time()
    15 run_time = end_time-start_time
    16 print('执行总共花了时间%s' % run_time)

    四、线程锁

    当所有的线程都在修改同一个数据时,可能出现覆盖的情况,比如一个数不断加1,因为后面的结果数覆盖了前面的数据,导致结果不正确。这个时候就要对这个变量加一个线程锁,让它在正在被修改的时候不会被其他任务修改。其实python3是会自动加锁的,但是我们也需要学习一下这个概念和方法,必须使用python2编程时就要用到了。

     1 import threading, time
     2 num = 1
     3 lock = threading.Lock()  # 申请一把锁
     4 
     5 def run():
     6     time.sleep(1)
     7     global num
     8     lock.acquire()  # 加上锁,其实python3是会默认加锁的
     9     num += 1
    10     lock.release()  # 解锁
    11 ts = []
    12 for i in range(50):
    13     t = threading.Thread(target=run)
    14     t.start()
    15     ts.append(t)
    16 [t.join() for t in ts]  # 如果不等待,主线程跑太快,上面那个time.sleep()会导致num=1就执行完了
    17 print(num)

    五、守护线程

    只要主线程结束,立刻结束其他子线程。不论子线程是否运行成功。

     1 import threading,time
     2 def run():
     3     time.sleep(3)  # 做一件事需要三秒
     4     print('哈哈哈')
     5 
     6 for i in range(5):
     7     t = threading.Thread(target=run)
     8     t.setDaemon(True)  # 把子线程设置为守护线程
     9     t.start()
    10 
    11 print('Done,运行完成。')
    12 time.sleep(3)  # 等三秒是可以运行下一个子线程的,但是等1秒的话来不及走子线程主线程就结束了

    六、多进程

    多进程用于处理CPU密集型任务。多线程用于处理IO密集型任务。其实python是无法使用多核的,原因如下:

     1 import multiprocessing,threading
     2 
     3 def my():
     4     print('哈哈哈')
     5 
     6 
     7 def run(num):
     8     for i in range(num):
     9         t = threading.Thread(target=my)
    10         t.start()
    11 if __name__ == '__main__':
    12     for i in range(5):
    13         p = multiprocessing.Process(target=run, args=(6,))  # 启动五个进程,每个进程6个线程
    14         # 这样就可以利用CPU的多核
    15         p.start()
  • 相关阅读:
    Oracle导出导入表空间创建
    ASP.NET 缓存 SqlCacheDependency 监视数据库表变化 让缓存更新的更及时更提高节能
    Silverlight在添加WCF服务引用时报错
    springboot中如何动态更换 配置文件 spring.profiles.active
    maven之根据profile动态切换resource
    java synchronized 关键字的锁升级过程
    子类中的方法和父类同名,但是参数不同,是重写(overload)不是覆盖(override)
    Java的协变(extends)和逆变(super),说白了都是子类的实例赋值给父类的变量
    Mybatis缓存
    [转]Spring MVC之 @PathVariable @CookieValue@RequestParam @RequestBody @RequestHeader@SessionAttributes, @ModelAttribute
  • 原文地址:https://www.cnblogs.com/myyard777/p/9101031.html
Copyright © 2020-2023  润新知