网络编程和并发编程

一.网络编程:

在网络编程中的一个基本组件就是套接字。套接字主要是两个程序之间的信息通道。

套接字包括两个:服务器套接字和客户机套接字。创建一个服务器套接字后,让它等待连接。这样它就在某个网络地址处监听。

一个套接字就是一个socket模块中socket类的实例。它的实例化需要3个参数:第一个参数是地址族(默认是socket.AF_INET);第2个参数是流(socket.SOCK_STREAM,默认值)或数据报(socket.SOCK_DGRAM)套接字。第三个参数是使用的协议(默认是0)。

socket起源于Unix,在Unix一切皆文件的哲学的思想下,socket是一种”打开—读/写—关闭”模式的实现,服务器和客户端各自维护一个”文件”,在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。socket的英文原义是“插槽”或“插座”,就像我们家里座机一样,如果没有网线的那个插口,电话是无法通信的。Socket是实现TCP,UDP协议的接口,便于使用TCP,UDP。

Python 提供了两个级别访问的网络服务:

  • 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

二.并发编程:

  ·总体概述:

      我们将一个正在运行的程序称为进程。每个进程都有它自己的系统状态,包含内存状态、打开文件列表、追踪指令执行情况的程序指针以及一个保存局部变量的调用栈。通常情况下,

      一个进程依照一个单序列控制流顺序执行,这个控制流被称为该进程的主线程。在任何给定的时刻,一个程序只做一件事情。

      一个程序可以通过Python库函数中的os或subprocess模块创建新进程(例如os.fork()或是subprocess.Popen())。然而,这些被称为子进程的进程却是独立运行的,

      它们有各自独立的系统状态以及主线程。因为进程之间是相互独立的,因此它们同原有的进程并发执行。这是指原进程可以在创建子进程后去执行其它工作。

      虽然进程之间是相互独立的,但是它们能够通过名为进程间通信(IPC)的机制进行相互通信。一个典型的模式是基于消息传递,可以将其简单地理解为一个纯字节的缓冲区,

      而send()或recv()操作原语可以通过诸如管道(pipe)或是网络套接字(network socket)等I/O通道传输或接收消息。还有一些IPC模式可以通过内存映射(memory-mapped)机制完成(例如mmap模块),

      通过内存映射,进程可以在内存中创建共享区域,而对这些区域的修改对所有的进程可见。

      多进程能够被用于需要同时执行多个任务的场景,由不同的进程负责任务的不同部分。然而,另一种将工作细分到任务的方法是使用线程。同进程类似,线程也有其自己的控制流以及执行栈,

      但线程在创建它的进程之内运行,分享其父进程的所有数据和系统资源。当应用需要完成并发任务的时候线程是很有用的,但是潜在的问题是任务间必须分享大量的系统状态。

      当使用多进程或多线程时,操作系统负责调度。这是通过给每个进程(或线程)一个很小的时间片并且在所有活动任务之间快速循环切换来实现的,这个过程将CPU时间分割为小片段分给各个任务。

      例如,如果你的系统中有10个活跃的进程正在执行,操作系统将会适当的将十分之一的CPU时间分配给每个进程并且循环地在十个进程之间切换。当系统不止有一个CPU核时,

      操作系统能够将进程调度到不同的CPU核上,保持系统负载平均以实现并行执行。

      利用并发执行机制写的程序需要考虑一些复杂的问题。复杂性的主要来源是关于同步和共享数据的问题。通常情况下,

      多个任务同时试图更新同一个数据结构会造成脏数据和程序状态不一致的问题(正式的说法是资源竞争的问题)。为了解决这个问题,

      需要使用互斥锁或是其他相似的同步原语来标识并保护程序中的关键部分。举个例子,如果多个不同的线程正在试图同时向同一个文件写入数据,那么你需要一个互斥锁使这些写操作依次执行,

      当一个线程在写入时,其他线程必须等待直到当前线程释放这个资源。

  ·Python的并发编程:

      Python长久以来一直支持不同方式的并发编程,包括线程、子进程以及其他利用生成器(generator function)的并发实现。

      Python在大部分系统上同时支持消息传递和基于线程的并发编程机制。虽然大部分程序员对线程接口更为熟悉,但是Python的线程机制却有着诸多的限制。

      Python使用了内部全局解释器锁(GIL)来保证线程安全,GIL同时只允许一个线程执行。这使得Python程序就算在多核系统上也只能在单个处理器上运行。

      Python界关于GIL的争论尽管很多,但在可预见的未来却没有将其移除的可能。

      Python提供了一些很精巧的工具用于管理基于线程和进程的并发操作。即使是简单地程序也能够使用这些工具使得任务并发进行从而加快运行速度。

      subprocess模块为子进程的创建和通信提供了API。这特别适合运行与文本相关的程序,因为这些API支持通过新进程的标准输入输出通道传送数据。

      signal模块将UNIX系统的信号量机制暴露给用户,用以在进程之间传递事件信息。信号是异步处理的,通常有信号到来时会中断程序当前的工作。

      信号机制能够实现粗粒度的消息传递系统,但是有其他更可靠的进程内通讯技术能够传递更复杂的消息。threading模块为并发操作提供了一系列高级的,面向对象的API。

      Thread对象们在一个进程内并发地运行,分享内存资源。使用线程能够更好地扩展I/O密集型的任务。multiprocessing模块同threading模块类似,不过它提供了对于进程的操作。

      每个进程类是真实的操作系统进程,并且没有共享内存资源,但multiprocessing模块提供了进程间共享数据以及传递消息的机制。

      通常情况下,将基于线程的程序改为基于进程的很简单,只需要修改一些import声明即可。

