简介
Python 是一个高层次的结合了解释性、交互性和面向对象的脚本语言。解释型语言: 这意味着开发过程中没有了编译这个环节。作为解释型语言,意味着开发过程中没有了编译这个环节,对代码逐行解析。
Python还具有可嵌入性,如Python无法运行的代码可以使用C或C++完成程序,然后从的Python程序中调用。也提供了数据库接口和GUI编程。
Python作为解释性语言,内核时Python解析器,任何安装了解析器的系统都可以运行Python文件。
基础语法
标识符
Python默认utf-8
编码,所有字符串都是 unicode 字符串。标识符
的第一个字符必须是字母表中字母或下划线’_’。标识符的其他的部分有字母、数字和下划线组成。标识符对大小写敏感。
Python保留字
>>> import keyword>>> keyword.kwlist['False', 'None', 'True', '__peg_parser__', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
Python注释
#这是单行注释"""这是多行注释这是多行注释"""'''也可以用三个单引号来进行多行注释'''
缩进
Python 使用缩进来表示代码块。缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。
基本数据类型
Python 中有六个标准的数据类型:
- Number(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Set(集合)
- Dictionary(字典)
Python3 的六个标准数据类型中:
不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
可变数据和不可变数据的“变”是相对于引用地址来说的,不是不能改变其数据,而是改变数据的时候会不会改变变量的引用地址。
数字:运算符+,-,* ,/ ,%
与其它语言一样括号 ()
用于分组,/
会保留小数部分,取而代之的是//
。**
运算符计算幂乘方 ,更高级计算需要引入数学计算库。
字符:Python 也提供单引号'...'
或双引号"..."
标识字符。\
可以用来转义,也可以使用 原始字符串,方法是在第一个引号前面加上一个r
会原样输出。
切片
# 要取得一段子串的话,可以用到变量[头下标:尾下标],就可以截取相应的字符串str="qwertyuiop"print(str[0:5])#qwert
类型判断
python可以用type函数来检查一个变量的类型:
type(name))
列表
列表List可以完成大多数集合类的数据结构实现。它支持字符,数字,字符串甚至可以包含列表(也就是嵌套)。
列表用[ ]标识。是 Python 最通用的复合数据类型。
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]tinylist = [123, 'john'] print list # 输出完整列表print list[0] # 输出列表的第一个元素print list[1:3] # 输出第二个至第三个的元素 print list[2:] # 输出从第三个开始至列表末尾的所有元素print tinylist * 2 # 输出列表两次print list + tinylist # 打印组合的列表
元组
元组Tuple是另一个数据类型,类似于 List(列表)。
元组用”()”标识。内部元素用逗号隔开。但是元素不能二次赋值,相当于只读列表。
tuple = ( 'abcd', 786 , 2.23, 'john', 70.2 )tinytuple = (123, 'john') print tuple # 输出完整元组print tuple[0] # 输出元组的第一个元素print tuple[1:3] # 输出第二个至第三个的元素 print tuple[2:] # 输出从第三个开始至列表末尾的所有元素print tinytuple * 2 # 输出元组两次print tuple + tinytuple # 打印组合的元组
字典
字典 (dictionary) 是除列表以外 Python 之中最灵活的内置数据结构类型。列表是有序的对象集合,字典是无序的对象集合。
两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
字典用”{ }”标识。字典由索引 (key) 和它对应的值 value 组成。
dict = {}dict['one'] = "This is one"dict[2] = "This is two"tinydict = {'name': 'john','code':6734, 'dept': 'sales'}print dict['one'] # 输出键为'one' 的值print dict[2] # 输出键为 2 的值print tinydict # 输出完整的字典print tinydict.keys() # 输出所有键print tinydict.values() # 输出所有值
数据类型转换
对数据内置的类型进行转换,只需要将数据类型作为函数名即可。
输入输出流
input()
函数作为输出流,print()
函数作为输入流
name=input()print(name)
变量
变量是存储在内存中的值。就是指针无关数据类型,解释器会分配指定大小的内存。
# 等号(=)用来给变量赋值counter = 100 # 赋值整型变量miles = 1000.0 # 浮点型name = "John" # 字符串# 多个对象指定多个变量a, b, c = 1, 2, "john"
文本换行
使用+ \
起到多行连接的作用:
data="this" + \"is" + \"Tuesday"print(data)#thisisTuesday# 空格也会被视为字符
内置库和函数
数学计算库
Python math 模块提供了许多对浮点数的数学运算函数。
Python cmath 模块包含了一些用于复数运算的函数。
import math
字符串运行算回切片获取
内置函数
关键字
自定义函数
Python函数的定义。定义函数需要用def
关键字实现,具体的语法格式如下:
def 函数名(参数列表)://实现特定功能的多行代码[return [返回值]]
def func(a,b):return a+bfunc(1,2)# 3
Python 支持在函数内部定义函数,此类函数又称为局部函数。
#全局函数def outdef ():#局部函数def indef():print("http://c.biancheng.net/python/")#调用局部函数indef()#调用全局函数outdef()
局部变量一样,默认情况下局部函数只能在其所在函数的作用域内使用。
lambda 表达式
对于定义一个简单的函数,Python 还提供了另外一种方法,lambda 表达式,又称匿名函数,常用来表示内部仅包含 1 行表达式的函数。如果一个函数的函数体仅有 1 行表达式,则该函数就可以用 lambda 表达式来代替。
name = lambda [list] : 表达式def name(list):return 表达式name(list)
eval() 和 exec() 函数
eval() 和 exec() 函数的功能是相似的,都可以执行一个字符串形式的 Python 代码(代码以字符串的形式提供),相当于一个 Python 的解释器。二者不同之处在于,eval() 执行完要返回结果,而 exec() 执行完不返回结果。
面向对象
Python 是一门面向对象的编程语言。类和对象是 Python 的重要特征,相比其它面向对象语言,Python 很容易就可以创建出一个类和对象。同时,Python 也支持面向对象的三大特征:封装、继承和多态。
面向对象中,常用术语包括:
- 类:可以理解是一个模板,通过它可以创建出无数个具体实例。比如,前面编写的 tortoise 表示的只是乌龟这个物种,通过它可以创建出无数个实例来代表各种不同特征的乌龟(这一过程又称为类的实例化)。
- 对象:类并不能直接使用,通过类创建出的实例(又称对象)才能使用。这有点像汽车图纸和汽车的关系,图纸本身(类)并不能为人们使用,通过图纸创建出的一辆辆车(对象)才能使用。
- 属性:类中的所有变量称为属性。例如,tortoise 这个类中,bodyColor、footNum、weight、hasShell 都是这个类拥有的属性。
- 方法:类中的所有函数通常称为方法。不过,和函数所有不同的是,类方法至少要包含一个 self 参数(后续会做详细介绍)。例如,tortoise 类中,crawl()、eat()、sleep()、protect() 都是这个类所拥有的方法,类方法无法单独使用,只能和类的对象一起使用。
在 Python 中,所有的变量其实也都是对象,包括整形(int)、浮点型(float)、字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)。以字典(dict)为例,它包含多个函数供我们使用,例如使用 keys() 获取字典中所有的键,使用 values() 获取字典中所有的值,使用 item() 获取字典中所有的键值对。
Python类的定义
Python 中定义一个类使用 class 关键字实现,其基本语法格式如下:
class 类名:多个(≥0)类属性...多个(≥0)类方法...
构造方法
在创建类时,我们可以手动添加一个__init__()
方法,该方法是一个特殊的类实例方法,称为构造方法(或构造函数)。
def __init__(self,...):代码块
注意,此方法的方法名中,开头和结尾各有 2 个下划线,且中间不能有空格。Python 中很多这种以双下划线开头、双下划线结尾的方法,都具有特殊的意义。
类的构造方法最少也要有一个 self 参数。self 所表示的都是实际调用该方法的对象。无论是类中的构造函数还是普通的类方法,实际调用它们的谁,则第一个参数 self 就代表谁。相当于Java的this。
类的实例化
创建类对象的过程,又称为类的实例化。类名(参数)
。
定义的类只有进行实例化后,才能得到利用。实例化后的类对象可以执行以下操作:
- 访问或修改类对象具有的实例变量,甚至可以添加新的实例变量或者删除已有的实例变量;
- 调用类对象的方法,包括调用现有的方法,以及给类对象动态添加方法。
类变量
在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性又可细分为以下 3 种类型:
- 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
- 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
- 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量。
类变量的特点是,所有类的实例化对象都同时共享类变量
实例变量只作用于调用方法的对象。另外,实例变量只能通过对象名访问,无法通过类名访问。
局部变量只能用于所在函数中,函数执行完成后,局部变量也会被销毁。
类方法
类方法也可以进行更细致的划分,具体可分为类方法、实例方法和静态方法。
采用 @classmethod 修饰的方法为类方法;采用 @staticmethod 修饰的方法为静态方法;不用任何修改的方法为实例方法。
实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。实例方法通常会用类对象直接调用。
Python 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。和 self 一样,cls 参数的命名也不是规定的(可以随意命名)。
类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)。
class CLanguage:#类构造方法,也属于实例方法def __init__(self):self.name = "C语言中文网"self.add = "http://c.biancheng.net"#下面定义了一个类方法@classmethoddef info(cls):print("正在调用类方法",cls)
类的静态方法中无法调用任何类属性和类方法。
class CLanguage:@staticmethoddef info(name,add):print(name,add)
setter和setter
Python 中,通过使用描述符,可以让程序员在引用一个对象属性时自定义要完成的工作。
class revealAccess:def __init__(self, initval = None, name = 'var'):self.val = initvalself.name = namedef __get__(self, obj, objtype):print("Retrieving",self.name)return self.valdef __set__(self, obj, val):print("updating",self.name)self.val = val
属性封装
使用用“类对象.属性”的方式访问类中定义的属性,其实这种做法是欠妥的,因为它破坏了类的封装原则。正常情况下,类包含的属性应该是隐藏的,只允许通过类提供的方法来间接实现对类属性的访问和操作。
在不破坏类封装原则的基础上,为了能够有效操作类中的属性,类中应包含读(或写)类属性的多个 getter(或 setter)方法,这样就可以通过“类对象.方法(参数)”的方式操作属性。此时属性要定义为实例属性。
class CLanguage:#构造函数def __init__(self,name):self.name = name #设置 name 属性值的函数 def setname(self,name):self.name = name#访问nema属性值的函数def getname(self):return self.name#删除name属性值的函数def delname(self):self.name="xxx"
这种操作类属性的方式比较麻烦,更习惯使用“类对象.属性”这种方式。Python 中提供了 property() 函数,可以实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。
class CLanguage:#构造函数def __init__(self,n):self.__name = n#设置 name 属性值的函数def setname(self,n):self.__name = n#访问nema属性值的函数def getname(self):return self.__name#删除name属性值的函数def delname(self):self.__name="xxx"#为name 属性配置 property() 函数name = property(getname, setname, delname, '指明出处')
封装
封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。
还可以定义以单下划线“_”开头的类属性或者类方法,这种类属性和类方法通常被视为私有属性和私有方法。
继承
继承机制经常用于创建和现有类功能类似的新类,又或是新类只需要在现有类基础上添加一些成员(属性和方法),但又不想直接将现有类代码复制给新类。也就是说,通过使用继承这种机制,可以轻松实现类的重复使用。
子类继承父类时,只需在定义子类时,将父类(可以是多个)放在子类之后的圆括号里即可。语法格式如下:
class 类名(父类1, 父类2, ...):#类定义部分
注意,如果该类没有显式指定继承自哪个类,则默认继承 object 类(object 类是 Python 中所有类的父类,即要么是直接父类,要么是间接父类)。另外,Python 的继承是多继承机制(和 C++ 一样),即一个子类可以同时拥有多个直接父类。
多继承经常需要面临的问题是,多个父类中包含同名的类方法。对于这种情况,Python 的处置措施是:根据子类继承多个父类时这些父类的前后次序决定,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法。
方法重载
子类继承了父类,那么子类就拥有了父类所有的类属性和类方法。通常情况下,子类会在此基础上,扩展一些新的类属性和类方法。
在子类定义一个同名同类型和参数的方法,重写方法体即可。
使用super()
函数访问父类成员或方法。但如果涉及多继承,该函数只能调用第一个直接父类的构造方法。
super().__init__(self,...)
多态
Python 是弱类型语言,其最明显的特征是在使用变量时,无需为其指定具体的数据类型。
类的特殊成员
__new__()
是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 __init__()
初始化方法被调用。
通常情况下,直接输出某个实例化对象,得到的信息只会是“类名+object at+内存地址”,对我们了解该实例化对象帮助不大。通过重写类的__repr__()
方法,当我们输出某个实例化对象时,其调用的就是该对象的 __repr__()
方法,输出的是该方法的返回值。
__del__()
方法,功能正好和 __init__()
相反,其用来销毁实例化对象。创建的类实例化对象后续不再使用,在适当位置手动将其销毁,释放其占用的内存空间(整个过程称为垃圾回收(简称GC))。
__dir()__
函数,通过此函数可以获取某个对象拥有的所有的属性名和方法名,该函数会返回一个包含有所有属性名和方法名的有序列表。
__dict__
属性。需要注意的一点是,该属性可以用类名或者类的实例对象来调用,用类名直接调用 __dict__
,会输出该由类中所有类属性组成的字典;而使用类的实例对象调用 __dict__
,会输出由类中所有实例属性组成的字典。
hasattr()
函数用来判断某个类实例对象是否包含指定名称的属性或方法。
hasattr(obj, name)
getattr()
函数获取某个类实例对象中指定属性的值。
getattr(obj, name[, default])
setattr()
函数的功能相对比较复杂,它最基础的功能是修改类实例对象中的属性值。其次,它还可以实现为实例对象动态添加属性或者方法。
setattr(obj, name, value)
迭代器
列表(list)、元组(tuple)、字典(dict)、集合(set)这些序列式容器有一个共同的特性,它们都支持使用 for 循环遍历存储的元素,都是可迭代的,因此它们又有一个别称,即迭代器。
实现如下 2 个方法:
__next__(self)
:返回容器的下一个元素。__iter__(self)
:该方法返回一个迭代器(iterator)。
装饰器
@staticmethod、@classmethod 和 @property,其中 staticmethod()、classmethod() 和 property() 都是 Python 的内置函数。
使用函数装饰器 A() 去装饰另一个函数 B(),其底层执行了如下 2 步操作:将 B 作为参数传给 A() 函数;将 A() 函数执行完成的返回值反馈回 B。
函数装饰器,就是通过装饰器函数,在不修改原函数的前提下,来对函数的功能进行合理的扩充。
异常处理
Python 中,用try except语句块捕获并处理异常,其基本语法结构如下所示:
try:
可能产生异常的代码块
except [ (Error1, Error2, … ) [as e] ]:
处理异常的代码块1
except [ (Error3, Error4, … ) [as e] ]:
处理异常的代码块2
except [Exception]:
处理其它异常
在原本的try except结构的基础上,Python 异常处理机制还提供了一个 else 块,也就是原有 try except 语句的基础上再添加一个 else 块,即try except else结构。使用 else 包裹的代码,只有当 try 块没有捕获到任何异常时,才会得到执行;反之,如果 try 块捕获到异常,即便调用对应的 except 处理完异常,else 块中的代码也不会得到执行。
try:result = 20 / int(input('请输入除数:'))print(result)except ValueError:print('必须输入整数')except ArithmeticError:print('算术错误,除数不能为 0')else:print('没有出现异常')print("继续执行")
Python 异常处理机制还提供了一个 finally 语句,通常用来为 try 块中的程序做扫尾清理工作。在整个异常处理机制中,finally 语句的功能是:无论 try 块是否发生异常,最终都要进入 finally 语句,并执行其中的代码块。
try:a = int(input("请输入 a 的值:"))print(20/a)except:print("发生异常!")else:print("执行 else 块中的代码") finally :print("执行 finally 块中的代码")
注意,和 else 语句不同,finally 只要求和 try 搭配使用,而至于该结构中是否包含 except 以及 else,对于 finally 不是必须的(else 必须和 try except 搭配使用)。
raise在
在程序的指定位置手动抛出一个异常。
raise [exceptionName [(reason)]]
其中,用 [] 括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述。如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息。
sys 模块中的 exc_info() 方法获得更多的异常信息。
模块
Python 提供了强大的模块支持,主要体现在,不仅 Python 标准库中包含了大量的模块(称为标准模块),还有大量的第三方模块,开发者自己也可以开发自定义模块。通过这些强大的模块可以极大地提高开发者的开发效率。
使用import
导入模块的语法
import 模块名1 [as 别名1], 模块名2 [as 别名2],…
:使用这种语法格式的 import 语句,会导入指定模块中的所有成员(包括变量、函数、类等)。不仅如此,当需要使用模块中的成员时,需用该模块名(或别名)作为前缀,否则 Python 解释器会报错。
from 模块名 import 成员名1 [as 别名1],成员名2 [as 别名2],…
: 使用这种语法格式的 import 语句,只会导入模块中指定的成员,而不是全部成员。同时,当程序中使用该成员时,无需附加任何前缀,直接使用成员名(或别名)即可。
用 [] 括起来的部分,可以使用,也可以省略。
自定义包与模块
包其实就是文件夹,包含py
文件的文件夹。手动创建一个包,只需进行以下 2 步操作:新建一个文件夹,文件夹的名称就是新建包的包名;创建py文件。
导入也很简单,主要有三种方式:
import 包名[.模块名 [as 别名]]
from 包名 import 模块名 [as 别名]
from 包名.模块名 import 成员名 [as 别名]
用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略。
模块属性与方法
查看模块成员:dir()
函数,通过 dir()
函数获取到的模块成员,不仅包含供外部文件使用的成员,还包含很多“特殊”(名称以 2 个下划线开头和结束)的成员,列出这些成员,对我们并没有实际意义。
import stringdir(string)
查看模块成员:__all__
变量,除了使用 dir() 函数之外,还可以使用 __all__
变量,借助该变量也可以查看模块(包)内包含的所有成员。__all__
变量在查看指定模块成员时,它不会显示模块中的特殊成员。
__doc__
属性,查看模块(包)的具体功能。
__file__
属性查找该模块(或包)文件所在的具体存储位置,直接查看其源代码。
IO处理
Python 提供了内置的文件对象,以及对文件、目录进行操作的内置模块,通过这些技术可以很方便地将数据保存到文件(如文本文件等)中。
在 Windows 上,路径书写使用反斜杠 “” 作为文件夹之间的分隔符,但在 OS X 和 Linux 上,使用正斜杠 “/” 作为它们的路径分隔符。需要两个第一个是转义字符。
对文件的系统级操作功能单一,比较容易实现,可以借助 Python 中的专用模块(os、sys 等),并调用模块中的指定函数来实现。
import osos.remove("a.txt")
文件的应用级操作可以分为以下 3 步,每一步都需要借助对应的函数实现:
- 打开文件:使用
open()
函数,该函数会返回一个文件对象; - 对已打开文件做读/写操作:读取文件内容可使用
read()、readline() 以及 readlines()
函数;向文件中写入内容,可以使用write()
函数。 - 关闭文件:完成对文件的读/写操作之后,最后需要关闭文件,可以使用
close()
函数。
如果想要操作文件,首先需要创建或者打开指定的文件,并创建一个文件对象,而这些工作可以通过内置的 open()
函数实现:
file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])
Python 提供了如下 3 种函数,它们都可以帮我们实现读取文件中数据的操作:
- read() 函数:逐个字节或者字符读取文件中的内容;
- readline() 函数:逐行读取文件中的内容;
- readlines() 函数:一次性读取文件中多行内容。
Python 中的文件对象提供了 write() 函数,可以向文件中写入指定内容。如:file.write(string)
close() 函数是专门用来关闭已打开文件的,如:file.close()
实现对文件指针的移动,文件对象提供了 tell() 函数和 seek() 函数。tell() 函数用于判断文件指针当前所处的位置,而 seek() 函数用于移动文件指针到文件的指定位置。
tell() 函数的用法很简单,如:file.tell()
。
seek() 函数用于将文件指针移动至指定位置,如:file.seek(offset[, whence])
使用 with as 操作已经打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证 with as 语句执行完毕后自动关闭已经打开的文件:
with 表达式 [as target]:代码块