Wetts's blog

Stay Hungry, Stay Foolish.

0%

转自:https://www.cnblogs.com/MY0213/p/8798926.html

TCP、UDP 可以绑定同一端口来进行通信:

网络中可以被命名和寻址的通信端口,是操作系统可分配的一种资源。

按照 OSI 七层协议的描述,传输层与网络层在功能上的最大区别是传输层提供进程通信能力。从这个意义上讲,网络通信的最终地址就不仅仅是主机地址了,还包括可以描述进程的某种标识符。为此,TCP/IP 协议提出了协议端口(protocol port,简称端口)的概念,用于标识通信的进程。

端口是一种抽象的软件结构(包括一些数据结构和 I/O 缓冲区)。应用程序(即进程)通过系统调用与某端口建立连接(binding)后,传输层传给该端口的数据都被相应进程所接收,相应进程发给传输层的数据都通过该端口输出。在 TCP/IP 协议的实现中,端口操作类似于一般的 I/O 操作,进程获取一个端口,相当于获取本地唯一的 I/O 文件,可以用一般的读写原语访问之。

类似于文件描述符,每个端口都拥有一个叫端口号(port number)的整数型标识符,用于区别不同端口。由于 TCP/IP 传输层的两个协议 TCP 和 UDP 是完全独立的两个软件模块,因此各自的端口号也相互独立,如 TCP 有一个 255 号端口,UDP也可以有一个 255 号端口,二者并不冲突。

端口号的分配是一个重要问题。有两种基本分配方式:第一种叫全局分配,这是一种集中控制方式,由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众。第二种是本地分配,又称动态连接,即进程需要访问传输层服务时,向本地操作系统提出申请,操作系统返回一个本地唯一的端口号,进程再通过合适的系统调用将自己与该端口号联系起来(绑扎)。TCP/IP 端口号的分配中综合了上述两种方式。TCP/IP 将端口号分为两部分,少量的作为保留端口,以全局方式分配给服务进程。因此,每一个标准服务器都拥有一个全局公认的端口(即周知口,well-known port),即使在不同机器上,其端口号也相同。剩余的为自由端口,以本地方式进行分配。TCP 和 UDP 均规定,小于 256 的端口号才能作保留端口。

再讨论一下,一个服务器监控一个端口,比如 80 端口,它为什么可以建立上成千上万的连接?

首先, 一个 TCP 连接需要由四元组来形成,即(src_ip、src_port、dst_ip、dst_port)。当一个连接请求过来的时候,服务端调用 accept 函数,新生成一个 socket,这个 socket 所占用的本地端口依然是 80 端口。由四元组就很容易分析到了,同一个(src_ip、src_port),它所对应的(dst_ip、dst_port)可以无穷变化,这样就可以建立很多个客户端的请求了。

在 Python 的 string 前面加上 r, 是为了告诉编译器这个 string 是个 raw string,不要转义。

例如:

1
2
3
4
5
6
7
8
9
s=r'\tt'
print(s)
Output:
'\tt'

s='\tt'
print(s)
Output:
' t'

和 list 比较,dict 有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增加而变慢;
  2. 需要占用大量的内存,内存浪费多。

而 list 相反:

  1. 查找和插入的时间随着元素的增加而增加;
  2. 占用空间小,浪费内存很少。

所以,dict 是用空间来换取时间的一种方法。

types模块中提供了四个常量

  • types.FunctionType:函数
  • types.BuiltinFunctionType:内建函数
  • types.LambdaType:匿名函数
  • types.GeneratorType:生成器类型

可使用for进行迭代的数据类型分为以下两种:

  1. 集合数据类型:如 dict、list、tuple、set、str 等;
  2. generator:包括生成器和 yield 的 generator function;

Python 的 Iterator 对象表示的是一个数据流,Iterator 对象可以被 next() 函数调用并不断返回下一个数据,直到没有数据时抛出 StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next() 函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。

把 list、dict、str 等 Iterable 变成 Iterator 可以使用 iter() 函数。

参考:https://blog.csdn.net/slrong/article/details/80306905

Python 中判断对象是否能迭代,导入 from collections import Iterable 报错。

改为 from collections.abc import Iterable 就可以了。

1
2
3
DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
from collections import Iterable
True

转自:https://www.cnblogs.com/allenblogs/p/10344814.html

注意,这里说的Python3里面的range函数,和Python2是不同的,返回的不是列表,是可迭代对象。

在python3中,如果执行下面的语句print(range(10))

得到结果是range(0,10),而不是期望的[0,1,2,3,4,5,6,7,8,9]。但是如果换一种方式print(list(range(10)))

