现在是多核和并发时代,所以不管什么语言都要支持这个特性。并发是看上去同时执行,并行是在多核上同时执行。
我们先解释下线程和进程。简单来说,一个任务就是一个进程(Process)。
在一个进程内部,要同时干多件事,就需要同时运行多个进程内的“子任务”,这些子任务就叫线程(Thread)
线程是最小的执行单元,而进程由至少一个线程组成。如何调度进程和线程,
完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间。
多进程和多线程的程序涉及到同步、数据共享的问题,编写起来更复杂。
生活心情
现在是多核和并发时代,所以不管什么语言都要支持这个特性。并发是看上去同时执行,并行是在多核上同时执行。
我们先解释下线程和进程。简单来说,一个任务就是一个进程(Process)。
在一个进程内部,要同时干多件事,就需要同时运行多个进程内的“子任务”,这些子任务就叫线程(Thread)
线程是最小的执行单元,而进程由至少一个线程组成。如何调度进程和线程,
完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间。
多进程和多线程的程序涉及到同步、数据共享的问题,编写起来更复杂。
日期和时间是我们编程经常需要处理的事情,相比较其他语言,python中的日期和时间处理非常简洁。
datetime是python处理日期和时间的标准库。
python中有一个datetime模块,里面有个datetime类,这里大家先要弄清楚,很容易搞混。
所以我们获取当前日期和时间的代码如下:1
2
3
4
5from datetime import datetime
now = datetime.now() # 获取当前datetime
print(now)
print(type(now))
# <class 'datetime.datetime'>
如果仅导入import datetime,则必须引用全名datetime.datetime
datetime.now()返回当前日期和时间,其类型是datetime
字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。
正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,
凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
我们判断一个字符串是否是一个合法的电话号码分两步,首先创建一个符合电话号码规则的正则表达式,
然后用这个正则表达式来匹配这个字符串是否合法。
因为正则表达式也是用字符串表示,我们就要先学习如何用字符来描述字符。
正则表达式中直接给出字符就是精确匹配,而用\d可匹配数字,\w匹配一个字母或数字。
.可以匹配任意一个字符,所以
在正则表达式中匹配变长的字符:
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。我们在hello.py模块里定义一个Hello的
当Python解释器载入hello模块时,就会依次执行该模块的所有语句,执行结果就是动态创建出一个Hello的class对象。
我们说class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。
type()函数既可以返回一个对象的类型,又可以创建出新的类型。
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。
OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。
为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,
并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。
自定义的对象数据类型就是面向对象中的类(Class)的概念。
给对象发消息实际上就是调用对象对应的关联函数(或者叫绑定函数),我们称之为对象的方法(Method)。
面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。
Class是一种抽象概念,比如我们定义一个叫Person的Class指定人类这个概念,
而实例(Instance)则是一个个具体的Person,比如,张三和李四是两个具体的Person。
python有着强大的表达式语法和函数特性,其中一个我的最爱便是装饰器。
在设计模式中,装饰器能够在不使用子类的情况下动态的修改函数、方法或类的功能。
当你需要扩展某个函数的功能却不想直接修改这个函数的时候,装饰器就可以派上用场了。
实现装饰器模式有很多种方法,但是python通过强大的语法支持来让这个变得相当容易。
在这篇文章中我将深入讲解Python的函数装饰器,并通过一系列的源码示例来彻底讲清楚这个东西。
所有例子都在Python2.7下运行通过,不过只需要稍作改变就可以运行在Python3上了,
甚至我猜测什么都不用改变都可以的,读者可以自己去试试。
本质上来讲,装饰器是以包装器形式工作的,其实就是在执行目标函数之前或之后加入自己的逻辑,
而不需要改变目标函数本身就可以增强它的功能,也就是说装饰了它。
在讲生成器之前,先讲讲python里面常用的几个常见的推导式:
列表推导式(list comprehension)1
my_list = [f(x) for x in sequence if cond(x)]
字典推导式(dictionary comprehension)1
my_dict = {k(x): v(x) for x in sequence if cond(x)}
集合推导式(set comprehension)1
my_set = {f(x) for x in sequence if cond(x)}
生成器表达式(generator expression)1
my_generator = (f(x) for x in sequence if cond(x))
对于大部分的python初学者而言,生成器和yield
关键字比较难以理解。很多文章解释的不清楚,
这篇文章我想深入的讲解这个yield
关键字,它到底是个什么东西,为什么它如此的重要,以及我们该如何去使用它。
注意:近些年来,随着越来越多的特性被加入到PEP中,生成器变得越来越强大。我在下一篇文章会深入讲解协程、多任务协作和异步I/O这些高阶知识,来见识下yield
的威力。
迭代(iteration)指的是去获取元素的一种方式,一个接一个。当你显式或隐式的使用循环来遍历某个元素集的时候,那就是迭代。
在Python里面,可迭代对象(iterable)和迭代器(iterator)有着特殊的含义。
iterable
是实现了__iter__()
方法的对象,该方法会返回一个iterator
对象iterator
是实现了__iter__()
和__next__()
方法的对象,__iter__()
方法返回的是iterator
对象本身由此可见,iterable
和iterator
的本质区别就是后者多了一个__next__()
方法。
也就是说一个iterator
对象必定是一个iterable
对象。
当你使用一个for
循环或者map
,或着一个列表推导,那么会先通过iter()获取相应的迭代器,
然后每次循环自动通过next
方法调用这个迭代器(iterator),从中获取每一个元素,从而完成迭代过程。
在一个iterable
对象上执行iter
会返回一个iterator
对象, 比如iter(obj)
模块和包都是用来组织代码用的,在python中一个模块就是一个.py文件,而一个包就是一个包含了__init__.py
的文件夹。
使用模块最大的好处就是提高代码可维护性,我们在编写代码的时候通常会引用内置模块或第三方模块。
引入包是为了解决命名冲突问题,你可以把包当成是命名空间,比如你写的abc.py
模块和其他人写的abc.py
模块只要在不同的包中就不会冲突。
只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。
比如我现在有这样一个目录结构:
winhong/
web/
__init__.py
util.py
__init__.py (定义cool()函数)
main.py (定义aa()函数和User类)
每一个包目录下面都会有一个__init__.py
的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,
而不是一个包。__init__.py
可以是空文件,也可以有Python代码,__init__.py
本身就是一个模块,
而它的模块名就是所在文件夹名,比如winhong
目录下的__init__.py
模块名就是winhong
,而web目录下的__init__.py
的模块名就是web
。
注:自己编写模块时候
sys
模块,自己的模块就不可命名为sys.py
当需要将写的程序打包分发出去的时候,就要使用到setuptools工具了,这里我通过一个实际例子来介绍它的使用方法。
之前写过一个rpc模块叫xnrpc:
Python的软件包一开始是没有官方的标准分发格式的。比如Java有jar包或者war包作为分发格式,Python则什么都没有。
后来不同的工具都开始引入一些比较通用的归档格式。比如,setuptools引入了Egg格式。
但是,这些都不是官方支持的,存在元数据和包结构彼此不兼容的问题。因此,为了解决这个问题,
PEP 427定义了新的分发包标准,名为Wheel。目前pip和setuptools工具都支持Wheel格式。
这里我们简单总结一下常用的分发格式:
Python setup.py bdist_egg
命令生成。Python setup.py bdist_wheel
生成。Python Wheels网站展示了使用Wheels发行的python模块在PyPI上的占有率,推荐使用wheel包。
如果你到系统中安装Python库的路径下看看,就能看到很多名称以.egg-info或者以.dist-info结尾的目录。这些目录的内容就是这个库的元数据,
是从库的分发包中拷贝出来的。其中.egg-info类型的目录来自于Egg格式的分发包,.dist-info类型的目录来自于Wheel格式的分发包
xnrpc项目的目录结果如下
项目最顶层的目录为“xnrpc”,其中与打包最相关的文件是setup.py,
这里面最核心的文件就是这个setup.py了,我们看看里面写什么: