Python基础知识
数据类型
计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种:
- 整数
Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等。
计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用0x前缀和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。
- 浮点数
浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,$1.23 \times 10^9$和$12.3 \times 10^8$是完全相等的。浮点数可以用数学写法,如1.23,3.14,-9.01,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,$1.23 \times 10^9$就是$1.23\times e^9$,或者$12.3\times e^8$,0.000012可以写成$1.2\times e^{-5}$,等等。
整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
- 字符串
字符串是以单引号’或双引号”括起来的任意文本,比如’abc’,”xyz”等等。请注意,’’或””本身只是一种表示方式,不是字符串的一部分,因此,字符串’abc’只有a,b,c这3个字符。如果’本身也是一个字符,那就可以用””括起来,比如”I’m OK”包含的字符是I,’,m,空格,O,K这6个字符。
1 | import sys |
a is type <class 'int'>
c is type <class 'float'>
e is type <class 'complex'>
g is type <class 'str'>
运算符
Python语言支持以下类型的运算符:
- 算术运算符
- 比较(关系)运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
算术运算符

1 | # coding=utf-8 |
3
Nicework
1
6
hellohello
4.5
4.5
4.5
3
1
0
10
8
比较(关系)运算符

1 | #小于符号,返回值是bool值 |
True
False
True
False
True
False
赋值运算符

1 | #!/usr/bin/python |
1 - c 的值为: 31
2 - c 的值为: 52
3 - c 的值为: 1092
4 - c 的值为: 52.0
5 - c 的值为: 2
6 - c 的值为: 2097152
7 - c 的值为: 99864
逻辑运算符

1 | #逻辑非 not |
False
True
True
False
位运算符

1 | #按位与运算&, 按位与是指一个数字转化为二进制,然后这些二进制的数按位来进行与运算 |
2
23
21
-13
24
24
6
3
成员运算符

1 | #!/usr/bin/python |
1 - 变量 a 不在给定的列表中 list 中
2 - 变量 b 不在给定的列表中 list 中
3 - 变量 a 在给定的列表中 list 中
身份运算符

1 | #!/usr/bin/python |
1 - a 和 b 有相同的标识
2 - a 和 b 有相同的标识
3 - a 和 b 没有相同的标识
4 - a 和 b 没有相同的标识
运算符优先级

容器
本文整理几种基本容器:
- 列表(list)
- 元组(tuple)
- 字典(dict)
- 集合(set)
列表
list是一种有序的集合,可以随时添加和删除其中的元素。
1 | # 初始化列表 |
7
1
abc
{1: 'one'}
4.5
[1, 2, 3, 'a', 'b']
[1, 2, 3, 'a', 'b', [4, 5, 6]]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4]
[2, 4]
True
False
Empty
['a', 'b', 'c', 'd', 'E', 'F', 'g']
abcdEFg
1
2
3
1
2
3
元组
另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改。
其中需要注意的是:tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。
1 | #创建 tuple |
number_tuple: (1, 3, 5, 7, 9)
9
string_tuple: ('adc', 'sdf', 'python')
sdf
mixed_tuple: ('python', 1, 5)
python
a:5
b:sdf
c:python
b
c
('b', 'c', 'd')
mix_tuple: (1, 2, ['a', 'b'])
mix_tuple: (1, 2, ['c', 'd'])
mix_list: [1, 2, ('a', 'b')]
mix_list: [1, 2, ('c', 'd')]
1
2
3
1
2
3
字典
字典由keys(键)和values(值)组成。字典的每个键值(key=>value)对,用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中.键必须是唯一的,但值则不必。值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。
1 | # 初始化 |
{'a': 1, 2: 'b', 'c': 3, 4: 'd'}
dict_keys(['a', 2, 'c', 4])
dict_values([1, 'b', 3, 'd'])
4
{'a': 100, 2: 'b', 'c': 3, 4: 'dd'}
{'a': 100, 2: 'b', 'c': 3, 4: 'dd', 'e': 5, 6: 'f'}
{'c': 3, 4: 'd'}
a in d
2 in d
x not in d
d is empty
a: 1
2: b
c: 3
4: d
a: 1
2: b
c: 3
4: d
集合(set)
set是基本数据类型的一种集合类型,它有可变集合(set())和不可变集合(frozenset)两种。创建集合set、集合set添加、集合删除、交集、并集、差集的操作都是非常实用的方法。
1 | # 初始化 |
{1, 2, 3, 4, 5}
{1, 2, 3, 4, 5}
5
5
{1, 2, 3, 4, 5, 6, 7, 8, 9}
{1, 2, 3, 4, 5, 6, 7}
True
False
set is empty
1
2
3
4
5
{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3, 4, 5, 6, 7, 8}
{4, 5}
{4, 5}
{1, 2, 3}
{1, 2, 3}
{1, 2, 3, 6, 7, 8}
{1, 2, 3, 6, 7, 8}
{1, 2, 3, 6, 7, 8}
判断
1 | number = 59 |
Enter an integer:58
guess is 58
the number is higher than that
Done!
循环
for
1 | for i in range(1,5): |
1
2
3
4
the for loop is over
1
3
5
7
9
1
3
5
7
9
Tom
111
Jerry
222
Cathy
333
Tom 111
Jerry 222
Cathy 333
you have only 3 chances to guess
chace1
Enter an integer:57
the number is higher than that,you have only 2chance!
chace2
Enter an integer:58
the number is higher than that,you have only 1chance!
chace3
Enter an integer:59
you are right!
while
1 | number = 59 |
Enter an integer:1
guess is: 1
the number is higher than that
Enter an integer:2
guess is: 2
the number is higher than that
Enter an integer:3
guess is: 3
the number is higher than that
Enter an integer:59
guess is: 59
you are right!
Done!
break && continue && pass
1 | #break && continue example |
函数
1 | #默认参数(放在函数参数末尾) |
面型对象(初级篇)
面向对象的三大特性是指:封装、继承和多态。
封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
- 将内容封装到某处
- 从某处调用被封装的内容
第一步:将内容封装到某处
self 是一个形式参数,
当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1
当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象obj1和obj2中,每个对象中都有name和age属性,在内存里类似于下图来保存。
第二步:从某处调用被封装的内容
调用被封装的内容时,有两种情况:
- 通过对象直接调用
- 通过self间接调用
1、通过对象直接调用被封装的内容
上图展示了对象obj1和obj2在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
1 | class Foo: |
wupeiqi
18
alex
73
2、通过self间接调用被封装的内容
执行类中的方法时,需要通过self间接调用被封装的内容
1 | class Foo: |
wupeiqi
18
alex
73
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。
继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。
例如:
猫可以:喵喵叫、吃、喝、拉、撒
狗可以:汪汪叫、吃、喝、拉、撒
如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:
1 | class 猫: |
上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:
动物:吃、喝、拉、撒
猫:喵喵叫(猫继承动物的功能)
狗:汪汪叫(狗继承动物的功能)
1 | class 动物: |
1 | #!/usr/bin/python |
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

