《Python 从入门到精通》——python进阶提高

一、python中使用正则表达式

1.1 正则表达式语法

1.1.1 行定位符

行定位符表示用来描述字符串的边界。“^”表示行的开始;“$”表示行的结尾

^tm

该表达式指字符串tm的开始位置是行头,如tm equal Tomorrow Moon就可以匹配,而Tomorrow Moon Equal tm 则不能匹配

tm$

则表示后者可以匹配,前者不能匹配。如果要匹配任意部分的字符串,则可以写成

tm

1.1.2 元字符

\bmr\w*\b

匹配以mr开头的单词,先从某个单词开始处(\b),然后匹配字母mr,接着是任意数量的字母或数字(\w*),最后是单词处(\b)。如该表达式可以匹配"mrsoft"、"mrbook"和"mr12345"等。

常用的元字符

.  匹配除换行以外的任意字符

\w  匹配字母或数字或下划线或汉字

\s  匹配任意的空白符

\d  匹配数字

\b  匹配单词的开始或结束

^  匹配字符串的开始

$  匹配字符串的结束

1.1.3 重复

\w* 可以匹配任意数量的字母或数字,若想匹配特点数量的数字,可以使用限定符来实现,例如匹配8位数字的学生学号

^\d{8}$

常用的限定符

? 匹配前面字符零次或一次(colou?r,匹配为colour和color)

+  匹配前面的字符一次或多次 (go+gle,匹配的范围从gogle到goo...gle)

*   匹配前面字符零次或多次 (go*gle,匹配范围从ggle到goo...gle)

{n} 匹配前面的字符n次  (go{2}gle,只匹配google)

{n,} 匹配前面的字符最少n次 (go{2,}gle,google到goo...gle)