得到的结果却是[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

那为什么会这样呢?其实在 Python3 中range()函数返回的对象很像一个列表,但是它确实不是一个列表,它只是在迭代的情况下返回指定索引的值,它并不会在内存中产生一个列表对象,官方解释说这样做是为了节约内存空间。通常我们称这种对象是可迭代的,或者是可迭代对象。

这里就要引入另外一个叫迭代器的概念,迭代器可以从一个可迭代对象中连续获取指定索引的值,直到索引结束。比如list()函数,所以在上面的例子中,我们可以用list()这个迭代器将range()函数返回的对象变成一个列表。

由此可以看出:range()函数返回的是一个可迭代对象(类型是对象),而不是列表类型;list()函数是对象迭代器,把对象转为一个列表,返回的变量类型为列表。

用 Code-Runner 运行 Python 程序时,默认使用 python 语句执行。如果电脑上有 Python2 和 Python3 两个版本,Python 语句是用 Python2 执行程序。

需要修改 Code-Runner 配置指定用 Python3 执行。

在 Settings 中搜索 Code Runner Configure,输入 code-runner.executorMap,按下图来修改配置。

1

  • 定义默认参数要牢记一点:默认参数必须指向不变对象!
  • 在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
  • 每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。
  • 类型属于对象,而不是变量

命题逻辑

条件命题的真值表

当 p 和 q 都为真,以及当 p 为假(与 q 的真值无关)时,语句 p->q 为真。

命题等价式

条件命题的逻辑等价式

  • p->q≡┐p∨q
  • p->q≡┐q->┐p
  • p∨q≡┐p->q
  • p∧q≡┐(p->┐q)
  • ┐(p->q)≡p∧┐q
  • (p->q)∧(p->r)≡p->(q∧r)
  • (p->r)∧(q->r)≡(p∨q)->r
  • (p->q)∨(p->r)≡p->(q∨r)
  • (p->r)∨(q->r)≡(p∧q)->r

双条件命题的逻辑等价式

  • p<->q≡(p->q)∧(q->p)
  • p<->q≡┐p<->┐q
  • p<->q≡(p∧q)∨(┐p∧┐q)
  • ┐(p<->q)≡p<->┐q

谓词和量词

谓词

语句“x 大于3”有两个部分。第一部分即变量 x 是语句的主语。第二部分(__谓词__“大于3”)表明语句的主语居右的一个性质。我们可以用 P(x) 表示语句“x 大于3”,其中 P 表示谓词“大于3”,而 x 是变量。语句 P(x) 也可以说成是命题函数 P 在 x 的值。一旦给变量 x 赋一个值,语句 p(x) 就成为命题并具有真值。

量词

量化表示在何种程度上谓词对于一定范围的个体成立。在自然语言中,所有、某些、许多、没有,以及少量这些词都可以用在量化上。这里我们集中讨论两类量化:全称量化,它告诉我们一个谓词在所考虑范围内对每一个体都为真;存在量化,它告诉我们一个谓词对所考虑范围内的一个或多个个体为真。

全称量词

许多数学命题断言某一性质对于变量在某一特定域内的所有值均为真,这一特定域称为变量的 __论域__(dormain of discourse)(或 __全体域__(universe of discourse)),时常简称为 __域__(domain)。这些语句可以用全称量化表示。

对特定论域而言 P(x) 的全称量化是这样一个命题:它断言 P(x) 对 x 在其论域汇总的所有值均为真。

注意,论域规定了变量 x 所有可能取的值。当我们改变论域时,P(x) 的全称量化的意义也随之改变。在使用全称量化时必须指定论域,否则语句的 全称量化 就是无定义的。

P(x)全称量化 是语句“P(x) 对 x 在其论域的所有值为真。”

符号 ∀xP(x) 表示 P(x) 的全称量化,其中 ∀ 称为 __全称量词__。命题 VxP(x) 读做“对所有 x,_P(x)_”或“对每个 x,_P(x)_”。一个使 P(x) 为假的个体称为 ∀xP(x) 的 __反例__。

通常,我们会做一个隐式的假设,即量词的论域均为非空的。注意如果论域为空,那么 ∀xP(x) 对任何命题函数 P(x) 都为真,因为论域中没有单个 x 使 P(x) 为假。

存在量词

P(x)存在量化 的命题“论域中存在一个个体 x 满足 _P(x)_。”

我们用符号 ョxP(X) 表示 P(x) 的存在量化,其中 ョ 称为 __存在量词__。存在量化 ョxP(X) 可读做“有一个 x 满足 _P(x)_”、“至少有一个 x 满足 _P(x)”或“对某个 x,_P(x)”。

通常,我们会做一个隐式的假设,即量词的论域均为非空的。如果论域为空,那么无论 Q(x) 是什么命题函数,当论域为空时论域中没有一个个体能使 Q(x) 为真,所以 ョxP(X) 为假。

唯一性量词

对于我们能定义的不同量词的数量使没有限制的,如“恰好有 2 个”、“有不超过 3 个”、“至少有 100 个”等。所有其他量词中最常见的使 __唯一性量词__,用符号 ョ! 或 ョ1表示。_ョ!xP(x)_(或 _ョ1xP(x)_)这种表示法是指“存在一个唯一的 x 使得 P(x) 为真”。(其他表示唯一性量词的语句有“恰好存在一个”、“有且只有一个”)比如,_ョ!x(x-1=0)_,其中论域使实数集合,表示存在一个唯一的实数 x 使得 x-1=0。

约束论域的量词

∀x<0(x2>0)

涉及量词的逻辑等价式

∀x(P(x)∧Q(x))≡∀xP(x)∧∀xQ(x)

量化表达式的否定

  • ┐∀xP(x)≡ョx┐P(x)
  • ┐ョxQ(x)≡∀x┐Q(x)

嵌套量词

嵌套量词的顺序

要注意的是,量词的顺序是很重要的,除非所有量词为全称量词或均为存在量词。

推理规则

数学中的证明是建立数学命题真实性的有效论证。所谓的 __论证__(argument),是指一连串的饿命题并以结论为最后的命题。所谓 __有效性__(valid),是指结论或论证的最后一个命题必须根据论证过程前面的命题或 __前提__(premise)的真实性推出。也就是说,一个论证是有效的当且仅当不可能出现所有前提为真而结论为假的情况。

命题逻辑的有效论证

命题逻辑中的一个论证是一连串的命题。除了论证中最后一个命题外都叫做前提,最后那个命题叫做结论。一个论证是有效的,如果它的所有前提为真蕴含着结论为真。
命题逻辑中的论证形式是一连串涉及命题变元的复合命题。无论用什么特定命题来替换其中的命题变元,如果前提均为真时结论为真,则称该论证形式是有效的。

证明导论

专用术语

正式地,一个 __定理__(theorem)是一个能够被证明是真的语句。在数学描述中,定理一词通常是用来专指那些被认为至少有些重要的语句。不太重要的定理有时称为 __命题__(定理也可以称为 __事实__(fact)或 __结论__(result))。一个定理可以是带一个或多个前提及一个结论的条件语句的全称量化式。当然,它也可以是其他类型的逻辑语句。我们用一个 __证明__(proof)来展示一个定理是真的。证明就是建立定理真实性的一个有效论证。证明中用到的语句可以包括 __公理__(axiom)(或 __假设__(postulate)),这些是我们假定为真的语句(例如,实数公理,以及平面几何的公理)、定理的前提(如果有的话)和以前已经被证明的定理。公理可以采用无须定义的原是属于来陈述,而在定理和证明中所用的所有其他属于都必须是有定义的。推理规则和其术语的定义一起用于从其他的断言推出结论,并绑定在证明中的每个步骤。实际上,一个证明的最后一步通常恰好是定理的结论。然而,为清晰可见,我们通常会重述定理的结论作为一个证明的最后步骤。
一个不太重要但有助于证明其结论的定理称为 __引理__(lemma)。当用一系列引理来进行复杂的证明时通常比较容易理解,其中每一个引理都被独立证明。__推论__(corollary)是从一个已经被证明的定理可以直接建立起来的定理。__猜想__(conjecture)是一个被提出认为是真的命题,通常是基于部分证据、启发式论证或者专家的直觉。当猜想的一个证明被发现时,猜想就变成了定理。

证明定理的方法

直接证明法

条件语句 p->q 的 直接证明法 的构造:第一步假设 p 为真;第二步用推理规则构造,而第三步表明 q 必须也为真。

反证法

反证法利用了这样一个事实:条件语句 p->q 等价于它的逆否命题 ┐q->┐p。着意味着条件语句 p->q 的证明可以通过它的逆否命题 ┐q->┐p 为真来完成。

归谬证明法

假设我们要证明命题 p 是真的。再假定我们能找到一个矛盾式 q 使得 ┐p->q 为真。因为 q 是假的,而 ┐p->q 是真的,所以我们能够得出结论 ┐p 为假,这意味着 p 为真。
因为无论 r 是什么,命题 r∧┐r 就是矛盾式,所以如果我们能够证明对某个命题 r,┐p->(r∧┐r) 为真,就能证明 p 是真的。这种类型的证明称为 __归谬证明法__(proof by contradiction)。由于归谬证明法不是直接证明结论,所以它是另一个种间接证明法。

等价证明法
反例证明法
穷举证明法
分情形证明法

存在性证明

ョxP(x) 这类命题的证明称为 __存在性证明__(existence proof)。有多种方式来证明这类定理。有时可以通过找出一个是的 P(a) 为真的元素 a(称为一个物证)来给出 ョxP(x) 的存在性证明。这样的存在性证明称为是 __构造性的__(constructive)。也可以给出一种 __非结构性的__(nonconstructive)存在性证明,即不是找出使 P(a) 为真的元素 a,而是以某种其他方式来证明 ョxP(x) 为真。

唯一性证明

某些定理断言具有特定性质的元素唯一存在。换句话说,这些定理断言恰好只有一个元素具有这个性质。要证明这些语句,需要证明存在一个具有此性质的元素,以及没有其他元素具有此性质。__唯一性证明__(uniqueness proof)的两个部分如下:

  • 存在性:证明存在某个元素 x 具有期望的性质。
  • 唯一性:证明如果 y≠x,则 y 不具有期望的性质。

证明存在唯一元素 x 使得 P(x) 为真等同于证明语句 ョx(P(x)∧∀y(y≠x->┐P(y)))。