三.每天十题:

1.什么是lambda函数以及它的好处?

答:lambda函数是一个匿名函数,起到的是一个函数速写的作用。 

  好处是:

    1、对于单行函数,使用lambda可以省去定义函数的过程,让代码更加精简。

    2、在非多次调用的函数的情况下,lambda表达式即用既得,提高性能

 

2.解释一下Python的and-or语法。

答:在Python 中,and 和 or 执行布尔逻辑演算,但是它们并不返回布尔值;而是,返回它们实际进行比较的值之一。

  使用 and 时,在布尔上下文中从左到右演算表达式的值。0、''、[]、()、{}、None 在布尔上下文中为假;其它任何东西都为真。还好,几乎是所有东西。默认情况下,布尔上下文中的类实例为真,

  但是你可以在类中定义特定的方法使得类实例的演算值为假。你将会在第 5 章中了解到类和这些特殊方法。如果布尔上下文中的所有值都为真,那么 and 返回最后一个值。在这个例子中,

  and 演算 'a' 的值为真,然后是 'b' 的演算值为真,最终返回 'b'。 

     如果布尔上下文中的某个值为假,则 and 返回第一个假值。在这个例子中,'' 是第一个假值。

  所有值都为真,所以 and 返回最后一个真值,'c'。

3.python是如何进类型转换的

答:

  1. 函数                      描述  
  2. int(x [,base ])         将x转换为一个整数  
  3. long(x [,base ])        将x转换为一个长整数  
  4. float(x )               将x转换到一个浮点数  
  5. complex(real [,imag ])  创建一个复数  
  6. str(x )                 将对象 x 转换为字符串  
  7. repr(x )                将对象 x 转换为表达式字符串  
  8. eval(str )              用来计算在字符串中的有效Python表达式,并返回一个对象  
  9. tuple(s )               将序列 s 转换为一个元组  
  10. list(s )                将序列 s 转换为一个列表  
  11. chr(x )                 将一个整数转换为一个字符  
  12. unichr(x )              将一个整数转换为Unicode字符  
  13. ord(x )                 将一个字符转换为它的整数值  
  14. hex(x )                 将一个整数转换为一个十六进制字符串  
  15. oct(x )                 将一个整数转换为一个八进制字符串 

 4.Python中类方法、类实例方法、静态方法有什么区别?

答: 

     三种方法的区别之一,体现在参数上:实例方法隐含的参数为类实例self,类方法隐含的参数为类本身cls,静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。

     逻辑上类方法应当只被类调用,实例方法实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数。

     Python中实现了一定的灵活性使得实例方法、类方法和静态方法,都能够被实例和类二者调用,而实现的原理就是显示的传递参数。

5.Python中的pass语句的作用是什么?

答:

  pass语句什么也不做,一般作为占位符或者创建占位程序,pass语句不会执行任何操作

6.介绍一下Python中range()和xrange()函数的用法?

答:

  range():range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列。

    xrange():用法与range完全相同,所不同的是生成的不是一个数组,而是一个生成器。

7.用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别?

答:

  <.*>这种匹配称作贪婪匹配 <.*?>称作非贪婪匹配

    <.*>写法是,尽可能多的匹配,就是匹配到的字符串尽量长, <.*?>写法是尽可能少的匹配,就是匹配到的字符串尽量短。

8.Python里如何拷贝一个对象?

答:

  Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块。

    1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。

    2. copy.deepcopy 深拷贝 拷贝对象及其子对象

9.如何用Python来对一个文本字符串进行查询和替换

答:

  可以使用sub()方法来进行查询和替换,sub方法的格式为:sub(replacement, string[, count=0])

  replacement是被替换成的文本

  string是需要被替换的文本

  count是一个可选参数,指最大被替换的数量

10.Django里Queryset的get方法和filter方法的区别?

答:

  django的get方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。

         比如我数据库里有一条记录,记录的name的值是” 老王python”的话,我用student=Student.objects.get(name='老王python'),返回的是一个记录对象,可以通过student.__dict__来查看,

    它返回的是一个字典的形式,{'key':valeus},key是字段的名称,而values是值的内容。而如果我用get方法来查询一个数据库里不存在的记录,程序会报错。

    比如:student= Student.objects.get(name='老王')。

    如果用django的get去取得关联表的数据的话,而关键表的数据如果多于2条的话也会报错。

  

  django的filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。

         比如我数据库里有一条记录,记录的name的值是老王python的话,我用student =Student.objects.filter(name='老王python'),它返回的student是一个对象的列表,

    可以看的出来student[0]和上面的get方式返回的student的结果是一样的。

    如果你用django的filter去取得关联表的数据的话,无论关联表有多少记录的都不会报错。

         另外我从别的资料里看到filter好像有缓存数据的功能,第一次查询数据库并生成缓存,下次再调用filter方法的话,直接取得缓存的数据,会get方法每次执行都是直接查询数据库的,

    不知道这个是不是正确。

原文地址:https://www.cnblogs.com/0704L/p/8447282.html