{n,m} 匹配前面的字符最少n次,最多m次 (employe{0,2},可以匹配employ、employe、employee

1.1.4 字符类

  当出现在没有预定元字符的字符集合(如元音字母a,e,i,o,u),则只需在方括号中列出即可,如[aeiou]就可以匹配任何一个英文元音字母,[.?!]匹配标点符号“.”、“?”或“!”。也可以指定一个字符范围,如[0-9]代表含义与\d就是完全一致的,[a-z0-9A-Z]也等同于\w。

  若想匹配给定字符串中任意的一个汉字,可以使用[\u4e00-\u9fa5];如果要匹配连续多个汉字,可以使用[\u4e00-\u9fa5]+。

1.1.5 排除字符

[^a-zA-Z]

该表达式表示用于匹配一个不是字母的字符

1.1.6 选择字符

例如匹配身份证号码,可以有15位全为数字,或者18位,最后一位为校验位(X或x),则可以将表达式写为:

(^\d{15}$)|(^\d{18}$)|(^\d{17})(\d|X|x)$

1.1.7 转义字符

如“."字符表示可以匹配任意字符,若想用正则表达式匹配127.0.0.1这样的IP地址,则可以用转义字符来实现

[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

1.1.8 分组

(thir|four)th

该表达式指匹配单词thirth或fourth

例如(\.[0-9]{1,3}){3},表示对分组(\.[0-9]{1,3})进行重复操作

1.1.9 在python中使用正则表达式语法

将匹配不是字母的一个字符的正则表达式表示为模式字符串

'[^a-zA-Z]'

如果将匹配以字母m开头的正则表达式转换为模式字符串

'\\bm\\w*\\b'

由于模式字符串中可能包括大量的特殊字符和反斜杠,所以需要写成原生字符串,即在模式字符串前加r或R,例如

r'\bm\w*\b'

1.2 使用re模块实现正则表达式操作

在使用re模块时,需先应用import语句

import re

1.2.1 匹配字符串

1.使用match()方法进行匹配

re.match(pattern,string,[flags])

pattren:模式字符串,由要匹配的正则表达式转换而来

string:匹配的字符串

flags:表示标志位,用于控制匹配方式,如是否区分字母大小写

常用标志

A (对于\w,\W,\b,\B,\d,\D,\s,\S只进行ASCII匹配)

I  (执行不区分字母大小写匹配)

M (将^和$用于整个字符串的开始和结尾的每一行)

S  (使用“.”字符匹配所有字符,包括换行符)

X (忽略模式字符中未转义的空格和注释)

例如匹配字符串是否以“mr_”开头,不区分是大小写

import re
pattern=r'mr_\w+'
string='MR_SHOP mr_shop'
match=re.match(pattern,string,re.I)
print(match)
string='项目名称 MR_SHOP mr_shop'
match=re.match(pattern,string,re.I)
print(match)

从结果中可以看出,如果开头为mr_,则返回一个Match对象,若不是,则返回None

 如果想获取匹配值可以使用Match对象的start()方法;获取匹配值的结束位置使用end()方法,通过span()方法可以返回匹配位置的元组

import re
pattern=r'mr_\w+'
string='MR_SHOP mr_shop'
match=re.match(pattern,string,re.I)
print('匹配值的起始位置:',match.start())
print('匹配值的结束位置:',match.end())
print('匹配值位置的元组:',match.span())
print('匹配值的字符串:',match.string)
print('匹配数据:',match.group())


如验证学生输入的学号是否合法

import re
pattern=r'(202[0-9]\d{8})$|(204[01289]\d{8})$'
number='202220620123'
match=re.match(pattern,number)
if match == None:
      print(number,'不是有效的学号')
else:
      print(number,'是有效的学号')

number='20430620123'
match=re.match(pattern,number)
if match == None:
      print(number,'不是有效的学号')
else:
      print(number,'是有效的学号')

2.使用search()方法进行匹配

re.search(pattern,string,[flags])

pattren:模式字符串,由要匹配的正则表达式转换而来

string:匹配的字符串

flags:表示标志位,用于控制匹配方式,如是否区分字母大小写

例如匹配字符串是否以“mr_”开头,不区分是大小写

import re
pattern=r'mr_\w+'
string='MR_SHOP mr_shop'
match=re.search(pattern,string,re.I)
print(match)
string='项目名称 MR_SHOP mr_shop'
match=re.search(pattern,string,re.I)
print(match)

从运行结果中可以看出,search()方法不仅是在字符的起始位置搜素,其他位置有符合的匹配也可以

 例如验证对话中是否出现警告字符

import re
pattern=r'(偷看)|(作弊)|(抄写)'
about='我刚刚考试的时候作弊了'
match=re.search(pattern,about)
if match==None:
      print(about,'安全!')
else:
      print(about,'警告!')
about='我刚刚完成了最后一道大题'
match=re.search(pattern,about)
if match==None:
      print(about,'安全!')
else:
      print(about,'警告!')

3.使用findall()方法进行匹配

re.findall(pattern,string,[flags]) 

pattren:模式字符串,由要匹配的正则表达式转换而来

string:匹配的字符串

flags:表示标志位,用于控制匹配方式,如是否区分字母大小写

例如匹配字符串是否以“mr_”开头,不区分是大小写

import re
pattern=r'mr_\w+'
string='MR_SHOP mr_shop'
match=re.findall(pattern,string,re.I)
print(match)
string='项目名称 MR_SHOP mr_shop'
match=re.findall(pattern,string)
print(match)

从结果中可以看出,findall()方法用于整个字符串中搜素所有符合正则表达式的字符串,并以列表的形式返回,若匹配成功,则返回包含匹配结构的列表,否则返回空列表

 1.2.2 替换字符串

re.sub(pattern,repl,string,count,flags)

pattren:模式字符串,由要匹配的正则表达式转换而来

repl:替换的字符串

string:要被查找替换的原始字符串

count:表示模式匹配后替换的最大次数,默认为0,表示替换所有的匹配

flags:表示标志位,用于控制匹配方式,如是否区分字母大小写

例如隐藏学生的学号信息

import re
pattern=r'2[0-9]\d{10}'
string='学生姓名:小明 学生学号:202420710923'
result=re.sub(pattern,'2XXXXXXXXXXX',string)
print(result)

 1.2.3 使用正则表达式分割字符串

re.split(pattern,string,[maxsplit],[flags])

pattren:模式字符串,由要匹配的正则表达式转换而来

string:匹配的字符串

maxsplit:表示最大的拆分次数

flags:表示标志位,用于控制匹配方式,如是否区分字母大小写

例如提取请求地址和各个参数

import re
pattern=r'[?|&]'
url='http://www.aun.com/ball.jsp?username="mr"&pwd="mrsoft"'
result=re.split(pattern,url)
print(result)

二 函数 

2.1 函数的创建和调用

2.1.1 创建一个函数

def functionname([parameterlist]):

        ["'comments'"]

        [functionbody]

functionname:函数名称,在调用函数时使用

parameterlist:指定向函数中传递的参数,若有多个参数,各参数之间使用“,”分隔,若不指定,则表示该函数没有参数

comments:表示为函数指定注释

functionbody:指定函数体,该函数被调用后需要执行的代码功能

如定义一个过滤危险字符的函数

def filterchar(string):
      '''过滤警告词汇
      '''
      import re
      pattern=r'(偷看)|(作弊)|(抄写)'
      sub=re.sub(pattern,'@_@',string)
      print(sub)
2.1.2 调用函数

functionname([parametersvalue])

functionname:函数名称,调用已命名好的函数名称

parametersvalue:指定各个参数的值

如上面的过滤危险字符程序代码,只需调用函数

def filterchar(string):
      '''过滤警告词汇
      '''
      import re
      pattern=r'(偷看)|(作弊)|(抄写)'
      sub=re.sub(pattern,'@_@',string)
      print(sub)
about='我刚刚考试的时候作弊了'
filterchar(about)

2.2 参数传递

 2.2.1 了解形式参数和实际参数

1.通过作用理解

定义或创建函数,此时函数参数obj为形式参数

defdemo(obj):

        print(obj)

调用函数,此时的函数参数mot和list1是实际参数

mot="i love you"

demo(mot)

list1=["very" "very" "love" "you"]

demo(list1)

根据实际参数的类型不同,可分为值传递和引用传递

def demo(obj):
      print("原值: ",obj)
      obj+=obj
print("======值传递======")
mot="i love you"
print("函数调用前:",mot)
demo(mot)
print("函数调用后:",mot)
print("======引用传递======")
list1=["very" "very" "love" "you"]
print("函数调用前:",list1)
demo(list1)
print("函数调用后:",list1)

2.通过比喻理解形式参数和实际参数

 例如定义一个计算BMI指数的函数并调用

def fun_bmi(person,height,weight):
      print(person+"的身高:"+str(height)+"米\t体重:"+str(weight)+"千克")
      bmi=weight/(height*height)
      print(person+"的BMI指数为:"+str(bmi))
      if bmi<18.5:
            print("体重过轻")
      if bmi>=18.5 and bmi<24.9:
            print("正常范围")
      if bmi>=24.9 and bmi<29.9:
            print("体重过重")
      if bmi>=29.9:
            print("肥胖")
fun_bmi("aun",1.82,60)
fun_bmi("auq",1.60,49)

其中函数指定的变量person、height和weight为形式参数,aun、1.83、60等为实际参数

 2.2.2 位置参数

1.数量必须与定义时一致

指定的实际参数数量必须与形式参数的数量一致,否则将抛出异常TypeError,如上面的BMI函数中,实际参数为fun_bmi("aun",1.82,60)

2.位置必须与定义时一致

如果将上面的实际参数位置调换,将发生以下错误显示

 2.2.3 关键字参数

用形式参数的的名字来确定输入的参数值,这样做可以避免顺序的错误,如:

fun_bmi(weight=60,person="aun",height=1.82)

这样即使顺序调换,也不会报错

2.2.4 为参数设置默认值

def functionname(...,[parameter1=defaultvalue1]):

        [functionbody]

如对上面计算BMI指数的代码进行修改

def fun_bmi(height,weight,person="aun"):
      print(person+"的身高:"+str(height)+"米\t体重:"+str(weight)+"千克")
      bmi=weight/(height*height)
      print(person+"的BMI指数为:"+str(bmi))
      if bmi<18.5:
            print("体重过轻")
      if bmi>=18.5 and bmi<24.9:
            print("正常范围")
      if bmi>=24.9 and bmi<29.9:
            print("体重过重")
      if bmi>=29.9:
            print("肥胖")
fun_bmi(1.82,60)

输出后是同样的效果,只不过无需指定第一个参数

2.2.5 可变参数

1.*parameter

def printplayer(*start):
      print('\n 我喜欢的篮球明星有:')
      for item in start:
            print(item)
printplayer('科比')
printplayer('科比','詹姆斯','乔丹','麦迪','艾弗森')
printplayer('科比','詹姆斯','乔丹','麦迪')

 

如果想要使用一个已存在的列表,可以在列表前加*

balls=['科比','詹姆斯','乔丹']
print(*balls) 

2.**parameter

def printsign(**sign):
      print( )
      for key,value in sign.items():
            print("["+key+"]的成绩是:"+value)
printsign(小明='90',小蓝='70')

同样的,如果想要使一个已存在的字典作为可变参数,在名称前加**

dict1={小明='90',小蓝='70'}
print(**dict1) 

2.3 返回值

return[value]

return:用于保存函数返回的结果

value:指定要返回的值,可以返回一个值,也可返回多个值

如模拟一个结账打折函数功能

def fun_checkout(money):
      money_old=sum(money)
      money_new=moeny_old
      if money_old>=500 and money_old<1000:
            money_new='{:.2f}'.format(money_old*0.9)
      elif money_old>=1000 and money_old<=2000:
            money_new='{:.2f}'.format(money_old*0.8)
      elif money_old>=2000 and money_old<=3000:
            money_new='{:.2f}'.format(money_old*0.7)
      elif money_old>=3000:
            money_new='{:.2f}'.format(money_old*0.6)
      return money_old,money_new

2.4 变量的作用域

2.4.1 局部变量

指在函数内部定义并使用的变量,只在函数内部有效。例如:

def f_demo():
      message='i love you'
      print('局部变量',message)
f_demo()
print('局部变量',message)

运行会显示异常

2.4.2 全局变量 

(1)在函数外定义

message='i love you'
def f_demo():
      print('局部变量',message)
f_demo()
print('局部变量',message)

(2)函数体内定义,并且使用global关键词修饰

message='i love you'
print('函数体外:message=',message)
def f_demo():
      global message
      message='very very love you'
      print('函数体内:message=',message)
f_demo()
print('函数体外:message=',message)

 

2.5 匿名函数 

匿名函数是指没有名字的函数,在需要一个函数但却不想命名的时候使用

result=lamba[arg1[arg2,...argn]]:expression

result:用于调用lambda

[arg1[arg2,...argn]]:用于指定要传递的参数列表

expression:用于指定一个实现具体功能的表达式

例如定义一个计算圆面积的函数

import math
def circlearea(r):
      result=math.pi*r*r
      return result
r=10
print('半径为',r,'的圆面积为:',circlearea(r))

使用lambda表达式如下

import math
r=10
result=lambda r:math.pi*r*r
print('半径为',r,'的圆面积为:',circlearea(r)) 

(该代码运行错误,需要定义一个变量,调用该lambda表达式)

三、面向对象程序设计

3.1 面向对象概述

3.1.1 对象

  通常来讲,对象划分为两个部分,即静态部分,比如说人的性别和动态部分,即对象执行的动作,比如说人可以行走

  在Python中,一切都是对象,不仅是具体的事物称为对象,字符串、函数等也都是对象

3.1.2 类

简单来说就是具有相同属性和行为的一类实体被称为类。如把雁群比作大雁类,那么大雁类就具备了翅膀和爪等属性,觅食、飞行和睡觉的行为,而大雁则被视为大雁类的一个对象。

3.1.3 面向对象程序设计的特点

面向对象程序设计具有三大基本特征:封装、继承和多态(在这里只进行简单的概括和描述,需要详细了解的可以另外学习)

1.封装

封装技术将对象的属性和行为封装起来,而封装起来的载体就是类,类是对客户隐藏而实现其细节,比如说用户在使用计算机时,只需移动鼠标和敲击键盘,无需知道计算机的内部工作原理。封装思想既保护了类内部数据结构的完整性,也避免了外部对内部数据的影响,提高了程序的可维护性。

2.继承

把平行四边形类看作是继承四边形类后产生的类,把类似于平行四边形的类称为子类,类似于四边形的类称为父类,其中我们可以说平行四边形是特殊的四边形,但是不能说四边形是平行四边形,同理,在python中,我们可以说子类的实例是父类的实例,但是反过来则不成立。所以,子类通过继承复用了父类的属性和行为的同时,又添加了子类特有的属性和行为。

3.多态

将父类对象应用于子类的特征就是多态。比如螺丝有长螺丝和短螺丝,他们在继承父类特征的同时,也具备了自己的特征,实现不同的效果,这就是多态化的结构。

3.2 类的定义和使用

3.2.1 定义类

class ClassName:

        "'类的帮助信息"'

        statement

ClassName:用于指定类名,一般使用大写字母开头

statement:类体,主要由类变量、方法和属性等定义语句组成,若定义类时没想好具体功能,可以直接使用pass语句代替

例如声明一个大雁类

class Geese:

        "'大雁类"'

        pass

3.2.2 创建类的实例

ClassName(parameterlist)

ClassName是必选参数,用于指定具体类;parameterlist是可选参数

例如创建Geese类的实例

class Geese:
      '''大雁类'''
      pass
wildGoose=Geese()
print(wildGoose)

3.2.3 创建__init__()方法

如以大雁声明一个类

class Geese:
    """大雁类"""

    def __init__(self):
        print("我是大雁类")

wildGoose = Geese()

在__init__()方法中,除了self参数,还可以自定义一些参数,例如

class Geese:
    """大雁类"""

    def __init__(self,beak,wing,claw):
        print("我是大雁类!我有以下特征:")
        print(beak)
        print(wing)
        print(claw)
beak_1="喙的特征(基部高)"
wing_1="翅膀长而尖"
claw_1="爪子是蹼状"
wildGoose=Geese(beak_1,wing_1,claw_1)

3.2.4 创建类的成员并访问

 1.创建类方法并访问

实例方法,指在类中定义的函数,同__init__()方法一样,实例方法第一个参数必须是self

def functionName(self,parameterlist):

        block

functionName:用于指定方法名

self:类的实例

parameterlist:指定除self参数以外的参数

block:方法体,实现具体功能

实例方法创建完成后,可以通过类的实例名称和点(.)操作符进行访问

instanceName.functionName(parametervalue)

如创建大雁类并定义飞行的方法

class Geese:
    """大雁类"""

    def __init__(self,beak,wing,claw):
        print("我是大雁类!我有以下特征:")
        print(beak)
        print(wing)
        print(claw)
    def fly(self,state):
        print(state)
beak_1="喙的特征(基部高)"
wing_1="翅膀长而尖"
claw_1="爪子是蹼状"
wildGoose=Geese(beak_1,wing_1,claw_1)
wildGoose.fly("我飞行的时候,一会儿排成个人字,一会排成个一字")

 

2.创建数据成员并访问

数据成员是指在类中定义的变量,即属性,根据定义位置,可分为类属性和实例属性

类属性:

指定义在类中,并且在函数体外的属性。类属性可以在类的所有实例之间共享值,也就是在所有实例化的对象中公用。

例如定义一个雁类Geese,在该类中定义3个类属性

class Geese:
    """雁类"""
    neck="脖子较长"
    wing="振翅频率高"
    leg="行走自如"
    def __init__(self):
        print("我属于雁类!我有以下特征:")
        print(Geese.neck)
        print(Geese.wing)
        print(Geese.leg)
geese=Geese()

除了访问类属性,还可以动态地为类和对象添加属性

Geese.beak="喙的长度和头部的长度几乎相等"

print("第2只大雁的喙:",list[1].beak)

实例属性:

指定义在类的方法中的属性,只作用于当前实例中

例如定义一个雁类Geese,在该类中定义3个类属性

class Geese:
    """雁类"""
    def __init__(self):
        self.neck="脖子较长"
        self.wing="振翅频率高"
        self.leg="行走自如"
        print("我属于雁类!我有以下特征:")
        print(self.neck)
        print(self.wing)
        print(self.leg)
geese=Geese()

实例属性也可以通过实例名称修改,但与类属性不同,实例属性修改后并不影响另一个实例中相应的实例属性的值。例如:

class Geese:
    """雁类"""
    def __init__(self):
        self.neck="脖子较长"
        print(self.neck)
goose1=Geese()
goose2=Geese()
goose1.neck="脖子没有天鹅的长"
print("goose1的neck属性:",goose1.neck)
print("goose2的neck属性:",goose2.neck)

 3.2.5 访问限制

(1)_foo:以单下划线开头的表示protected(保护)类型的成员,只允许类本身和子类进行访问,但不能使用”from module import*“导入

例如创建一个Swan类,通过实例名输出保护属性_neck_swan

class Swan:
    '''天鹅类'''
    _neck_swan='天鹅的脖子很长'
    def __init__(self):
        print("__init__():",Swan._neck_swan)
swan=Swan()
print("直接访问:",swan._neck_swan)

从运行结果可以看出,保护属性可以通过实例名访问

(2)__foo:双下划线表示private(私有)类型的成员,只允许定义该方法的类本身进行访问,而且也不能通过类的实例进行访问,但是可以通过”类的实例名.类名__xxx“方式访问

例如创建一个Swan类,通过实例名输出私有属性_neck_swan

class Swan:
    '''天鹅类'''
    __neck_swan='天鹅的脖子很长'
    def __init__(self):
        print("__init__():",Swan.__neck_swan)
swan=Swan()
print("加入类名:",swan._Swan__neck_swan)
print("直接访问:",swan._neck_swan)

3.3 属性

3.3.1 创建用于计算的属性

在Python中,可以通过@property将一个方法转换为属性,从而实现用于计算的属性,可以直接通过方法名来访问方法,而不需要在添加"()"

@property

def methodname(self):

        block

methodname:指定方法名

self:必要参数,表示类的实例

block:方法体,实现的具体功能

例如定义一个矩阵类,然后定义一个计算矩形面积的方法,应用@property将其转换为属性,并访问

class Rect:
    def __init__(self,width,height):
        self.width=width
        self.height=height
    @property
    def area(self):
        return self.width*self.height
rect=Rect(800,600)
print("面积为:",rect.area)

3.3.2 为属性添加安全保护机制

 在Python中,默认情况下,创建的类属性或者实例是可以在类体外进行修改的,若想要限制其不能在类体外修改,可以设置为私有,但类体外也不能获取它的值,如果想要创建一个可以读取,但不能修改的属性,可以用@property实现只读属性

例如创建一个TVshow,在创建一个show属性,用于显示当前播放的电视节目

class TVshow:
    def __init__(self,show):
        self.__show=show
    @property
    def show(self):
        return self.__show
tvshow=TVshow("正在播放《猪猪侠》")
print("默认:",tvshow.show)

通过上面的方法创建的show属性是只读的,尝试修改该属性的值,再重新获取

tvshow.show="正在播放《熊出没》"
print("修改后:",tvshow.show)

 

红色的异常信息就是修改属性show时抛出的异常

3.4 继承 

3.4.1 继承的基本语法

 继承是面向对象编程最重要的特性之一。不仅可以实现代码的重用,还可以通过继承来理顺类与类之间的关系

class ClassName(baseclasslist):

        "'类的帮助信息"'

        Statement

ClassName:指定类名

baseclasslist:指定要继承的基类,可以有多个,类名之间用逗号分割,若不指定,将使用所有Python对象的根类object

“‘类的帮助信息”’:用于指定类的文档字符串

statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成
 

例如创建水果基类及其派生类

class Fruit:
    color="绿色"
    def harvest(self,color):
        print("水果是:"+color+"的!")
        print("水果已经收获....")
        print("水果原来是:"+ Fruit.color +"的!");
class Apple(Fruit):
    color="红色"
    def __init__(self):
        print("我是苹果")
class Orange(Fruit):
    color="橙色"
    def __init__(self):
        print("\n 我是橘子")
apple=Apple()
apple.harvest(apple.color)
orange=Orange()
orange.harvest(orange.color)

3.4.2 方法重写

基类的成员都会被派生类继承,当基类中的某个方法不完全适用于派生类时,就需要在派生类中重写父类这个方法

例如在创建派生类Orange时,重写harvest()方法

class Orange(Fruit):
    color="橙色"
    def __init__(self):
        print("\n我是橘子")
    def harvet(self,color):
        print("橘子是:"+color+"的!")
        print("橘子已经收获……")
        print("橘子原来是:"+ Fruit.color +"的!");
3.4.3 派生类中调用基类__init__()方法

在派生类中定义__init__方法时,不会自动调用基类的__init__()方法。例如:

class Fruit:
    def __init__(self,color="绿色"):
       Fruit.color=color
    def harvest(self):
        print("水果原来是:"+Fruit.color+"的!");
class Apple(Fruit):
    color="红色"
    def __init__(self):
        print("我是苹果")
apple=Apple()
apple.harvest()

 

因此,要让派生类调用基类的__init__()方法进行必要的初始化,需要在派生类是使用super()函数调用基类__init__()方法。

super().__init__()

class Fruit:
    def __init__(self,color="绿色"):
       Fruit.color=color
    def harvest(self):
        print("水果原来是:"+Fruit.color+"的!");
class Apple(Fruit):
    color="红色"
    def __init__(self):
        print("我是苹果")
        super().__init__()
apple=Apple()
apple.harvest()

四、模块

 4.1 模块概述

在Python中,一个扩展名为,py的文件就称为一个模块。通常情况下,我们把能够实现某一特定功能设置在一个文件中作为一个模块,从而方便其他程序和脚本导入并使用。另外,使用模块也可以避免函数名和变量名冲突。

4.2 自定义模块

 4.2.1 创建模块

例如创建计算BMI指数模块

def fun_bmi(person,height,weight):
    '''功能: 根据身高和体重计算BMi指数
        person:姓名
        height:身高,单位:米
        weight:体重,单位:千克
    '''
    print(person+"的身高:"+str(height)+"米\t 体重:"+str(weight)+"千克")
    bmi=weight/(height*height)
    print(person+"的BMI指数为:"+str(bmi))
def fun_bmi_upgrade(*person)
    '''功能:……
    ……
    '''
4.2.2 使用import语句导入模块

创建模块后就可以在其他程序中使用该模块。

import modulename[as alias]

例如:

import bmi
bmi.fun_bmi("GGbond",1.55,120)

4.2.3 使用from……import语句导入模块

使用import语句导入模块时,每执行一条import语句都会创建一个新的命名空间,若不想每次导入都创建,而是将具体的定义导入当前的命名空间,就可以使用from……import语句

from modelname import member

modelname:模块名称,区分字母大小写

member:用于指定要导入的变量、函数或者类等

例如

from bmi import fun_bmi

导入空格包括同名函数的模块

(1)创建矩形模块

def girth(width,height):
      '''功能:计算周长
            参数:width(宽度)、height(高)
'''
      return (width+height)*2
def area(width,height):
      '''功能:计算面积
            参数:width(宽度)、height(高)
'''
      return width*height
if __name__=='__main__':
      print(area(10,20))

(2)创建圆形模块

import math
PI=math.pi
def girth(r):
      '''功能:计算周长
            参数:r(半径)
'''
      return round(2*PI*r,2)
def area(r):
      '''功能:计算面积
            参数:r(半径)
'''
      return round(PI*r*r,2)
if __name__=='__main__'
      print(girth(10))

(3)调用计算矩形和圆形的周长

import rectangle as r
import circular as c
if __name__=='__main__':
      print("圆形的周长为:",c.girth(10))
      print("矩形的周长为:",r.girth(10,20))

4.2.4 模块搜素目录

 当使用import语句导入模块时,默认情况下,会按照以下顺序进行查找

(1)在当前目录下查找

(2)在PYTHONPATH下的每个目录中查找

(3)在Python的默认安装目录下查找

以上各个目录的具体位置保存在标准模块sys的sys.path变量中,可以通过以下代码

import sys

print(sys.path)

1.临时添加

import sys

sys.path.append('E:/program/Python/Code/demo')

 

2.增加.pth文件

#.pth文件是我创建的路径文件(这里为注释)

E:/program/Python/Code/demo

3.在PYTHONPATH环境变量中添加

属性——高级系统设置——环境变量——编辑——添加新的目录模块

4.3 Python中的包

包简单理解就是”文件夹“,只不过在该文件夹下必须存在一个名称为”__init__.py“的文件

4.3.1 创建和使用包

1.创建和使用包

2.使用包

创建包后,就可以在包中创建相应的模块,然后在使用import语句从包中加载模块,通常有以下三种方式

(1)通过”import+完整包名+模块名“

import setting.size

(2)在size模块中定义变量

width=800
height=600

(3)通过“import+完整包名+模块名”形式导入size

import settings.size
if __name__=='__main__':
      print('宽度:',settings.size.width)
      print('高度:',settings.size.height)

(4)通过“from+完整包名+import+模块名”形式加载指定模块

from settings import size
if __name__=='__main__':
      print('宽度:',size.width)
      print('高度:',size.height)

 (5)通过“from+完整包名+模块名+import+定义名”

from settings.size import width,height
if __name__=='__main__':
      print('宽度:',width)
      print('高度:',height)

4.3.2 以主程序的形式执行

 创建一个名称为christmastree的模块

pinetree='我是一颗松树'
def fun_christmastree():
      '''功能:一个梦
            无返回值
      '''
      printree='挂上彩灯、礼物……变成圣诞树'
      print(pinetree)
print('\n 下雪了……\n')
print('========开始做梦……========\n')
fun_christmastree()
print('========梦醒了……========\n')
pinetree='我身上落满雪花,'+pinetree+'^-^'
print(pinetree)

在与christmastree模块同级目录下创建一个main.py文件,再通过print()语句输出

import differenttree
print(differenttree.pinetree)
4.4 引用其他模块
4.4.1 导入和使用标准模块

import random

例如生成由数字、字母组成的4位验证码

import random  
if __name__=='__main__':
    checkcode=""    
    for i in range(4):      
        index=random.randrange(0,4)     
        if index !=i and index+1 !=i:
            checkcode+=chr(random.randint(97,122))      
        elif index+1==i:
            checkcode+=chr(random.randint(65,90))      
        else:
            checkcode+=str(random.randint(1,9))     
    print("验证码:",checkcode)    

Python常用的内置标准模块

 sys        与Python解释器及其环境操作相关

time        提供与时间相关的各种函数的标准库

os            提供访问操作系统服务功能

calendar  与日期相关的各种函数

urllib        用于读取来自网上的数据标准库

json        使用JSON序列化和反序列化对象

re            用于字符串中执行正则表达式匹配和替换

math        提供标准算术运算函数的标准库

decimal     进行精确控制运算精度、有效数位

shutil       进行高级文件操作,如赋值、移动和重命名等

logging     提供了灵活的记录事件、错误、警告和调试信息等日志信息的功能

tkinter        使用Python进行GUI编程的标准库

五、异常处理及程序调试

5.1 异常概述

例如模拟幼儿园分苹果

def division():
      print("\n========== 分苹果 ==========\n")
      apple=int(input("请输入苹果的个数:"))
      children=int(input("请输入来了几个下朋友:"))
      result=apple//children
      remain=apple-result*children
      if remain>0:
            print(apple,"个苹果,平均分给",mchildren,"个小朋友,每个分",result,
                        "个,剩下",remain,"个。")
      else:
            print(apple,"个苹果,平均分给",children,"个小朋友,每个分",result,"个。")
if __name__=='__main__':
      division()

 若输入个数时,把小朋友输成0

 则抛出ZeroDivisionError异常

Python中常见的异常

NameError        尝试访问一个没有声明的变量引发的错误

IndecError        索引超出序列氛围引发的错误

IndentationError  缩进错误

ValueError        传入的值错误

KeyError        请求一个不存在的字典关键词引发的错误

IOError        输入输出错误

ImportError      当import语句无法找到模块或from无法在模块中找到相应的名称时引发的错误

AttributeError        尝试访问未知的对象属性引发的错误

TypeError        类型不合适引发的错误

MemoryError        内存不足

ZeroDivisionError        除数为0引发的错误

5.2 异常处理语句

5.2.1 try……except语句

try:

        block1

except[ExceptionName [as alias]]:

        block2

block1:表示可能出现错误的代码

[ExceptionName [as alias]]:可选参数,用于指定要捕获的异常

block2:表示进行异常处理的代码块

def division():
      print("\n========== 分苹果 ==========\n")
      apple=int(input("请输入苹果的个数:"))
      children=int(input("请输入来了几个小朋友:"))
      result=apple//children
      remain=apple-result*children
      if remain>0:
            print(apple,"个苹果,平均分给",mchildren,"个小朋友,每个分",result,
                        "个,剩下",remain,"个。")
      else:
            print(apple,"个苹果,平均分给",children,"个小朋友,每个分",result,"个。")
if __name__=='__main__':
      try:
            division()
      except ZeroDivisionError:
            print("\n 出错了 ~-~ ---苹果不能被0个下朋友分")
      except ValueError as e:
            print("输入错误:",e)

5.2.2 try……except……else语句

 用于指定当try语句块中没有发现异常时要执行的语句块

def division():
      print("\n========== 分苹果 ==========\n")
      apple=int(input("请输入苹果的个数:"))
      children=int(input("请输入来了几个小朋友:"))
      result=apple//children
      remain=apple-result*children
      if remain>0:
            print(apple,"个苹果,平均分给",mchildren,"个小朋友,每个分",result,
                        "个,剩下",remain,"个。")
      else:
            print(apple,"个苹果,平均分给",children,"个小朋友,每个分",result,"个。")
if __name__=='__main__':
      try:
            division()
      except ZeroDivisionError:
            print("\n 出错了 ~-~ ---苹果不能被0个下朋友分")
      except ValueError as e:
            print("输入错误:",e)
      else:
            print("分苹果顺利完成……")

5.2.3 try……except……finally

try:

        block1

except [ExceptionName [as alias]]:

        block2

finally:

        block3

def division():
      print("\n========== 分苹果 ==========\n")
      apple=int(input("请输入苹果的个数:"))
      children=int(input("请输入来了几个小朋友:"))
      result=apple//children
      remain=apple-result*children
      if remain>0:
            print(apple,"个苹果,平均分给",mchildren,"个小朋友,每个分",result,
                        "个,剩下",remain,"个。")
      else:
            print(apple,"个苹果,平均分给",children,"个小朋友,每个分",result,"个。")
if __name__=='__main__':
      try:
            division()
      except ZeroDivisionError:
            print("\n 出错了 ~-~ ---苹果不能被0个下朋友分")
      except ValueError as e:
            print("输入错误:",e)
      else:
            print("分苹果顺利完成……")
      finally:
            print("进行了一次分苹果操作")

 5.2.4 使用raise语句抛出异常

raise [ExceptionName[(reason)]]

def division():
      print("\n========== 分苹果 ==========\n")
      apple=int(input("请输入苹果的个数:"))
      children=int(input("请输入来了几个下朋友:"))
      if apple<children:
            raise ValueError("苹果太少了,不够分……")
      result=apple//children
      remain=apple-result*children
      if remain>0:
            print(apple,"个苹果,平均分给",mchildren,"个小朋友,每个分",result,
                        "个,剩下",remain,"个。")
      else:
            print(apple,"个苹果,平均分给",children,"个小朋友,每个分",result,"个。")
if __name__=='__main__':
      try:
            division()
      except ZeroDivisionError:
            print("\n 出错了 ~-~ ---苹果不能被0个下朋友分")
      except ValueError as e:
            print("出错了:",e)

六、文件及目录操作

6.1 基本文件操作

6.1.1 创建和打开文件

 file=open(filename[,mode[,buffering]])

file:被创建的文件对象

filename:要创建或打开文件的文件名称,需要用单引号或双引号括起来

mode:可选参数,用于指定文件的打开模式

mode参数的参数值说明

r        只读模式打开文件

rb        以二进制格式打开文件,并且采用只读模式

r+        打开文件后,可以读取文件内容,也可以写入新的内容覆盖原有内容

rb+        以二进制格式打开文件,并且采用读写模式

w        以只写模式打开文件

wb        以二进制格式打开文件,并且采用只写模式

w+        打开文件后,先清空所有内容,使其变成一个空文件,对这个空文件有读写权限

wb+        以二进制格式打开文件,并且采用读写模式

a        以追加模式打开一个文件

ab        以二进制格式打开文件,并且采用追加模式

a+        以读写模式打开文件

ab+        以二进制格式打开文件,并且采用追加模式

buffering:可选参数,用于指定读写文件的缓冲模式

open()方法经常实现以下几个功能

1.打开一个不存在的文件时先创建文件

例如创建并打开记录蚂蚁庄园动态的文件

print("\n","="*10,"蚂蚁庄园生态","="*10)
file=open('message.txt','w')
print("\n 即将显示……\n")

 2.以二进制形式打开文件

file=open('pexels-evgeny-tchebotarev-4101555.jpg','rb')
print(file)

 3.打开文件时指定编码方式

在使用open()函数打开文件时,默认采用GBK编码,当打开的文件不是GBK编码时,将抛出异常,所以在打开文件时,直接指定使用的编码方式

例如,打开采用UTF—8编码保存的notice.txt文件

file=open('notice.txt','r',encoding='utf-8')

6.1.2 关闭文件

打开文件后,需要及时关闭,以免对文件造成不必要的破坏

file.close()

6.1.3 打开文件时使用with语句

为了避免打开文件时抛出异常而导致文件不能被及时关闭,可以使用python提供的with语句,保证with语句执行完毕后关闭已经打开的文件

with expression as target:

        with-body

expression:打开文件的open()函数

target:指定一个变量,并且将expression的结果保存到该变量中

with-body:指定with语句体

print("\n","="*10,"蚂蚁庄园生态","="*10)
with open('message.txt','w') as file:
      pass
print("\n 即将显示……\n")
6.1.4 写入文件内容

file.write(string)

例如向蚂蚁庄园的动态文件写入一条信息

print("\n","="*10,"蚂蚁庄园生态","="*10)
file=open('message.txt','w')
file.write("你使用了1张加速卡,小鸡撸起袖子开始双手吃饲料,进食速度大大加快。\n")
print("\n 写入了一条动态……\n")
file.close()

 6.1.5 读取文件

 1.读取指定字符

file.read([size])

with open('message.txt','r') as file:
      string=file.read(9)
      print(string)

使用read(size)文件读取文件时,是从文件的开头读取的,如果要读取部分内容,可以先使用文件对象seek()方法将文件的指针移动到新的位置

 file.seek(offset[,whence])

file:表示已经打开的文件

offset:用于指定移动的字符个数

whence:用于指定从什么位置开始计算

with open('message.txt','r') as file:
      file.seek(19)
      string=file.read(13)
      print(string)

显示蚂蚁庄园的动态

print("\n","="*25,"蚂蚁庄园生态","="*25,"\n")
with open('message.txt','r') as file:
      message=file.read()
      print(message)
print("\n","="*29,"over","="*29,"\n")

2.读取一行

 file.readline()

逐行显示蚂蚁庄园的动态

print("\n","="*35,"蚂蚁庄园生态","="*35,"\n")
with open('message.txt','r') as file:
      number=0
      while True:
            number+=1
            line=file.readline()
            if line =='':
                  break
            print(number,line,end="\n") 
print("\n","="*39,"over","="*39,"\n")

 3.读取全部行

file.readlines()

print("\n","="*25,"蚂蚁庄园生态","="*25,"\n")
with open('message.txt','r') as file:
      message=file.readlines()
      print(message)
print("\n","="*29,"over","="*29,"\n")

 如果文件较大,采取这种方法读取文件内容会慢,这时可以将列表的内容逐行输出

print("\n","="*25,"蚂蚁庄园生态","="*25,"\n")
with open('message.txt','r') as file:
      messageall=file.readlines()
      for message in messageall:
            print(message)
print("\n","="*29,"over","="*29,"\n")

6.2 目录操作 

6.2.1 os和os.path模块

import os

导入os模块后,可以使用该模块提供的变量获取与系统有关的信息:

name:用于获取操作系统类型

 linesep:用于获取当前操作系统上的换行符

 sep:用于获取当前操作系统所使用的路径分隔符

 os模块提供的目录相关的函数

getcwd()        返回当前工作的目录

listdir(path)        返回指定路线下的文件和目录信息

mkdir(path[,mode])        创建目录

makedirs(path1/path2...[,mode])        创建多级目录

rmdir(path)        删除目录

removedirs(path1/path2..)        删除多级目录

chdir(path)        把path设置为当前工作目录

walk(top[,topdown[,onerror]])        遍历目录树

6.2.2 路径

1.相对路径

在学习当前路径前,先了解当前工作目录,如以下代码

import os
print(os.getcwd())

而相对路径就是依赖于当前工作目录,如果当前工作目录下有一个名称为message.txt的文件,

那么打开这个文件时,直接写上文件名就是相对路径

2.绝对路径

 绝对路径是指在使用文件时指定文件的实际路径,如要获取demo\message.txt的绝对路径

import os
print(os.path.abspath(r"demo\message.txt"))

3.拼接路径

os.path.join(path1[,path2[,...]])

例如将"C:\users\Auc\Documents\大一\python.pr"和"differenttree\message.txt"路径拼接在一起

import os
print(os.path.join("C:\users\Auc\Documents\大一\python.pr","differenttree\message.txt"))
6.2.3 判断目录是否存在

例如判断绝对路径”C:\differenttree"是否存在

import os
print(os.path.exists("C:\differenttree"))

 6.2.4 创建目录

1.创建一级目录

os.mkdir(path,mode=0o777)

path:指定要创建的目录

mode:指定数值模式

例如在系统上创建一个C:\demo目录

import os
os.mkdir("C:\\demo")

2.创建多级目录

例如在创建的C:\demo目录下,在创建子目录test\dir\mr

import os
os.makedirs("C:\\demo\\test\\dir\\mr")
6.2.5 删除目录

例如删除刚刚创建的C:\\demo\\test\\dir\\mr目录

import os
os.rmdir("C:\\demo\\test\\dir\\mr")
6.2.6 遍历目录

os.walk(top[,topdown][,onerror][,followlinks])

top:用于指定要遍历内容的根目录

topdown:可选参数,用于指定遍历的顺序

onerror:用于指定错误处理方式,默认为忽略

followlinks:指定在支持的系统上访问由符号连接指向目录

例如遍历指定C:\demo的目录

import os
tuples=os.walk("C:\\demo")
for tuple1 in tuples:
      print(tuple1,"\n")

6.3 高级文件操作

 python内置的os模块除了可以对目录进行操作,还可以对文件进行一些高级操作

os模块提供的与文件相关的函数

access(path,accessmode)        获取对文件是否有指定的访问权限

chmod(path,mode)        修改path指定文件的访问权限

remove(path)        删除path指定的文件路径

rename(src,dst)        将文件或目录src重命名为dst

stat(path)        返回path指定文件的信息

startfile(path[,operation])        使用关联的应用程序打开path指定的文件

6.3.1 删除文件

例如删除当前工作目录下的文件

import os
path=",rsoft.txt"
if os.path.exists(path):
      os.remove(path)
      print("文件删除完毕!")
else:
      print("文件不存在!")
      

6.3.2 重命名文件和目录 

例如想要将C:\demo\message.txt文件重命名为C:\demo\information.txt

import os
src="C:\demo\message.txt"
dst="C:\demo\information.txt"
os.rename(src,dst)
if os.path.exists(src):
      os.rename(src,dst)
      print("文件重命名完毕!")
else:
      print("文件不存在!")
6.3.3 获取文件基本信息

在计算机上创建文件后,该文件本身就会包含一些信息,例如文件的最后一次访问时间,最后一次修改时间,文件大小等基本信息

os.stat(path)

stat()函数返回的对象的常用属性

st_mode        保护模式

st_dev        设备名

st_ino        索引号

st_uid        用户ID

st_nlink        硬链接号

st_gid        组ID

st_size        文件大小,单位为字节

st_atime        最后一次访问时间

st_mtime        最后一次修改时间

st_ctime        最后一次状态变化的时间

import os
fileinfo=os.stat("differenttree")
print("文件完整路径:",os.path.abspath("differenttree"))
print("索引号:",fileinfo.st_ino)
print("设备名:",fileinfo.st_dev)
print("文件大小:",fileinfo.st_size,"字节")
print("最后一次访问时间:",fileinfo.st_atime)
print("最后一次修改时间:",fileinfo.st_mtime)
print("最后一次状态变化时间:",fileinfo.st_ctime)

七、操作数据库

7.1 数据库编程接口

7.1.1 连接对象

数据库连接对象主要提供获取数据库游标对象和提交/回滚事务的方法,以及关闭数据库连接

1.获取连接对象

获取连接对象需要使用connect()函数

connect()函数常用的参数及说明

dsn        数据源名称,给出该参数表示数据库依赖

user        用户名

password        用户密码

host        主机名

database        数据库名称

2.连接对象的方法

connect()函数返回连接对象,这个对象表示目前和数据库的会话。连接对象支持方法如表:

连接对象方法

close()        关闭数据库连接

commit()        提交事务
rollback()        回滚事物

cursor()        获取游标对象,操作数据库

7.1.2 游标对象

游标对象代表数据库中的游标,用于指示抓取数据库操作的上下文。主要提供执行SQL语句、调用存储过程、获取查询结果等方法

游标对象方法

callproc(procname,[,parameters])        调用存储过程,需要数据库支持

close()        关闭当前游标

execute(operation[,parameters])        执行数据库操作,SQL语句

executemany(operation,seq_of_params)        用于批量操作

fetchone()        获取查询结果集中的下一条记录

fetchmany(size)        获取指定数量的记录

fetchall()        获取结果集中的所有记录

nextset()        跳至下一个可用的结果集

arraysize        指定使用fetchmany()获取的行数,默认为1

7.2 使用SQLite

7.2.1 创建数据库文件

创建SQLite数据库文件

import sqlite3
conn=sqlite3.connect('mrsoft.db')
cursor=conn.cursor()
cursor.execute('create table user(if int(10) primary key,name varchar(20))')
cursor.close()
conn.close()

7.2.2 操作SQLite 

1.新增用户数据信息

insert onto 表名(字段名1,...,字段名n) values(字段值1,字段值2,...,字段值n)

import sqlite3
conn=sqlite3.connect('gzgs.db')
cursor=conn.cursor()
cursor.execute('insert into user (id,name) values ("1","MRSOFT")')
cursor.execute('insert into user (id,name) values ("2","Au")')
cursor.execute('insert into user (id,name) values ("3","小艺")')
cursor.close()
conn.commit()
conn.close()

2.查看用户数据信息

import sqlite3
conn=sqlite3.connect('gzgs.db')
cursor=conn.cursor()
cursor.execute('select*from user')
result1=cursor.fetchone()
print(result1)
cursor.close()
conn.close()

3.修改用户数据信息

import sqlite3
conn=sqlite3.connect('gzgs.db')
cursor=conn.cursor()
cursor.execute('update user set name=? where id=?',('MR',1))
cursor.execute('select*from user')
result=cursor.fetchone()
print(result)
cursor.close()
conn.commit()
conn.close()

4.删除用户数据信息

import sqlite3
conn=sqlite3.connect('gzgs.db')
cursor=conn.cursor()
cursor.execute('update user set name=? where id=?',('MR',1))
cursor.execute('select*from user')
result=cursor.fetchall()
print(result)
cursor.close()
conn.commit()
conn.close()

猜你喜欢

转载自blog.csdn.net/m0_74016429/article/details/131999310