1 | class Animal: |
那么问题又来了,多继承呢?
- 是否可以继承多个类
- 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?
1、Python的类可以继承多个类,Java和C#中则只能继承一个类
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
1 | # 经典类多继承 |
A.bar
1 | # 新式类多继承 |
A.bar
经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
多态
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。
1 | # Python伪代码实现Java或C#的多态 |
1 | # Python “鸭子类型” |
以上就是本节对于面向对象初级知识的介绍,总结如下:
面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用
类是一个模板,模板中包装了多个“函数”供使用
对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
面向对象三大特性:封装、继承和多态
面型对象(高级篇)
将详细介绍Python类的成员、成员修饰符、类的特殊成员。
类的成员
类的成员可以分为三大类:字段、方法和属性
注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。
字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,
- 普通字段属于对象
- 静态字段属于类
1 | #字段的定义和访问 |
河北省
'中国'
由上述代码可以看出普通字段需要通过对象来访问,静态字段通过类访问,在使用上可以看出普通字段和静态字段的归属是不同的。其在内容的存储方式类似如下图:
由上图表示:
- 静态字段在内存中只保存一份
- 普通字段在每个对象中都要保存一份
应用场景:通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
方法
方法包括:普通方法、类方法、静态方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
- 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
- 静态方法:由类调用;无默认参数;
1 | #方法的定义和使用 |
普通方法
类方法
静态方法

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
属性
如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。
对于属性,有以下三个知识点:
- 属性的基本使用
- 属性的两种定义方式
1、属性的基本使用
1 | # 属性的定义和使用 |
由属性的定义和调用要注意一下几点:
- 定义时,在普通方法的基础上添加 @property装饰器;
定义时,属性仅有一个self参数
调用时,无需括号方法:foo_obj.func() 属性:foo_obj.prop注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
- 根据用户请求的当前页和总数据条数计算出 m 和 n
- 根据m 和 n 去数据库中请求数据
1 | # ############### 定义 ############### |
0
10
从上述可见,Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回。
2、属性的两种定义方式
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器
- 静态字段 即:在类中定义值为property对象的静态字段
装饰器方式:在类的普通方法上应用@property装饰器
我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )
- 经典类,具有一种@property装饰器(如上一步实例)
1 | # ############### 定义 ############### |
'xuke'
- 新式类,具有三种@property装饰器
1 | # ############### 定义 ############### |
@property
@price.setter
@price.deleter
注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
1 | # 实例 |
静态字段方式,创建值为property对象的静态字段
当使用静态字段的方式创建属性时,经典类和新式类无区别
1 | class Foo: |
xuke
property的构造方法中有个四个参数
- 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
- 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
- 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
- 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
1 | class Foo: |
由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
1 | # 实例 |
所以,定义属性共有两种方式,分别是【装饰器】和【静态字段】,而【装饰器】方式针对经典类和新式类又有所不同。
成员修饰符
类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式:
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
1 | class C: |
私有成员和公有成员的访问限制不同:
静态字段
- 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
- 私有静态字段:仅类内部可以访问;
1 | # 公有静态字段 |
公有静态字段
公有静态字段
1 | 私有静态字段 |
普通字段
- 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
- 私有普通字段:仅类内部可以访问;
1 | # 公有字段 |
1 | # 私有字段 |
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用
类的特殊成员
上文介绍了Python的类成员以及成员修饰符,从而了解到类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。无论人或事物往往都有不按套路出牌的情况,Python的类成员也是如此,存在着一些具有特殊含义的成员,详情如下:
1、 __doc__
表示类的描述信息
1 | class Foo: |
类的描述信息
2、 __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
1 | #!/usr/bin/env python |
1 | from lib.aa import C |
3、 __init__
构造方法,通过类创建对象时,自动触发执行。
1 | class Foo: |
4、 __del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
1 | class Foo: |
5、__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
1 | class Foo: |
6、__dict__
类或对象中的所有成员
上文中我们知道:类的普通字段属于对象;类中的静态字段和方法等属于类,即:
1 | class Province: |
7、__str__
如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
1 | class Foo: |
8、__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
1 | #!/usr/bin/env python |
9、__getslice__、__setslice__、__delslice__
该三个方法用于分片操作,如:列表
1 | #!/usr/bin/env python |
10、__iter__
用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
1 | # 第一步 |
1 | # 第二步 |
1 | # 第三步 |
以上步骤可以看出,for循环迭代的其实是 iter([11,22,33,44]) ,所以执行流程可以变更为:
1 | #!/usr/bin/env python |
1 | # For循环语法内部 |
11、__new__ 和 __metaclass__
阅读以下代码:
1 | class Foo(object): |
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
1 | print (type(obj)) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建 |
所以,obj对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a). 普通方式
1 | class Foo(object): |
b).特殊方式(type类的构造函数)
1 | def func(self): |
因此 类是由type类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
1 | class MyType(type): |
异常处理
1 | while True: |
please enter a numberABC
Not valid input , try again...
please enter a number123
OS error :[Errno 2] No such file or directory: 'myfile.txt'
文件读写
1 | some_sentences = '''\ |
i love learing python
because python is fun
and also easy to use
json处理
1 | import json |
{"Python": 100, "C++": 70, "Basic": 60, "others": {"C": 65, "Java": 50}}
{'Python': 100, 'C++': 70, 'Basic': 60, 'others': {'C': 65, 'Java': 50}}
100
非dict对象如何用json序列化?
1 | class Student: |
Tom: 15, 85
{'name': 'Tom', 'age': 15, 'score': 85}
- 方法1
1 | jtxt = json.dumps(s, default = lambda obj: obj.__dict__) |
{"name": "Tom", "age": 15, "score": 85}
Tom: 15, 85
- 方法2
1 | def s2d(s): |
{"name": "Tom", "age": 15, "score": 85}
Tom
参考
廖雪峰Python教程(https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000)
Python 运算符 (http://www.runoob.com/python/python-operators.html#ysf6)
Python面向对象(初级篇)(http://www.cnblogs.com/wupeiqi/p/4493506.html)
Python面向对象(高级篇)(http://www.cnblogs.com/wupeiqi/p/4766801.html)