元组(tuple):
元组的特性:
是序列表,有序
元组数据值可以访问,不能修改,不能修改,不能修改
元组数据可以是任意类型
总之,list所有的特性,除了可修改以外,元组都具有
也就意味着,list具有的一些操作,比如索引,切片,序列相加,相乘,成员资格操作等,一模一样
元组的函数:
len:获取用户元组的长度
集合set:
集合是高中数学中的一个概念
定义:一堆确定的无序的唯一的数据,集合中每一数据成为一个元素
s = set()
s = {value} 使用大括号时,里面必须有值,否则就为dict字典了
集合的特征:
集合内数据无序,即无法使用索引和切片
集合内部数据具有唯一性,可以用来排序重复数据
集合内部的数据,str,int,float,tuple,冰冻集合等,即内部只能放置可哈希数据
集合函数:
copy:
remove:移除指定的值,直接改变原有值,
discard:和remove一样,但是当移除set中没有的值时,不报错
intersection:交集 &
difference:差集 -
union:并集 |
issubset:检查一个集合是否为另一个子集
issuperset:检查一个集合是否为另一个超集
冰冻集合(frozen set):
冰冻就是不可以进行任何修改的集合
frozenset是一种特殊集合
dict字典:
字典是一种组合数据,没有顺序的组合,数据以键值对形式出现
特征:
字典是无序类型,但是无序,所以没有切片和索引
字典中的数据每个都由键值对组成,即kv对
key:必须是可哈希的值,比如string,float,tuple,但是list,set,dict不行
value:任何值
字典相关函数:
通用函数:len,max,min,dict
str(dict):返回字典的字符串形式
clear:清空字典
items:返回字典的键值对组成的元组格式dict.items()
dict.values()
dict.keys()
get:根据指定键返回相应的值,好处是,可以设置默认值
dict.get(k,默认值)
fromkeys:使用指定的序列作为键,使用一个值作为字典的所有键的值
注意:fromkeys两个参数的类型
fromkeys的调用主体
Python 的正则表达式:
re:
. 匹配任意字符
[] 匹配一组字符中的任意字符
[^...] 匹配不在组中的任意字符
? 0 or 1次
+ 1+次
{m,n} 至少m次,最多n次
{0,n} 最多n次
{m,} 至少m次
^ 开头
$ 结尾
part1|part2 匹配part1或者part2
(...) :匹配表达式,也表示一个组
\b 匹配单词边界
[0-9]: \d \D
[0-9a-zA-Z]: \w \W
\s : 任意空白字符,[\n\t\f\v\r], \S
\n\t: 匹配换行符、制表符
\nn:
a*? 非贪婪模式
(*|+|?|{})? :使用非贪婪模式
match对象:
re.search:返回一个match对象
match对象:
属性:
string
re
pos
endpos
方法:
group()
start()
end()
re.findall:返回列表
re.sub:返回替换后的整个串
re.subn:返回元祖:替换后的串及替换次数
re.compile:
思考:复制/etc/passwd到/tmp,如何替换/tmp/passwd中的/bin/bash为/BIN/BASH?
hello world:
(o(.)):group1 o
group
flags:
I或IGNORECASE:忽略字符大小写
M或MULTILINE
A或ASCII:仅执行8位ASCII码匹配
U或NUICODE:
函数的基础概念:
Python中可以创建4中函数:
1.全局函数:定义在模块中
2.局部函数:嵌套于其他函数中
3.lambda函数:表达式
4.方法:于特定数据类型关联的函数,并且只能与数据类型关联一起使用(定义在类中的函数)
Python提供了很多内置函数:
函数文档:
函数文档的作用是对当前函数提供使用相关的参考信息
文档的写法:
在函数内部开始的第一行使用三字符串定义符
一般具有特定格式
参看案例
文档查看
使用help函数,形如help(stu)
使用__doc__,参看案例
案例:
def stu(name,age,*args):
'''
这是第一行
这是第二行
这是第三行
'''
print("This is hanshu stu")
查看文档
>>>help(stu)
Help on function stu in module __main__:
stu(name, age, *args)
这是第一行
这是第二行
这是第三行
>>> stu.__doc__
'\n 这是第一行\n 这是第二行\n 这是第三行\n '
案例2:
>>> def stu(name,age):
...
'''
...
这是文档的文字内容
...
:param name: 表示学生的姓名
...
:param age: 表示学生的年龄
...
:return: 此函数没有返回值
...
'''
...
pass
...
>>> help(stu)
Help on function stu in module __main__:
stu(name, age)
这是文档的文字内容
:param name: 表示学生的姓名
:param age: 表示学生的年龄
:return: 此函数没有返回值
>>> print("*"*20)
********************
>>> stu.__doc__
'\n 这是文档的文字内容\n :param name: 表示学生的姓名\n :param age: 表示学生的年龄\n :return: 此函数没有返回值\n '
函数语法:
def functionname(parameters):
suit
函数的变量作用域:
函数:
名称:
作用域:
函数定义了本地作用域(local),而模块定义了全局作用域(global)
1.每个模块都是一个全局作用域,因此,全局作用域的范围仅限于单个程序文件
2.每次对函数的调用都会创建一个新的本地作用域,赋值的变量除非声明为全局变量,否则均为本地变量
3.所有的变量名都可以归纳为本地、全局或内置的(__builtin__模块提供)
变量名解析:LEGB原则
变量名引用分三个作用域进行:首先是本地(local)。之后是函数内(enclosing function local)。接着是全局(global),最后是内置(__builtin__);
提升局部变量为全局变量:
使用global
案例如下:
def func():
global a1
a1 = 100
print(a1)
print("I am func")
a2 = 99
print(a2)
先调用func,a1才能变为全局变量
func()
print(a1)
eval()函数
把一个字符串当成一个表达式来执行,返回表达式执行后的结果
语法:
eval(string_code,global=None,local=None)
案例:
x = 100
y = 200
#执行x+y
#z = x+y
z = eval("x+y")
>>>print(z)
300
exec()函数:
和eval功能类似,但是不返回结果
Python闭包:
def functionName(arg1,arg2...):
suit
参数传递形式:
1.未知参数:从左到右
2.关键字参数:按关键名匹配
混用上面两种方式时:所有位置参数,所有的关键字参数(关键字参数必须放在后面)
3.认参数:有默认值的参数
混用有默认值的参数和无默认值的参数时,无默认值放前面
4.调用函数时使用可变参数要求:
定义函数时使用*:收集位置参数
定义函数时使用**:收集关键字参数
收集参数解包问题:
把参数放入list或者字典dict中,直接吧list/dict中地值放入收集参数中
语法:
def stu(*args):
print("hahahaha")
#n用来表示循环次数
#主要用来调试
n = 0
for i in args:
print(type(i))
print(n)
n += 1
print(i)
stu("liuyifei","feifei",18,20)
l = list()
l.append("liuyifei")
l.append("feifei")
l.append(18)
l.append(20)
stu(l)
stu(*l)----------解构
可变参数解包:调用函数时,使用*
练习:返回/etc/passwd中包含了/bin/bash字串的所有用户名为一个列表
Python闭包:闭包叫lexical closure
函数中使用yield,会返回一个生成器对象。
(函数)装饰器:
1、装饰器本身是一个函数,用于装饰其他函数;
2、功能:增强被装饰函数的功能;
装饰器一般接受一个函数对象作为参数,以对其进行增强
递归函数:
递归需要边界条件,递归前进段和递归返回段;
优点:简洁,容易理解
缺点:对递归深度游限制,消耗资源大
Python对递归深度有限制,超过限制报错
协程:
函数的设计规范:
耦合性:
(1)通过参数接受输入,以及通过return产生输出以保证函数的独立性;
(2)尽量减少使用全局变量进行函数间通信;
(3)不要在函数中修改可变类型的参数;
(4)避免直接改变定义在另外一个模块中的变量;
聚合性:
(1)每个函数都应该有一个单一的、统一的目标;
(2)每个函数的功能都应该相对简单;
类与面向对象:
程序 = 指令+数据:
代码可以选择以指令为核心或以数据为核心进行编写
两种范型:
1、以指令为核心:围绕“正在发生什么”进行编写
面向过程编程:程序具有一系列线性步骤;主题思想是代码作用于数据
2、以数据为核心:围绕“将影响谁”进行编程
面向对象编程(oop):围绕数据及为数据严格定义的接口来组织程序,用数据控制对代码的访问
所有编程语言的最终目的都是提供一种抽象方法:
在机器模型(“解空间”或“方案空间”)与实际解决的问题模型(“问题空间”)之间,程序员必须建立一种联系
面向过程:程序 = 算法+数据结构
面向对象:将问题空间中的元素以及它们在解空间中的表示物抽象为对象,并允许通过问题来描述问题而不是方案
可以把实例(对象)想象成一种新型变量,它保存着数据,但可以对自身的数据执行操作
类型由状态集合(集合)和转换这些状态的操作集合组成:
类抽象:
类:定义了被多个同一类型对象共享的结构和行为(数据和代码)
类的数据和代码:即类的成员
数据:成员变量或实例变量
成员方法:简称为方法,是操作数据的代码,用于定义如何使用成员变量;因此一个类的行为和接口是通过方法来定义的
方法和变量:
私有:内部使用
公共:外部可见
类间关系:
1、依赖(“uses-a”):一个类的方法操纵另一个类的对象
2、聚合(“has-a”):类A的对象包含类B的对象
3、继承(“is-a”):描述特殊与一般关系
OOP思想:
接触到任意一个任务,首先想到的是任务这个世界的构成,是由模型构成的
几个名词:
OO:面向对象
OOA:面向对象的分析
OOD:面向对象的设计
OOI:面向对象的实现
OOP:面向对象的编程
OOA——>OOD--->OOI:面向对象的实现过程
面向对象(OOP)编程的原则:
面向对象的模型机制有3个原则:封装、继承及多态
封装:
隐藏实现方案细节
将代码及其处理的数据绑定在一起的一种编程机制,用于保证程序和数据不熟外部干扰且不会被耽误
在类中或者子类中都可以进行访问,但是外部不可以
方法:在成员名称前添加一个下划线
继承:
一个对象获得另一个对象属性的过程;用于实现按层分类的概念
一个深度继承的子类继承了类层次中它的每个祖先的所有属性
超类、基类、父类
子类、派生类
特征:
所有的类都继承自object类,即所有的类都是object类的子类
子类一旦继承父类,则可以使用父类中除私有成员外的所有内容
子类继承父类后并没有将父类成员完全赋值到子类中,而是通过引用关系访问调用
子类中可以定义独有的成员属性和方法
子类中定义的成员和父类成员如果相同,则优先使用子类成员
子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重写
可以使用父类名、父类成员的格式来调用父类成员,也可以使用super(),父类成员的格式来调用
super:
super不是关键字,而是一个类
super的作用是获取MRO(MethodResolutionOrder)列表中的第一个类
super与父类之间没有任何实质性的关系,但通过super可以调用到父类
super使用两个方法,参见在构造函数中调用父类的构造函数
单继承和多继承:
单继承:每个类只能继承一个类
多继承:每个类允许继承多个类
单继承和多继承的优缺点:
单继承:
传承有序逻辑清晰语法简单隐患少
功能不能无限扩展,只能在当前唯一的继承链中扩展
多继承:
优点:类的功能扩展方便
缺点:继承关系混乱
菱形继承、钻石继承:
多个子类继承自同一个父类,这些子类由被同一个类继承,于是继承关系图形成一个菱形图谱
关于多继承的MRO
MRO就是多继承中,用于保存继承顺序的一个列表
Python本身采用C3算法来多继承的菱形继承进行计算的结果
MRO列表的计算原则
子类永远在父类前面
如果多个父类,则根据继承语法中括号内类的书写顺序存放
如果多个类继承了同一个父类,子孙类中只会选取继承语法括号中第一个父类的父类
多态:
允许一个接口被多个通用的类动作使用的特性,具体使用哪个动作与应用场合相关
“一个接口,多个方法”
用于为一组相关的动作设计一个通用的接口,以降低程序复杂性
多态就是同一个对象在不同情况下有不同的状态出现
多态不是语法,是一种设计思想
多态性:一种调用方式,不同的执行效果
多态:同一事物的多种形态,动物分为人类,够类,猪类
[多态和多态性](https://www.cnblogs.com/luchuangao/p/6739557.html)
Mixin设计模式
主要采用多继承方式对类的功能进行扩展
[Mixin概念](https://www.zhihu.com/question/20778853)
[MRO and Mixin](https://blog.csdn.net/robinjwong/article/details/48375833)
[Mixin模式](https://www.cnblogs.com/xybaby/p/6484262.html)
[Mixin MRO](https://runforever.github.io/2014-07-19/2014-07-19-python-mixin学习笔记/)
[MRO](https://xiaocong.github.io/blog/2012/06/13/python-mixin-and-mro/)
我们使用多继承语法来实现Mixin
使用Mixin实现多继承的时候非常小心
首先它必须表示某一单一功能,而不是某个物品
职责必须单一,如果由多个功能,则写多个Mixin
Mixin不能依赖于子类的实现
子类即使没有继承这个Mixin类,也能照样工作,只是缺少了某个功能
优点:
使用Mixin可以在不对类进行任何修改的情况下,扩展功能
可以方便的组织和维护不同功能组件的划分
可以根据需要任意调整功能类的组合
可以避免创建很多新的类,导致类的继承混乱
类class(类即对象):
Python使用class关键字创建类,语法格式如下:
class ClassName(bases):
‘class documentation string’
class_suite
超类是一个或多个用于继承的父类集合
超类可以包含:声明语句、类成员定义、数据属性、方法
注意:
如果不存在继承关系,ClassName后面的“(bases)”可以不提供
类文档为可选
class语句的一般形式:
class class_name(bases):
data=value: 定义数据类型
def method(self,...): 定义方法属性
self.number = value
类成员描述符(属性):
类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式
get:获取属性
set:修改或者添加属性
delete:删除属性
如果想使用类的成员描述符,大概有三种方法:
使用类实现描述器
使用属性修饰符
使用property函数
property函数很简单
property(fget,fset,fdel,doc)
案例:
#定义一个Person类,具有name,age属性
#对于任意输入的姓名,我们希望都用大写方式保存
#年龄,我们希望内部同一用整数保存
#x = property(fget,fset,fdel,doc)
class Person():
#函数的名称可以任意
def fget(self):
return self._name
def fget1(self):
return self._age
def fset(self,name):
#所有输入的姓名以大写形式保存
self._name = name.upper()
def fset1(self,age):
#所有输入的年龄以整数保存
self._age = int(age)
def fdel(self):
self._name = "NoName"
self._age = 100
name = property(fget, fset, fdel, "对name进行如下操作")
age = property(fget1, fset1, fdel, "对age进行如下操作")
p1 = Person()
p1.name = "feifei"
p1.age = 18.7
print(p1.name)
print(p1.age)
无论哪种修饰符都是为了对成员属性进行相应的控制
类的方式:适合多个类中的多个属性功用一个描述符
property:使用当前类中使用,可以控制一个类中多个属性
属性修饰符:使用于当前类中使用,控制一个类中的一个属性
可调用对象:
函数
内置函数
自定义函数
def
lambda
类
类方法
issubclass(A,B):检测一个类是否为另一个类的子类 ------->A是B的子类吗?
isinstance(A,B):检测一个对象是否是一个类的实例------>A是B的实例吗?
hasattr(A,"xxx"):检测一个对象是否有成员xxx
getattr:获取一个对象的成员xxx
setattr:设置一个对象的成员xxx
delattr:删除一个对象的成员xxx
dir:获取对象列表
函数的属性:
__doc__
__name__
__dict__
__code__
__globals__
内置函数的属性:
__doc__
__name__
__self__
方法的属性:
__doc__
__name__
__class__:方法所属的类
__func__:实现该方法的函数对象
__self__:调用此方法的实例
类:
__doc__
__name__
__bases__:查看类的基类
__dict__
__module__:定义了当前类的模块名称
实例:
__class__
__dict__
对象都有特殊方法(魔术方法):
魔术方法不需要人为调用的方法,在特定时刻会自动触发
魔术方法的统一特征就是,方法名前后各有两个下划线
操作类:
__init__:构造函数,
__new__:对象实例化方法,此函数比较特殊,一般不需要要使用,
__del__,__call__:对象当函数使用的时候触发,
__str__:对象被当做字符串使用时调用,
__repr__:返回字符串,和__str__相似
__dir__()
__add__()
__ge__()
a > b ====> a.__ge__(b)
实例:
class A():
def __init__(self,name = "feifei"):
print("1")
def __call__(self):
print("2")
def __str__(self):
return "nihao"
a = A() ---->自动调用__init__
a() ---->自动调用__call__
print(a) ---->自动调用__str__
描述符相关:
__set__
__get__
__delete__
属性操作相关:
__getattr__:访问一个不存在的属性时触发
实例:
class A():
name = "feifei"
age = 11
def __getattr__(self,name):
#print("NO attr")
#print(name)
return "NO attr",name
a = A()
print(a.name)
print(a.addr)
__setattr__:对成员属性进行设置的时候触发
参数:
self用来获取当前对象
被设置的属性名称,以字符串形式出现
需要对属性名称设置的值
作用:进行属性设置的时候进行验证或者修改
注意:在该方法中不能对属性直接进行赋值操作,否则死循环
实例:
class A():
def __init__(self):
pass
def __setattr__(self, name, value):
print("设置属性:{0}".format(name))
#下面语句会导致问题,死循环
#self.name = value
#此种情况,为了避免死循环,规定统一调用父类魔法函数
super().__setattr__(name, value)
a = A()
print(a.__dict__)
a.age = 18
运算分类相关魔法方法:
__gt__:进行对于判断的时候触发的函数
参数:
self
第二参数时第二个对象
返回值可以是任意值,推荐返回布尔值
案例:
class Student():
def __init__(self, name):
self._name = name
def __gt__(self, obj):
#print("哈哈,{0}会比{1}大吗?".format(self, obj.))
print("哈哈,{0}会比{1}大吗?".format(self._name, obj._name))
return self._name > obj._name
stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
抽象类
抽象方法:没有具体实现内容的方法称为抽象方法
抽象方法的主要意义是规范了子类的行为和接口
抽象类的使用需要借助abc模块
import abc
抽象类:包含抽象方法的类叫抽象类,通常称为ABC类
抽象类的使用:
抽象类可以包含抽象方法,也可以包含具体方法
抽象类中可以有方法也可以有属性
抽象类不允许直接实例化
必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法
假定子类没有实现所有继承的抽象方法,则子类也不能实例化
抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范
实例:
#抽象类的实现
import abc
#声明一个类并且指定当前类的元类
class Human(metaclass = abc.ABCMeta):
#定义一个抽象的方法
@abc.abstractmethod
def smoking(self):
pass
#定义类抽象方法
@abc.abstractclassmethod
def drink():
pass
#定义静态抽象方法
@abc.abstractstaticmethod
def play():
pass
def sleep(self):
print("Sleeping....")
自定义类:
类其实是一个类定义和各种方法的自由组合
可以定义类和函数,然后自己通过类直接赋值
可以借助于MethodType模块实现
借助于type模块中的types实现
利用元类实现-MetaClass
元类是类
备用来创造别的类
实例:
#自己组装一个类
class A():
pass
def say(self):
print("Saying....")
say(9)
A.say = say
a = A()
a.say()
#例子-2
#自己组装一个类
from types import MethodType
class A():
pass
def say(self):
print("Saying....")
a = A()
a.say = MethodType(say,A)
a.say()
#利用type制造一个类
#先定义类应该具有的成员函数
def say(self):
print("Saying....")
def talk(self):
print("Talking...")
#用type来创建一个类
A = type("AName", (object, ), {"class_say":say, "class_talk":talk})
#然后可以像正常访问一样使用类
a = A()
a.class_say()
a.class_talk()
#元类演示
#元类写法是固定的,它必须继承自type
#元类一般命名以MetaClass结尾
class TulingMetaClass(type):
#注意以下写法
def __new__(cls, name, bases, attrs):
#自己的业务处理
print("哈哈,我是元类")
attrs['id'] = '000000'
attrs['addr'] = "北京海淀区公主坟西翠路12号"
return type.__new__(cls, name, bases, attrs)
#元类定义完就可以使用,使用注意写法
class Teacher(object, metaclass=TulingMetaClass):
pass
t = Teacher()
t.id
t.addr
#t.__dict__
Python模块:模块就是Python文件,后缀名为.py
顶层文件
模块文件1
模块文件2
如何定义模块:
模块就是一个普通文件,所以任何代码可以直接书写
不过根据模块的规范,最好模块中编写如下内容:
函数(单一功能)
类(相似功能的组合,或者类似业务模块)
测试代码
模块直接导入
假如模块名称直接以数字开头,需要借助importlib帮助 名称=importlib.import_module("数字模块名称")
案例:
#写一个模块
#包含一个学生类
#一个sayHello函数
#一个打印语句
class Student():
def __init__(self, name="NoName", age=19):
self.name = name
self.age = age
def intd(self):
print("My name is {0},{1} years old".format(self.name,self.age))
def sayHello():
print("Hi,welcome!")
#此判断语句建议一直作为程序的入口
if __name__ == '__main__':
print("我是模块Student")
模块的搜索路径和存储
什么是模块的搜索路径
加载模块的时候,系统会在哪些地方寻找此模块
系统默认的模块搜索路径
import sys
sys.path 属性可以获取路径列表
案例:
添加搜索路径:
sys.path.append(dir)
模块的加载顺序:
上搜索内存中已经加载好的模块
搜索Python的内置模块
搜索sys.path路径
包:
包是一种组织管理代码的方式,包里面存放的是模块
用于将模块包含在一起的文件夹就是包
自定义包的结构
/---包
/---/---__init__.py 包的标志文件
/---/---模块1
/---/---模块2
/---/---子包(子文件夹)
/---/---/---__init__.py 包的标志文件
/---/---/---子包模块1
/---/---/---子包模块2
包的导入操作:
import package_name
直接导入一个包,可以使用__init__.py中的内容
使用方式是:
package_name:func_name
package_name.class_name.func_name()
Python模块、扩展和应用程序可以按以下几种形式进行打包和发布:
压缩文件(使用distutils):
Windows的zip文件和类Unix平台的.tar.gz文件
自动解包或自动安装可执行文件
Windows中的.exe文件
自包含的,不要求安装的预备运行可执行程序
Windows的.exe文件、Unix上带有一个小的脚本前缀的ZIP压缩文件、Mac上的.app文件等
平台相关的安装程序
Windows上的.msi文件、Linux上常见的.rpm、src.rpm和.deb文件等
Python eggs:
较流行的第三方扩展
distutils模块能够帮助完成模块或程序发布:
“发布”是指一个文件集合,这些文件联合在一起可使用distutils构建、打包和发布模块
创建好的发布可用于安装,也可上传到PyPI与他人共享
创建发布:
将各个代码文件组织到模块容器中
准备一个README或README.txt文件
而后在容器中创建setup.py文件
from distutils.core import setup
setup(
name ='testmod',
version ='0.0.1',
author ='LiFei',
author_email ='
[email protected]'
py_modules =['testmod',...],
url ='http://www.lifei.com',
description ='A simple module.',
)
set.py中setup()中可用参数:
platforms:平台列表
license:许可证
py_modules:各模块名称组成的列表,此些模块可能位于包的根目录下(modname),也可能位于某子包目录中(subpkg1.modname):
packages:各子包名称列表
大体分为两类:元数据信息和包中的内容列表
Python setup.py sdist
可以为sdist指定格式:
zip: zip file
gztar: tar.gz file
bztar: tar.bz2 file
ztar: tar.Z file
tar: tar
Python setup.py bdist
要以为bdist指定的格式:
gztar: tar.gz file
ztar: tar.Z file
tar: tar file
zip: zip file
rpm: RPM Package
pkgtool:Solaris pkgtool
wininst: Windows 上自解压的zip格式的包
msi: Miscrosoft Installer
bdist_dump:
bdist_rpm:
bdist_wininst:
bdist_msi:
获取帮助的方式:
python setup.py --help
pyhton setup.py --help-commands:所有可以使用的命令,如build,install
python setup.py COMMAND --help:获取特定命令的帮助
python setup.py COMMAND --help-formats:获取特定命令支持使用的格式
安装包:
python setup.py install
build and install:
python setup build:
--build-base/path/to/build_dir
lib,lib.platform
第三方模块的默认安装路径通常为:site-packages
C:\\Users\\lee\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages
自定义安装路径:
--user
--prefix
--exec-prefix
深度定制:
--install-purelib /path/to/python_lib
--install-plat/to/plat_lib
--install-lib /path/to/lib
以上三个同时使用时第三个会覆盖前两个
--install-scripts /path/to/lib
可执行文件的安装路径
--install-data
--install-headers
常用模块:
calendar
time
datetime
timeit
os
shutil
zip
math
string
上述所有模块使用理论上都应该先导入,string是特例
calendar(日历),time,datetime(日期时间)的区别参考中文意思
calendar:
跟日历相关的模块
#calendar:获取一年的日历字符创
#参数
#w = 每个日期之间的间隔字符数
#l = 每周所占用的行数
#c = 每个月之间的间隔字符数
cal = calendar.calendar(2018)
print(type(cal))
#print(cal)
cal = calendar.calendar(2018,w=1,l=0,c=10)
print(cal)
#isleap:获取某一年是否闰年
calendar.isleap(2000)
>>>True
#leapdays:获取指定年份之间的闰年的个数
calendar.leapdays(1998,2018)
>>>>5
#mouth():获取某个月的日历字符串
#格式:calendar.month(年,月)
#返回值:月日历的字符串
m3 = calendar.month(2018,3)
print(m3)
#monthrange():获取一个月的周几开始和天数
#格式:calendar.monthrange(年,月)
#返回值:元组(周几开始,总天数)
#注意:周默认0-6表示周一到周日
t = calendar.monthrange(2018,5)
print(t)
#monthcalendar():返回一个月每天的矩阵列表
#格式:calendar.monthcalendar(年,月)
#返回值:二级列表
#注意:矩阵中没有天数用0表示
m = calendar.monthcalendar(2018,5)
print(m)
#prcal:print calendar直接打印日历
c = calendar.prcal
print(type(c))
print(c)
#prmonth():直接打印整个月的日历
#格式:calendar》prmonth(年,月)
#返回值:无
calendar.prmonth(2018,5)
#weekday()获取周几
#格式:calendar.weekday(年,月,日)
#返回值:周几对应的数字
calendar.weekday(2018,5,19)
time模块:
时间戳:
一个时间表示,根据不同语言,可以是整数或者浮点数
是从1970年1月1日0时0分0秒到现在经历的秒数
如果表示的时间是1970年以前或者太遥远的未来,可能出现异常
32位操作系统能支持到2038年
实例:
import time
#时间模块的属性
#timeone:当前时区和UTC时间相差的秒数,在没有夏令时的情况下的间隔,东八区是-28800
#altzone:获取当前时区与UTC时间相差的秒数,在有夏令时的情况下,东八区是-32400
#daylight:测当前是否是夏令时的时间状态
#print(time.timezone)
#print(time.altzone)
#print(time.daylight)
#得到时间戳
#print(time.time())
#localtime,得到当前时间的时间结构
#可以通过点操作得到相应的属性元素的内容
#t = time.localtime()
#print(t)
#asctime():返回元祖的正常字符化之后的时间格式
#格式:time.asctime(时间元组)
#返回值:字符串 Sat May 19 17:53:31 2018
#tt = time.asctime(t)
#print(tt)
#print(type(tt))
#ctime:获取字符串化的当前时间
#t1 = time.ctime()
#print(t1)
#mktime():使用时间元组获取对应的时间戳
#格式:time.mktime(时间元组)
#返回值:浮点数时间戳
#t2 = time.localtime()
#t3 = time.mktime(t2)
#print(t3)
#clock:获取cpu时间,3.0-3.3版本直接使用,3.6调用有问题
#sleep:是程序进入休眠状态,n秒之后继续
#for i in range(10):
# print(i)
# time.sleep(1)
'''def p():
time.sleep(2.5)
t0 = time.clock()
#p()
time.sleep(3)
t1 = time.clock()
print(t1 - t0)'''
#strftime:将时间元组转化为自定义的字符串格式
#把时间表示成 2018 5.19 18:11
t = time.localtime()
ft = time.strftime("%Y%m%d %H:%M", t)
print(ft)
datetime模块:
#datetime模块
#-datetime提供日期和时间的运算和表示
import datetime
#datetime常见属性
#datetime.date: 一个理想化的日期,提供year,month,day属性
'''t = datetime.date(2018,5,19)
print(t)
print(t.year)
print(t.month)
print(t.day)'''
#datetime.time:提供一个理想化的时间,提供hour,minute,second,microsecond等内容
'''t1 = datetime.time(18,39,30,20)
print(t1)
print(t1.hour)
print(t1.minute)
print(t1.second)
print(t1.microsecond)'''
#datetime.datetime:提供日期跟时间的结合
from datetime import datetime
#常用类方法
#today
#now
#utcnow
#fromtimestamp
'''dt = datetime(2018,5,19)
print(dt.today())
print(dt.now())
print(dt.utcnow())'''
#datetime.timedelta:提供一个时间差,时间长度
from datetime import datetime,timedelta
#t3 = datetime.now()
#print(t3)
#print(t3.strftime("%Y-%m-%d %H:%M:%S"))
#t4 = timedelta(hours = 1)
#当前时间加上时间间隔后,把得到的一个小时后的时间格式化输出
#print((t3+t4).strftime("%Y-%m-%d %H:%M:%S"))
#timeit:时间测量工具
#测量程序运行时间间隔实验
'''def p():
time.sleep(3)
t1 = time.time()
p()
print(time.time() - t1)'''
#生成列表两种方法的比较
#如果单纯生成一个列表的时间,可能很难实现
import timeit
'''
c = '''
sum = []
for i in range(1000):
sum.append(i)
'''
#利用timeit调用代码,执行10000次,查看运行时间
t1 = timeit.timeit(stmt="[i for i in range(1000)]",number=10000)
#测量代码c执行10000次运行的结果
t2 = timeit.timeit(stmt=c,number=10000)
print(t1)
print(t2)
'''
#timeit 可以执行一个函数,来测量一个函数的执行时间
'''
f doIt():
num = 3
for i in range(num):
print("Repeat for {0}".format(i))
#执行函数,重复10次
t = timeit.timeit(stmt=doIt,number=10)
print(t)
'''
s = '''
def doIt():
num = 3
for i in range(num):
print("Repeat for {0}".format(i))
'''
#执行doIt(num)
#setup负责把环境变量准备好
#实际相当于给timeit创造了一个小环境
#在创造的小环境中,代码执行的顺序大致是:
#def doIt(num):
# ....
#num = 3
#doIt(num)
t = timeit.timeit("doIt()",setup=s+"num=3",number=10)
print(t)
#os模块-操作系统相关
#主要是文件操作
#和操作系统相关的操作,主要包含三个模块
#-os,操作系统目录相关
#-os.path,系统路径相关操作
#-shutil,高级文件操作,目录树的操作,文件赋值,删除,移动
#-路径:
#-决定路径:总是从根目录上开始
#-相对路径:基本上以当前环境为开始的一个相对的地方
#os模块
#getcwd():获取当前的工作目录
#格式:os.getcwd()
#返回值:当前工作目录的字符串
#当前工作目录就是程序在进行文件相关操作,默认查找文件的目录
'''
import os
mydir = os.getcwd()
print(mydir)
'''
#chdir():改变当前的工作目录
#change directory
#格式:os.chdir(路径)
#返回值:无
'''
os.chdir('C:/Users/lee')
mydir = os.getcwd()
print(mydir)
'''
#listdir():获取一个目录中所有子目录和文件的名称列表
#格式:os.listdir(路径)
#返回值:所有子目录和文件名称的列表
'''
ld = os.listdir()
print(ld)
'''
#makedirs():递归创建文件夹
#格式:os.makedirs(递归路径)
#返回值:无
#递归路径:多个文件夹层层包含的路径就是递归路径,例如:a/b/c...
'''
rst = os.makedirs("liuyifei")
print(rst)
'''
'''
rstr = os.removedirs("liuyifei")
print(rstr)
'''
#system():运行系统shell命令
#格式:os.system(系统命令)
#返回值:打开一个shell或者终端界面
#一般推荐使用subprocess模块代替
'''
rst = os.system("dir")
print(rst)
'''
#getenv():获取指定的系统环境变量值
#格式:os.getenv('环境变量名')
#返回值:指定环境变量名对应的值
'''
rst = os.getenv('PATH')
print(rst)
'''
#值部分
#-os.curdir:current dir:当前目录
#-os.pardir:parent dir:父目录
#-os.sep:当前系统的路径分隔符
#-windows:"\"
#-linux:"/"
#-os.linesep:当前系统的换行符号
#-windows:"\r\n"
#-unix,linux,macos:"\n"
#-os.name:当前系统的名称
#-windows:nt
#-linux,mac,unix:posix
#print(os.curdir)
#print(os.pardir)
#print(os.sep)
#print(os.linesep)
#print(os.name)
#os.path 模块,跟路径相关的模块
import os.path as op
#abspath():将路径转化为绝对路径
#格式:os.path.abspath('路径')
#返回值:路径的绝对路劲形式
#linux中:
#. 点,代表当前路径
#.. 双点,代表父目录
'''
absp = op.abspath(".")
print(absp)
abspf = op.abspath("..")
print(abspf)
'''
#basename():获取路径中的文件名部分
#格式:os.path.basename(路径)
#返回值:文件名字符串
'''
bn = op.basename("C:/Users/lee")
print(bn)
'''
#join():将多个路径拼合成一个路径
#格式:os.path.join(路径1,路径2,...)
#返回值:组合之后的新路径字符串
#bd = "/home/tlxy"
#fn = "dana.haha"
#p = op.join(bd,fn)
#print(p)
#>>>/home/tlxy/dana.haha
#spilt():将路径切割为文件夹部分和当前文件部分
#格式:os.path.spilt(路径)
#返回值:路径和文件名组成的元组
#t = op.split("/home/tlxy/dana.haha")
#print(t)
#>>>('home/tlxy','dana.haha')
#d,p = split("/home/tlxy/dana.haha")
#print(d,p)
#>>>/home/tlxy dana.haha
#isdir():检测是否是目录
#格式:os.path.isdir(路径)
#返回值:布尔值
#rst = op.isdir("C:/Users/lee")
#print(rst)
#>>>True
#rst = op.isdir("Users/lee")
#print(rst)
#>>>False
#exists():检测文件或者目录是否存在
#格式:os.path.exists(路径)
#返回值:布尔值
#e = op.exists("C:/Users/lee")
#print(e)
#>>>True
#e = op.exists("Users/lee")
#print(e)
#>>>False
#shutil模块
import shutil
#copy():复制文件
#格式:shutil.copy(来源路径,目标路径)
#返回值:返回目标路径
#拷贝的同时,可以给文件重命名
#rst = shutil.copy("/home/tlxy/dana.haha","/home/tlxy/haha.haha")
#print(rst)
#>>>/home/tlxy/haha.haha
#copy2():复制文件,保留元数据(文件信息)
#格式:shutil.copy(来源路径,目标路径)
#返回值:返回目标路径
#注意:copy()和copy2()的唯一区别在于copy2复制文件时尽量保留元数据
#copyfile():将一个文件中的内容复制到另外一个文件当中
#格式:shutil.copyfile('源路径','目标路径')
#返回值:无
#rst = shuil,copyfile("dana.haha","haha.haha")
#print(rst)
#>>>haha.haha----->源文件中的内容被写入目标路径文件中
#move():移动文件/文件夹
#格式:shutil.move(源路径,目标路径)
#返回值:目标路径
#rst = shutil.move("/home/tlxy/dana.haha","home/tlxy/dana")
#print(rst)
#>>>/home/tlxy/dana/dana.haha
#归档和压缩
#-归档:把多个文件或者文件夹合并到一个文件当中
#-压缩:用算法把多个文件或者文件夹无损或者有损合并到一个文件当中
#make_archive():归档操作
#格式:shutil.make_archive('归档之后的目录和文件名','后缀','需要归档的文件夹')
#返回值:归档之后的地址
#rst = shutil.make_archive("/home/tlxy/tuling","zip","/home/tlxy/dana")
#print(rst)
#>>>/home/tlxy/tuling.zip
#unpack_archive():解包操作
#格式:shutil.unpack_archive('归档文件地址','解包之后的地址')
#返回值:解包之后的地址
#zip-压缩包
import zipfile
#-模块名称叫做 zipfile
#zipfile.ZipFile(file[,mode[,comression[,allowZip64]]])
#创建一个ZipFile对象,表示一个zip文件。参数file表示文件的路径或类文件对象(file-like object);参数mode指示打开zip文件的模式,默认值为’r’,表示读已经存在的zip文件,也可以为’w’或’a’,’w’表示新建一个zip文档或覆盖一个已经存在的zip文档,’a’表示将数据附加到一个现存的zip文档中。参数compression表示在写zip文档时使用的压缩方法,它的值可以是zipfile. ZIP_STORED 或zipfile. ZIP_DEFLATED。如果要操作的zip文件大小超过2G,应该将allowZip64设置为True。
#zf = zipfile.ZipFile("/home/tlxy/tuling.zip")
#ZipFile.getinfo(name):
#获取zip文档内指定文件的信息。返回一个zipfile.ZipInfo对象,它包括文件的详细信息。
#rst = zf.getinfo("dana.haha")
#print(rst)
#ZipFile.namelist()
#获取zip文档内所有文件的名称列表。
#nl = zf.namelist()
#print(nl)
#>>>['haha.haha','2-oop.ipynb','dana.haha']
#ZipFile.extractall([path[,members[,pwd]]])
#解压zip文档中所有文件到当前目录。参数members的默认值为zip文档内的所有文件名称列表,也可以自己设置,选择要解压的文件名称。
#rst = zf.extractall("/home/tlxy/dana")
#print(rst)
#random
#-随机数
#-所有的随机模块都是伪随机
#random():获取0-1之间的随机小数
#格式:random.random()
#返回值:随机0-1之间的小数(不包括0和1)
import random
import math
#print(int(random.random()*100))
#随机生成0-100之间的整数
'''
ls = []
for i in range(200):
import math
ls.append(math.floor(random.random()*100))
print(ls)
'''
#choice():随机返回序列中的某个值
#格式:random.choice()
#返回值:序列中的某个值
#l = [str(i)+"haha" for i in range(10)]
#print(l)
#rst = random.choice(l)
#print(rst)
#shuffle():随机打乱列表
#格式:random.shuffle(列表)
#返回值:打乱顺序之后的列表
'''
l = [i for i in range(10)]
print(l)
random.shuffle(l)
print(l)
'''
#randint(a,b):返回一个a-b之间的随机整数包含a和b
#print(random.randint(0,100))
Python异常:
Python 的运行时错误成为异常:
语法错误:软件的结构上有错误而导致不能被解释器解释或不能被编译器编译
逻辑错误:由于不完整或不合法的输入所致,也可能是逻辑无法生成、计算或者输出结果需要的过程无法执行等
Python异常时一个对象,表示错误或意外情况:
在Python检测到一个错误是,将触发一个异常:
Python可以通过异常传导机制传递一个异常对象,发出一个异常情况出现的信号
程序员也可以在代码中手动触发异常
Python异常也可以理解为:程序出现了错误而在正常控制流以外采取的行为:
第一阶段:解释器触发异常,此时当前程序流将被打断
第二阶段:异常处理,如忽略非致命性错误、减轻错误带来的影响等
异常的公用:
错误处理:
Python的默认处理,停止程序,答应错误消息
使用try语句处理异常并从异常中恢复
事件通知:
用于发出有效状态信号
特殊情况处理:
无法调整代码去处理的场景
终止行为:
try/finally语句可确保执行必需的结束处理机制
非常规控制流程:
异常时一种高级跳转(C语言的goto)机制
检测通过try语句来检测:
任何在try语句块里的代码都会被监测,以检查有无异常发生
try语句主要有两种形式:
try-except:检测和处理异常
可以有多个except
支持使用else子句处理没有探测异常的执行的代码
try-finally:仅检查异常并做一些必要的清理工作
仅能有一个finally
try语句的复合形式:
try-except-finally
定义了进行异常监控的一段代码,并且提供了处理异常的机制:
语法:
try:
try-suit
except Exception[,reason]
except_suit
例子:
try:
f1 = open('/tmp/a.txt'.'r')
except IOError,e:
print('Could not open file:',e)
try语句可以带有多个except子句,还可以有一个可选的else子句,语法格式如下:
try:
try_suite
except Exception1[,reason]:
suite_exception1
except (Exception2,Exception3,...)[,reason]:
suite_
...
except:
suite_
else:
else_suite
except分句个数没有限制,但else只能有一个
没有异常发生时,else分句才会执行
没有符合的except分句时,异常会向上传递到程序中的之前进入try中或者到进程的顶层(顶层就是解释器)
无论异常是否发生,finally子句都会执行
异常于定义必需进行的清理动作,如关闭文件或断开服务器连接等
finally中的所有代码执行完毕后会继续向上一层引发异常
语法:
try:
try_suite
finally:
finally_suite
例子:
try:
f1 = open('/tmp/a.txt','r')
finally:
f1.close()
Traceback (most recent call last):
File "
",line 3,in
IOError:File not open for writing(关闭文件后继续向上触发异常)
自定义异常(用户手动触发异常):
raise语句可显示触发异常:
raise [SomeException[,args[,tracback]]]
SomeException:可选,异常的名字,仅能使用字符串、类或实例
args:可选,以元组的形式传递给异常参数
tracback:可选,异常触发时新生成的一个用于异常-正常化的跟踪标记录,多用于重新引发异常时
案例:
#异常处理
不能保证程序永远正确运行
但是,必须保证程序在最坏的情况下得到的问题倍妥善处理
Python的异常处理模块全部语法为:
try:
尝试运行的代码
except 异常类型1:
解决方案1:用于尝试在这里处理出现的错误
except 异常类型2:
解决方案2
except 异常类型3:
解决方案3
else:
没有异常,执行的代码
finally:
不管如何都会执行的代码
try:
num = int(input("Plz input your number:"))
rst = 100/num
print("计算结果是{0}".format(rst))
except ZeroDivisionError as e:
print("输入错了")
print(e)
exit()
except NameError as e:
print("名字起错了")
print(e)
exit()
except AttributeError as e:
print("好像属性问题")
print(e)
exit()
except ValueError as e:
print("值错误")
print(e)
exit()
#下面这句话是最后一个错误exception
except Exception as e:
print("我也不知道")
print(e)
else:
print("good!")
finally:
print("牛逼")
#用户手动触发异常
#当某些情况,用户希望自己引发一个异常的时候,可以使用
#raise关键字来引发异常
try:
print("hello!")
print("guys")
#手动引发一个Name异常
#注意语法:raise ErrorClassName
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
#raise
except ValueError as e:
print("ValueError")
except Exception as e:
print("有异常")
else:
print("All right")
finally:
print("I am coming")
#案例2
#自己定义异常
#需要注意:自定义异常必须是系统资产的子类
class FlyNameError(NameError):
pass
try:
print("hello!")
print("guys")
#手动引发一个Name异常
#注意语法:raise ErrorClassName
raise FlyNameError('HiThere')
except NameError:
print('NameError')
#raise
except FlyNameError as e:
print("FlyNameError")
except ValueError as e:
print("ValueError")
except Exception as e:
print("有异常")
else:
print("All right")
finally:
print("I am coming")
实例:
l1=[1,2,3]
l2=[]
def f1(seq1,seq2):
... if not seq1 or not seq2:
... raise ValueError("Seq must be non-empty.")
... print((x,y) for x in seq1 for y in seq2)
...
>>> f1(l1,l2)
Python异常时内置的经典类Exception的子类的实例:
为了向后兼容,Python还允许使用字符串或任何经典类实例
Python2.5之后,Exception是从BaseException继承的新式类
Python自身引发的所有异常都是Exception的子类的实例
大多的标准异常都是由StandardError派生的,其中有3个抽象的子类
ArithmeticError
由于算数错误而引发的异常基类
OverflowError,ZeroDivisionError,FloatingPointError
LookupError:
容器在接受到一个无效键或索引时引发的异常的基类
IndexError,KeyError
EnvironmentError:
由于外部原因而导致的异常的基类
IOError,OSError,WindowsError
标准异常类:
AssertionError:
断言语句失败
AttributeError:
属性引用或赋值失效
IOError:
I/O操作失败
ImportError:
import语句不能找到要导入的模块,或者不能找到该模块特别请求的名称
IndentationError:
解析器遇到了一个由于错误的缩进而引发的语法错误
IndexError:
用来索引序列的整数超出了范围
KeyError:
用来索引映射的键不在映射中
KeyboardInterrupt:
用户按了终端键(Ctrl+c,Ctrl+Break或Delete)
MemoryError:
运算耗尽内存
NameError:
引用了一个不存在的变量名
NotImplementedError:
由抽象基类引发的异常,用于指示一个具体的子类必须覆盖一个方法
OSError:
由模块os中的函数引发的异常,用来指示平台相关的错误
OverflowError:
整数运算的结果太大导致溢出
SyntaxError:
语法错误
SystemError:
Python本身或某些扩展模块中的内部错误
TypeError:
对某对象执行了不支持的操作
UnboundLocalError:
引用为绑定值的本地变量
UnicodeError:
在Unicode的字符串之间进行转换时发生的错误
ValueError:
应用于某个对象的操作或函数,这个对象具有正确的类型,但确有不适当的值
WindowsError:
模块os中的函数引发的异常,用来指示与Windows相关的错误
ZeroDivisionError:
除数为0
自定义异常类:
自定义异常和多重继承:
较有效的方法是从自定义异常类和标准异常类进行多重继承,例如:
class CustomArrtibuteError(CustomException,AttributeError):
pass
标准库中使用的其它异常:
Python标准库中的许多模块都定义了自己的异常类,如socket中的socket,error
等同于自定义的异常类
assert语句:(断言,,,,
assert实现:手动触发异常)
assert语句用于在程序中引入调试代码:
assert condition[,expression]
如果condition条件满足,则assert不做任何操作
如果condition条件不满足,则assert使用expression作为参数实例化AssertionError并引发结果实例
注意:如果运行Python时使用了-O优化选项,则assert将是一个空操作:编译器不为assert语句生成代码
运行Python时不使用-O选项,则__debug__内置变量为True,否则其值为False
assert语句相当于下面的代码:
if __debug__:
if not condition:
raise AssertionError,
Python执行环境:
Python解释器启动:
python[options] [-c cmd| filename | - ] [args]
选项(常用的):
-h :打印所有可用命令选项的列表
-i :在程序执行后进入交互模式
-E :忽略环境变量
-B :阻止在导入时创建.pyc或.pyo文件
-O :优化模式
-OO:优化模式,在创建.pyo文件时删除文档字符串
-m module:以脚本的形式运行库模块module
-v :详细模式,跟踪导入语句
-c cmd:以字符串形式执行cmd
Python解释器环境变量:
PYTHONPATH : 以冒号分割的模块搜索路径
PYTHONHOME : Python安装的位置
PYTHONOPTIMIZE: 相当于-O选项
PYTHONVERBOSE: 相当于-V
PYTHONUSEBASE: 每个用户站点包的根目录
Python代码的测试、调试与探查
Python文档字符串:
如果函数、类或模块的第一行是一个字符串,这个字符串就称为文档字符串(docstrings)
内置函数help()或对象的默认方法__doc__可以显示这些文档字符串
doctest模块:
doctest模块允许在文档字符串内嵌入注释以显示各种语句的期望行为,尤其是函数和方法的结果
此处的文档字符串看起来如同一个交互式shell会话
可用于测试文档是否与程序主体保持同步,或基于文档对程序本身做测试
自定义模块test:
#/usr/bin/python
#
def add(num1,num2):
'''
>>>add(12,43) ---类似与Python会话的文档串
55
'''
return num1 + num2
使用doctest模块进行测试
>>>import test
>>>import doctest
>>>doctest.doctest(test)
TestResults(failed=0,attempted=1)
>>>doctest.testmod(test,verbose=True)
Trying:
add(12,43)
Excepting:
55
ok
1 items had no tests:
test
1 items passed all tests:
1 tests in test.add
1 tests in 2 items.
1 passed and 0 failed.
Test passed.
TestResults(failed=0,attempted=1)
创建可自测试的模块:
在模块的尾部添加如下代码即可:
if __name__ == '__main__':
import doctest
doctest.testmod()
此类模块在Python解释器中直接运行时即能进行自我测试
Python访问MariaDB(或者MySQL):
下载模块MySQLdb —依赖第三方模块—>easy_install
MySQLdb:
This package is a wrapper around _mysql,which mostly imp;ement the MySQL C API
PACKAGE CONTENTS
connections : 建立连接数据库
constants(package) :
converters : 将Python中的字符串转换成MySQL可以操作的数据类型
cursors : 游标
release :
times :
connections:
class Connection(_mysql,connection):
__init__(self,*args,**kwargs): ---->构造器
Create a connection to database
It is strong recommended that you use keyword parameters
host: string,host to connect 主机
user: string,user to connect as 用户名
passwd: string,password to use 密码
db: string,database to use 连接之后把谁当做默认数据库
port:integer,TCP/IP port to conect to 服务器端口
unix_socket: string,location of unix_socket to use
connect_timeout:number of seconds to wait before the connection attempt fails 连接超时
compress: if set,compression is enabled 是不是压缩来实现数据发送
import MySQLdb as mysql
建立连接:
conn mysql.connect(host'',user'',passwd'',db'')
创建游标:
cur conn,cursor()
发送查询:
sqlstatement 'sql statement'
cur.execute(sqlstatement)
cur.execumany(sqlstatement)
获取数据:
cur.execute('select statement')
cur.fetchone()
cur.fetchmany(N)
cur.fetchall()
fetchall():
result cur.fetchall()
关闭:
cur.close()
conn.close()
练习:把/etc/passwd文件中的内容的每一行存储在MySQLdb(或MariaDB)的表中;
Python网络编程:
socket模块:
socket.socket(socket.AF_INET,socket.SOCKET_STREAM)
AF_INET:
AF_UNIX:
socket.socket(family,type)
family
AF_INET:
AF_UNIX:
type:
STREAM:tcp
SOCK_DGRAM:udp
tcpconn socket.socket(socket.AF_INET,socket.SOCKET_STREAM)
第二步:绑定地址
使用套接字对象的bind发放绑定于某地址和端口
tcpconn.bind('ip',port)
tcpconn.bind((172.16.100.6',8023))
第三步:使用listen方法进行监听状态
tcpconn.listen(backlog)
tcpconn.listen(100)
第四步:循环监听状态
使用套接字对象的accept方法接受用户需求,
编写客户端程序:
第一步:创建一个socket对象,以连接服务器端:
clientsock socket.socket(socket.AF_INET,socket.SOCK_ATREAM)
第二步:连接至服务器:
clientsock.connet(('server_ip',server_port))
clientsock.connet((''172.16.100.7',8023))
第三步:发送请求:
clientsock.send()
服务器端:
import socket
s socket.socket(socket.af_inet,seckie.SOCK_STREAM)
sa ('172.16.100.7',8023)
s.bind(sa)
s.listen(20)
while True:
cinfo,caddr s.accept()
print("Got a connection from %s" %caddr[0])
data cinfo.recv(1-1024)
print("Receive data:%s"%data)
cinfo.send("echo:"+data)
cinfo.close()
客户端:
import socket
c socket.socket(socket.AF_INET,socket.SOCK_STREAM)
saddr ('172.16.100.7',8023)
c.connect(saddr)
c.send('hello server')
data c.recv(1024)
print("Reply from server %s" %data)
web框架:
Django
Flask
Web2py
TuborGears
函数式编程:
#Python语言的高级特性
#-函数式编程(FunctionalProgramming)
#-基于lambda演算的一种编程方式
#-程序中只有函数
#-函数可以作为参数,同样可以作为返回值
#-纯函数是编程语言:LISP,Haskell
#-Python函数式编程只是借鉴函数时编程的一些特点,可以理解成一半函数时一半Python
#需要讲述:
#高阶函数
#返回函数
#匿名函数
#装饰器
#偏函数
#lambda表达式
#函数:最大程度复用代码
#存在问题:如果函数很小,很短,则会造成啰嗦
#如果函数被调用次数少,则会造成浪费
#对于阅读者来说,造成阅读流程的被迫中断
#-lambda表达式(匿名函数):
#一个表达式,函数体相对简单
#不是代码块,仅仅是一个表达式
#可以有参数,有多个参数也可以,用逗号隔开
#“小”函数举例
'''
def printA():
print("AAAAAA")
printA()
'''
#lambda表达式的用法
#1.以lambda开头
#2.紧跟一定的参数(如果有的话)
#3.参数后用冒号和表达式主体隔开
#4.只是一个表达式,所以,没有return
#计算一个数字的100倍数
#因为就是一个表达式,所以没有return
#使用上和普通函数一模一样
stm = lambda x:100 * x
stm(44)
stm2 = lambda x,y,z:x+ y*10+ z*100
stm(11)
###高阶函数
#-把函数作为参数使用的函数,就是高阶参数
a = 100
b = a
#函数名就是一个变量
'''
def funA():
print("In funA")
funB = funA
funB()
'''
###以上代码得出结论:
#-函数名称是变量
#-funB 和 funA只是名称不一样而已
#既然函数名称是变量,则应该可以被当成参数传入另一个函数
#高阶函数举例
#funA是普通函数,返回一个传入数字的100倍数字
'''
def funA(n):
return n * 100
#再写一个函数,把传入参数乘以300,
def funB(n):
#最终是想返回300n
return funA(n) * 3
#print(funB(9))
#写一个高阶函数
def funC(n,f):
#假定函数是把n扩大300倍
return f(n) * 3
print(funC(9,funA))
#比较funC和funB,显然funC的写法要优于funB
#例如
def funD(n):
return n*10
#需求变更,需要把n放大30倍,此时funB则无法实现
print(funC(7,funD))
'''
###系统高阶函数-map
#-原意就是映射,即把集合或者列表的元素,每一个元素都按照一定的规则进行操作,生成一个新的集合
#-map函数时系统提供的具有映射功能的函数,返回值是一个迭代对象
'''
l1 = [i for i in range(10)]
print(l1)
l2 = []
for i in l1:
l2.append(i*10)
print(l2)
#利用map实现
def mulTen(n):
return n*10
l3 = map(mulTen,l1)
#map 类型是一个可迭代的数据结构,所以可以使用for遍历
for i in l3:
print(i)
#以下列表生成式得到的结果为空,why?
###-因为上面的for循环以及遍历了一次,指针已经走到尾部去了,所以,当下面的l4中再次使用for循环遍历l3的时候,就为空了
l4 = [i for i in l3]
print(l4)
print(type(l3))
print(type(l1))
'''
#reduce
#--原意就是归并,缩减
#--把一个可迭代对象最后归并为一个结果
#--对于函数参数要求,必须由两个参数,必须有返回结果
#reduce([1,2,3,4,5])==f(f(f(f(1,2),3),4),5)
#reduce需要导入functools包
'''
from functools import reduce
#定义一个操作函数
#加入操作函数只是相加
def myAdd(x,y):
return x + y
#对于列表[1,2,3,4,5,6]执行myAdd的reduce操作
rst = reduce(myAdd,[1,2,3,4,5,6])
print(rst)
'''
#filter 函数
#-过滤函数:对一组数据进行过滤,符合条件的数据会生成一个新的列表并返回
#-和map相比较:
#-相同:都对列表的每一个元素逐一进行操作
#-不同:
#-map会生成一个跟原来数据相对应的新列表
#-filter不一定,只要符合条件的才会进入新的数据集合
#-filter函数怎么写:
#-利用给定的函数进行判断
#-返回值一定是个布尔值
#-调用格式:filter(f,data),f是过滤函数,data是数据
#案例
#对于一个列表,对其进行过滤,偶数组成一个新的列表
#需要定义一个过滤函数
#过滤函数需要有输入,返回布尔值
'''
def isEven(a):
return a % 2 == 0
l = [1,2,3,4,5,6,7,8,9,54]
rst = filter(isEven,l)
#返回的filter内容是一个可迭代对象
print(type(rst))
print(rst)
print([i for i in rst])
'''
#高阶函数-排序
#-把一个序列按照一个给定的算法进行排序
#-key:在排序前对每一个元素进行key函数运算,可以理解为按照key函数定义的逻辑进行排序
#-Python2和Python3相差巨大
#排序案例
'''
a = [1,2,3,4,5,6,223,432,545]
a1 = sorted(a,reverse = True)
print(a1)
'''
#排序案例2
'''
a = [-32,43,54,2,-43,5,-432]
#按照绝对值进行排序
a1 = sorted(a,key = abs, reverse = True)
print(a1)
'''
#sorted案例
'''
astr = ['ad','fdf','gdfg','hhd','tgaggfdw','opjajj']
str1 = sorted(astr)
print(str1)
str2 = sorted(astr,key = str.lower)
print(str2)
'''
#返回函数
#-函数可以返回具体的值
#-也可以返回一个函数作为一个结果
'''
def myF(a):
print('In myF')
return None
a = myF(8)
print(a)
'''
#函数作为返回值返回,被返回的函数在函数体内定义
'''
def myF2():
def myF3():
print("In myF3")
return 3
return myF3
#使用上面定义
#调用myF2,返回一个函数myF3,赋值给f3
f3 = myF2()
print(type(f3))
print(f3)
f3()
'''
#返回函数例子
#args:参数列表
#1.myF4定义函数,返回内部定义的函数myF5
#2.myF5使用了外部变量,这个变量是myF4的参数
'''
def myF4(*args):
def myF5():
rst = 0
for n in args:
rst += n
return rst
return myF5
f5 = myF4(1,2,3,4,5,6,7,8,9)
#f5的调用方式
f5()
'''
#闭包(closure)
#-当一个函数在内部定义函数,并且内部的函数应用外部函数的参数或者局部变量,当内部函数被当做返回值的时候,相关参数和变量保存在返回的函数中,这种结果,叫闭包
#-上面定义的myF4是一个闭包结构
#闭包常见的坑:
'''
def count():
#定义列表
fs = []
for i in range(1,4):
def f():
return i * i
fs.append(f)
return fs
f1,f2,f3 = count()
print(f1())
print(f2())
print(f3())
>>>9
>>>9
>>>9
###出现的问题:
#-造成上述状况的原因是,返回函数引用了变量i,i并非立即执行,而是等到单个函数都返回的时候才统一使用,此时i已经变成了3,最终调用的时候,都返回的是3*3
#-此问题描述成:返回闭包时,返回函数不能引用任何循环变量
#-解决方案:在创建一个函数,用该函数的参数绑定循环变量的当前值,无论该循环变量以后如何改变,已经绑定的函数参数值不能再改变
#修改上述函数:
def count2():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3 = count2()
print(f1())
print(f2())
print(f3())
'''
#装饰器
#普通函数
def hello():
print("Hello world!")
hello()
f = hello
f()
#f和hello是一个函数
print(id(f))
print(id(hello))
print(f.__name__)
print(hello.__name__)
#现在有新的需求
#对hello功能进行扩展,每次打印hello之前打印当前系统的时间
#而实现这个功能又不能改动现有代码
#==>使用装饰器
###装饰器(Decrator)
#-在不该懂函数代码的基础上无限扩展函数功能的一种机制,本质上讲,装饰器是一个返回函数的高阶函数
#-装饰器的使用:使用@语法,即在每一次要扩展到函数定义前使用@+函数名
#任务:
#对hello函数进行功能扩展,每次执行hello打印当前时间
import time
'''
#高阶函数,以函数作为参数
def printTime(f):
def wrapper(*args,**kwargs):
print("Time:",time.ctime())
return f(*args,**kwargs)
return wrapper
#上面定义了装饰器,使用的时候需要用到@,此符号是Python的语法塘
@printTime
def hello():
print("Hello world")
hello()
#装饰器的好处是,一旦定义,就可以装饰任意函数
#一旦被其装饰,则把装饰器的功能直接添加到定义函数的功能上
@printTime
def hello2():
print("你好,飞飞")
print("你好,菲菲")
hello2()
'''
'''
#上面对函数的转十圈使用了系统定义的语法塘
#下面开始手动执行下装饰器
def hello3():
print("我是手动执行的")
hello3()
hello3 = printTime(hello3)
hello3()
f = printTime(hello3)
f()====>Time: Sat May 26 19:14:52 2018
Time: Sat May 26 19:14:52 2018
我是手动执行的
#解释为什么上面f()的执行结果是这样的?
###因为这里的hello3已经不是自定义函数hello3,而是前面被赋值的hello3
'''
###偏函数
#把字符串转化成十进制数字
int("12345")
#求八进制的字符串12345,表示成十进制的数字是多少
int("12345",base=8)
#新建一个函数,此函数是默认输入的字符串是16进制数字
#把此字符串返回十进制的数字
'''
def int16(x,base=16):
return int(x,base)
int16("12345")
##偏函数
#-参数固定的函数,相当于一个由特定参数的函数体
#-functools.partial的作用是,把一个函数某些参数固定,返回一个新函数
import functools
#实现上面int16的功能
int16 = functools.partial(int,base=16)
int16("12345")
'''
#高级函数补充
#zip
#-把两个可迭代内容生成一个可迭代的tuple元素类型组成的内容
'''
#案例1
l1 = [1,2,3,4,5]
l2 = [11,22,33,44,55]
z = zip(l1,l2)
print(type(z))
print(z)
for i in z:
print(i)
'''
'''
#案例2
l1 = ["liuyifei","lifei","liangchaowei"]
l2 = [99,100,98]
z = zip(l1,l2)
#for i in z:
# print(i)
l3 = [i for i in z]
print(l3)
'''
#enumerate
#-跟zip功能比较像
#-对可迭代对象里的每一个元素,配上一个索引,然后索引和内容构成tuple类型
'''
#案例1
l1 = [11,22,33,44,55]
em = enumerate(l1)
l2 = [i for i in em]
print(l2)
em1 = enumerate(l1,start = 100)
l2 = [i for i in em1]
print(l2)
'''
#collections模块
#-namedtuple
#-deque
####namedtuple
#-tuple类型
#-是一个可命名的tuple
'''
import collections
Point = collections.namedtuple("Point",['x','y'])
p = Point(11,22)
print(p.x)
print(p[0])
print(p.y)
print(p[1])
Circle = collections.namedtuple("Circle",['x','y','r'])
c = Circle(100,150,50)
print(c)
print(type(c))
#检测一下namedtuple属于谁的子类
isinstance(c,tuple)
'''
'''
#deque
#比较方便的解决了频繁删除插入带来的效率问题
from collections import deque
q = deque(['a','b','c'])
print(q)
q.append("d")
print(q)
q.appendleft("x")
print(q)
'''
#defaultdict
#-当直接读取dict不存在的属性时,直接返回默认值
'''
d1 = {"one":1,"two":2,"three":3}
print(d1['one'])
print(d1['two'])
from collections import defaultdict
func = lambda:"李飞"
d2 = defaultdict(func)
d2["one"] = 1
d2["two"] = 2
print(d2["one"])
print(d2["three"])
'''
#counter
#统计字符串个数
'''
from collections import Counter
#为什么下面的结果不把字符串作为键值,而是以其中的每一个字母作为键值
#这是因为需要括号里的内容为可迭代
c = Counter("fdagajeriourtioewja fvcnmvaijtiewtam")
print(c)
s = ["feifei","love","liuyifei"]
c1 = Counter(s)
print(c1)
'''
调试技术
-调试流程:单元测试->集成测试->交测试部
-分类
-静态调试:
-动态调试:
#pdb调试
-【官网】(https://docs.python.org/2/library/pdb.html)
-【pdb模块介绍】(https://blog.csdn.net/carolzhang8406/article/details/6923997)
-【pdb调试技巧】(https://www.ibm.com/developerworks/cn/linux/l-cn-pythondebugger/)
-简单实用的介绍,推荐优先阅读
-【pdb详细中文介绍】(https://blog.csdn.net/wyb_009/article/details/8896744)
-主要是帮助文件的中文翻译
-【案例调试01】(https://www.cnblogs.com/dkblog/archive/2010/12/07/1980682.html)
-【调试案例02】(http://python.jobbole.com/81184)
-pdb:python 调试库
#单元测试
-推荐文档
-【官方测试文档集合】https://wiki.python.org/moin/PythonTestingToolsTaxonomy)
-【测试案例01】(http://blog.csdn.net/a542551042/article/details/46696635)
-【PyUnit】(https://wiki.python.org/moin/PyUnit)
-【PyUnit详细讲解案例02】(http://www.jb51.net/article/64119.htm)
-【测试案例03】(https://www.cnblogs.com/iamjqy/p/7155315.html)
#持久化-文件
#文件
#-长久保存信息的一种数据信息集合
#-常用操作
#-打开关闭文件(文件一旦打开,需要关闭操作)
#-读写内容
#-查找
#open函数
#-open函数负责打开文件,带有很多参数
#-第一个参数,必须有,文件的路径和名称
#-mode:表明文件用什么方式打开
#-r:只读方式打开
#-w:写的方式打开,会覆盖以前的内容
#-x:创建方式打开,如文件已经存在,报错
#-a:append方式,以追加的方式对文件内容进行写入
#-b:binary方式,二进制方式写入
#-t:文本方式打开
#-+:可读写
#打开文件,用写的方式
#r表示后面的字符串内容不需要转义
#f称之为文件句柄
f = open(r"test01.txt",'w')
#文件打开后必须关闭
f.close()
#此案例说明,以写方式打开文件,默认是如果没有文件,则创建
#with语句
#-with语句使用的技术是一种成为上下文管理协议的技术(ContextManagementProtocal)
#-自动判断文件的作用域,自动关闭不在使用的文件句柄
#with语句案例
with open(r"test01.txt","r") as f:
pass
#下面语句块开始对文件f进行操作
#在本模块中不需要再使用close关闭文件f
#with案例
with open(r"test01.txt",'r') as f:
#按行读取内容
strline = f.readline()
#次结构保证能够完成读取文件直到结束
while strline:
print(strline)
strline = f.readline()
#list能用打开的文件作为参数,把文件内每一行内容作为一个元素
with open(r"test01.txt",'r') as f:
#以打开的文件f作为参数,创建列表
l = list(f)
for line in l:
print(line)
#read 是按字符读取文件内容
#允许输入参数决定读取几个字符,如果没有指定,从当前位置读取到结尾
#否则,从当前位置读取指定个数字符
with open(r"test01.txt", 'r') as f:
strChar = f.read()
print(len(strChar))
print(strChar)
#作业:
#使用read读取文件,每次读取一个,使用循环读完
#尽量保持格式
#作业答案:
with open(r"test01.txt", 'r') as f:
strChar = f.read(1)
while strChar:
print(strChar)
strChar = f.read(1)
#print(len(strChar))
#print(strChar)
#seek(offset, from)
#-移动文件的读取位置,也叫读取指针
#-from的取值范围:
#-0:从文件开头开始便宜
#-1:从文件当前位置开始便宜
#-2:从文件末尾开始偏移
#-移动的单位是字节(byte)
#返回文件指针当前的位置
#seek案例
#打开文件后,从第五个字节开始读取
with open(r"test01.txt","r") as f:
#seek 移动单位是字节
f.seek(4,0)
strChar = f.read()
print(strChar)
#关于读取文件的练习
#打开文件,三个字符一组独处内容,然后显示在屏幕上
#每读取一次,休息一秒钟
#让程序暂停,可以使用time下的sleep函数
import time
with open(r"test01.txt","r") as f:
strChar = f.read(3)
while strChar:
print(strChar)
#sleep参数单位是秒
time.sleep(1)
strChar = f.read(3)
#tell函数:用来显示文件读写指针的当前位置
with open(r"test01.txt","r") as f:
strChar = f.read(3)
pos = f.tell()
while strChar:
print(pos)
print(strChar)
strChar = f.read(3)
pos = f.tell()
#文件的写操作-write
#-write(str):把字符串写入文件
#writelines(str):把字符串按行写入文件
#-区别:
#-write函数参数只能是字符串
#-WriteLine参数可以是字符串,也可以是字符序列
#write案例
#1.向文件追加一句话
#a代表追加方式打开
with open(r"test01.txt","a") as f:
f.write("\nliuyifei\nlifei")
#可以直接写入行,用writeline
#writelines表示写入很多行,参数可以是list格式
with open(r"test01.txt","a") as f:
f.writelines("\nI love you")
f.writelines("\nliuyifei")
l = ["I", "love", "liuyifei"]
with open(r"test01.txt", "a") as f:
f.writelines(l)
#持久化-pickle
#-序列化(持久化,落地):把程序运行中的信息保存在磁盘上
#-反序列化:序列号的逆过程
#-pickle:Python提供的序列化模块
#-pickle.dump:序列化
#-pickle.load:反序列化
#序列化案例:
import pickle
age = 19
with open(r"test01.txt","wb") as f:
pickle.dump(age, f)
#反序列化案例
with open(r"test01.txt", "rb") as f:
age = pickle.load(f)
print(age)
#序列化案例
import pickle
a = [19, "lifei", "I love liuyifei", [175,55]]
with open(r"test01.txt","wb") as f:
pickle.dump(a, f)
with open(r"test01.txt", "rb") as f:
a = pickle.load(f)
print(a)
#持久化-shelve
#-持久化工具
#-类似字典,用kv对保存数据,存取方式和字典也类似
#-open,close
#使用shelve创建文件并使用
import shelve
#打开文件
#shv相当于一个字典
shv = shelve.open(r"shv.db")
shv["one"] = 1
shv["two"] = 2
shv["three"] = 3
shv.close()
#通过以上案例发现,shelve自动创建的不仅仅是一个shv.db文件,还包括其他格式文件
#shelve读取案例
shv = shelve.open(r"shv.db")
print(shv["one"])
print(shv["three"])
shv.close()
#shelve特性
#-不支持多个应用并行写入
#-为了解决这个问题,open的时候可以使用flag=r
#写回问题
#shelve默认情况下不会等待持久化对象进行任何修改
#解决方法:强制写会:writeback=True
#shelve 只读方式打开
import shelve
shv = shelve.open(r"shv.db", flag="r")
try:
k1 = shv["one"]
print(k1)
finally:
shv.close()
import shelve
shv = shelve.open(r"shv.db")
try:
shv["one"] = {"eins":1, "zwei":2, "dreri":3}
finally:
shv.close()
shv = shelve.open(r"shv.db")
try:
one = shv["one"]
print(one)
finally:
shv.close()
#shelve忘记写回,需要强制写回
'''
import shelve
shv = shelve.open(r"shv.db")
try:
k1 = shv["one"]
print(k1)
#此时,一旦shelve关闭,则内容还是存在于内存中,没有写回数据库
k1["eins"] = 100
finally:
shv.close()
import shelve
shv = shelve.open(r"shv.db")
try:
k1 = shv["one"]
print(k1)
finally:
shv.close()
'''
#改进
import shelve
shv = shelve.open(r"shv.db", writeback=True)
try:
k1 = shv["one"]
print(k1)
#此时,一旦shelve关闭,则内容还是存在于内存中,没有写回数据库
k1["eins"] = 100
finally:
shv.close()
import shelve
shv = shelve.open(r"shv.db")
try:
k1 = shv["one"]
print(k1)
finally:
shv.close()
#shelve 使用with管理上下文环境
with shelve.open(r"shv.db", writeback=True) as shv:
k1 = shv["one"]
print(k1)
#此时,一旦shelve关闭,则内容还是存在于内存中,没有写回数据库
k1["eins"] = 1000
with shelve.open(r"shv.db") as shv:
print(shv["one"])