1 面向对象程序设计
1.1 知识点思维导图
1.1.1 面向对象概述思维导图
1.1.2 类和对象的定义思维导图

1.1.3 魔术方法的思维导图
1.1.4 私有成员与封装
1.1.5 类的继承
1.1.6 类的多态特性
1.1.7 类的属性和实例属性
1.2 练习题
1.2.1 基础知识练习题
1.下列说法中不正确的是( D )。
A.类是对象的模板,而对象是类的实例
B.实例属性名如果以 开头,就变成了一个私有变量
C.只有在类的内部才可以访问类的私有变量,外部不能访问
D.在Python中,一个子类只能有一个父类
2.下列选项中不是面向对象程序设计基本特征的是( C )。
A.继承 B.多态 C.可维护性 D.封装
3.在方法定义中,访问实例属性x的格式是( )。B
A.x B.self.x C.self[x] D.self.getx()
4. 在面向对象开发中,由类创建的实例,我们称之为( A )
A. 对象 B.变量 C.方法 D.函数
下列程序的执行结果是( D )。
class Point:x=10y=10def __init__(self,x,y):self.x=xself.y=ypt=Point(20,20)print(pt.x,pt.y)
A.10 20 B.20 10 C.10 10 D.20 20
6.下列程序的执行结果是( A )。class C():f=10class C1(C):passprint(C.f,C1.f)
A.10 10 B.10 pass C.pass 10 D.运行出错
现有如下代码, 会输出什么: D
class People(object):__name = "heima"__age = 18p1 = People()print(p1.__name, p1.__age)
A.heima 18
B.heima18
C.”heima”18
D. 程序错误,得不到输出
8.在Python中,定义类的关键字是 。class
9.类的定义如下:class person:name='Liming'score=90
该类的类名是 person ,其中定义了 name 属性和 scroe 属性,它们都是 类的 属性。如果在属性名前加两个下划线(__),则属性是 私有 属性。将该类实例化创建对象p,使用的语句为 p=person() ,通过p来访问属性,格式为 p.name 、 p.score 。
10.Python类的构造方法是 init() ,它在 创建 对象时被调用,可以用来进行一些属性 初始化 操作;类的析构方法是 del() , 它在 销毁 对象时调用,可以进行一些释放资源的操作。
11.可以从现有的类来定义新的类,这称为类的 继承 ,新的类称为 子类 ,而原来的类称为 基类 、父类或超类。
12.创建对象后,可以使用 . 运算符来调用其成员。
13.下列程序的运行结果为 100
class Account:def __init__(self,id):self.id=idid=888acc=Account(100)print(acc.id)
14.下列程序的运行结果为 100,100 。
class parent:def __init__(self,param):self.v1=paramclass child(parent):def __init__(self,param):parent.__init__(self,param)#super().__init__(param)self.v2=paramobj=child(100)print(obj.v1,obj.v2)
- 下列程序的运行结果为 。
class account: #银行账户def __init__(self,id,balance):self.id=id #账户名self.balance=balance #余额def deposit(self,amount): #存款方法self.balance+=amountdef withdraw(self,amount): #取款方法self.balance-=amountacc1=account('1234',100)acc1.deposit(500)acc1.withdraw(200)print(acc1.balance)
- 什么是类,什么是对象?
类:对一类事物的描述,是抽象的、概念上的定义。
对象:实际存在的该类事物的每个个体,因而也称实例(instance)。
类是对象的抽象,对象是类的实例。
17. python中如何定义一个类的格式 :::info class 类名(object):
成员(方法) ::: 类(class)由哪三个部分构成
类名,属性,方法。
19. 类名的命名规则是什么
要遵循标识符的命名规范,尽量使用大驼峰命名法,命名时做到“见名思意”。
20 . python中如何通过类创建对象 :::info 对象名 = 类名() ::: 21 定义类如下:
class Hello(object):pass
下面说明错误的是( D )。
A. 该类实例中包含dir()方法
B. 该类实例中包含hash()方法
C. 该类实例中包含dir(),还包含hash()
D. 该类没有定义任何方法,所以该实例中没有包含任何方法
22. 定义类如下: Bclass Hello():def showInfo(self):print(self.x)
下面描述正确的是( )。
A. 这个类的语法有问题
B. 该类可以实例化
C. 在pycharm工具中会出现语法错误,说self没有定义
D. 该类可以实例化,并且能正常通过对象调用showInfo()
23. 关于Python类说法正确的是( C )。
A. 类的实例方法必须创建对象后才可以调用
B. 类的实例方法必须创建对象前才可以调用
C. 类的类方法可以用对象和类名来调用
D. 类的静态属性可以用类名和对象来调用
24. 定义类如下: Cclass Hello(object):def __init__(self,name)self.name=namedef showInfo(self)print(self.name)
下面代码能正常执行的( )。
A. h = Hello
h.showInfo()
B. h = Hello()
h.showInfo(“张三”)
C. h = Hello(“张三”)
h.showInfo()
D. h = Hello(“admin”)
showInfo
25. 定义类如下:class A():def a():print("a")class B ():def b():print("b")class C():def c():print(c)class D(A,C):def d():print("d")
以下程序能执行的结果是( )。 :::info d=D()
d.a()
d.c()
d.d() ::: A. a,c,d B. a,d
C. d,a D. 执行会报错
26. init方法有什么作用,如何定义
init方法用来监听对象的实例化过程。
def init(self):
pass
27. str方法有什么作用,使用时应注意什么问题
str方法用来追踪对象的属性值的变化的。
str方法不能再添加任何参数,
str方法必须有一个返回值,返回值必须为字符串类型。
28. 对象方法中的”self”代表什么
self代表的是类的实例对象(注意不是类本身)
29.要修改一个对象的属性有几种方法,分别是什么?
直接修改属性的值。
通过方法修改属性的值。
通过方法对属性的值进行递增/减。
30. 保护属性安全性的一般处理方式是什么?
把这个属性设置为私有的,通过一些封装的方法进行操作。
31. 要想将一个属性私有化,该怎么做?
在属性名前面加上两个下划线,即:属性名。
32. 如何将上述的name改成私有属性
self.name = name
33. 如果子类中没有定义init方法,但是要实例化一个对象,那此时会自动调用父类的构造方法吗?
如果本身没有定义init方法,会调用直接继承给它的第一个父类的init方法。
34. 简单描述什么是单继承
一个子类只能有一个父类,被称为单继承。
35. 如果子类重写了init方法,那么在实例化对象的时候,你觉得会调用哪个构造方法,是父类的还是子类的?
子类重写了init方法,默认会调用自己的。
36. 当子类重写init方法,在实例化对象的时候,如果想要调用父类的init方法该怎么办?
需要显示进行调用,即:super().init()。
37. 在一个对象销毁的时候,可以在什么函数释放资源?
通过魔法方法,del。
38. 简单描述什么是多继承
一个子类可以有多个父类,称为多继承。
39. 简单描述什么是重写?
子类不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
40 . 学过Python面向对象的知识,应该都知道魔法方法,下面请你来说说new()和init()的区别?
(1)new()是一个静态方法,而init()是一个实例方法;
(2)new()方法会返回一个创建的实例,而init()什么都不返回;
(3)只有在new()返回一个cls的实例时后面的init()才能被调用;
(4)当创建一个新实例时调用new(),初始化一个实例时用init()。1.2.2 程序设计题
1.定义一个Person类,提供可以重新设置私有属性name的方法,限制条件为字符串长度小于10,才可以修改。
# Person类class Person(object):def __init__(self):self.__name = ""def set_name(self, name):if len(name) < 10:self.__name = name
1.设计一个Circle类来表示园,这个类包含圆的半径以及求周长和面积的函数。再使用这个类创建半径为1~100的圆,并计算出相应的周长及面积。
class circle:def __init__(self,radius):self.radius=radiusdef length(self):return self.radius*2*3.14def area(self):return self.radius**2*3.14a=int(input("输入半径:"))c=circle(a)print("周长为:",c.length(),"面积为:",c.area())
2.编写程序并测试,有一个汽车类Vehicle,类中的私有数据成员为车轮个数wheels和车重weight;小车类Car是汽车类vehicle派生类,其中包含载客人数passenger_load,默认4人;卡车类Truck是汽车类vehicle派生类,其中包含载客人数passenger_load和载重量payload。
提示:编写类时要使用get和set方法,Vehicle类定义display()显示车轮和重量,Car和Truck中要对display()进行同名覆盖。class Vehicle:def __init__(self,wheels,weight):self.setWheels(wheels)self.setWeight(weight)def setWheels(self,wheels):self.__wheels = wheelsdef setWeight(self,weight):self.__weight = weightdef getWheels(self):return self.__wheelsdef getWeight(self):return self.__weightdef display(self):print("车轮={0},重量={1}".format(self.getWheels(),self.getWeight()))class Car(Vehicle):def __init__(self,wheels,weight,passenger_load = 4):super(Car,self).__init__(wheels,weight)self.setPassenger(passenger_load)def setPassenger(self, passenger_load,):self.__passenger_load = passenger_loaddef getPassenger(self):return self.__passenger_loaddef display(self):print("车轮={0},重量={1},载客人数={2}".format(self.getWheels(),self.getWeight(),self.getPassenger()))class Truck(Vehicle):def __init__(self,wheels,weight,passenger_load,payload):super(Truck, self).__init__(wheels,weight)self.setPassenger(passenger_load)self.setPayload(payload)def setPassenger(self,passenger_load):self.__passenger_load = passenger_loaddef setPayload(self,payload):self.__payload = payloaddef getPassenger(self):return self.__passenger_loaddef getPayload(self):return self.__payloaddef display(self):print("车轮={0},重量={1},载客数={2},载重量={3}".format(self.getWheels(),self.getWeight(),self.getPassenger(),self.getPayload()))vehicle = Vehicle(4,10000)vehicle.display()car = Car(4,5000,4)car.display()truck = Truck(8,20000,12,12000)truck.display()
3.编写一个学生和教师数据输入和输出的程序。学生数据包括编号、姓名、班号、和成绩;教师的数据含有编号、姓名、职称和部门。要求设计一个person类,作为学生数据操作类student和教师数据操作类teacher的基类。
class Person(object):def __init__(self,number,name):self.setNumber(number)self.setName(name)def setNumber(self,number):self.__number=numberdef setName(self,name):self.__name=namedef getName(self):return self.__namedef getNumber(self):return self.__numberdef show(self):print("编号为:"+str(self.getNumber())+",名字为:"+str(self.getName()))class Student(Person):def __init__(self,number,name,classNumber,grade):super(Student,self).__init__(number,name)Person.__init__(self,number,name)self.setClassNumber(classNumber)self.setGrade(grade)def setClassNumber(self,classNumber):self.__classNumber=classNumberdef setGrade(self,grade):self.__grade=gradedef getClassNumber(self):return self.__classNumberdef getGrade(self):return self.__gradedef show(self):super(Student,self).show()print("学生班号为:"+str(self.getClassNumber())+",成绩为:"+str(self.getGrade()))class Teacher(Person):def __init__(self,number,name,title,department):super(Teacher,self).__init__(number,name)Person.__init__(self,number,name)self.setTitle(title)self.setDepartment(department)def setDepartment(self,department):self.__department=departmentdef setTitle(self,title):self.__title=titledef getTitle(self):return self.__titledef getDepartment(self):return self.__departmentdef show(self):super(Teacher,self).show()print("教师职称是:"+str(self.getTitle())+",教师部门是:"+str(self.getDepartment()))if __name__=='__main__':hexiaojiang=Person(20181611701,'He xiao jiang')hexiaojiang.show()studentWang=Student(20181611750,'Wang hao jia',8,100)studentWang.show()teacherNa=Teacher(520521,'Nasinhore','讲师','教学部')teacherNa.show()
4.定义一个水果类,然后通过水果类,创建苹果对象、橘子对象、西瓜对象并分别添加上颜色属性 ```python
水果类
class Fruits(object): pass
苹果对象
apple = Fruits() apple.color = “red”
橘子对象
tangerine = Fruits() tangerine.color = “orange”
西瓜对象
watermelon = Fruits() watermelon.color = “green”
<a name="bGzTx"></a># 2 模块与包<a name="VVhFn"></a>## 2.1 知识点思维导图<a name="VhXtI"></a>### 2.1.1 模块<a name="RskpH"></a>### 2.1.2 包<a name="lXLJ7"></a>## 2.2 练习题<a name="Us769"></a>### 2.2.1 基础知识练习题1.以下导入模块方式中错误的是( )<br />A. import mo # mo.函数名( ) mo.类名( ) mo.变量名<br />B. from mo import * <br />C. import mo as moo # moo.函数名( ) moo.类名( ) moo.变量名<br />D.import * from mo #语法错误<br />2.对于以下导入方式中使用模块math中的sqrt函数正确的方式是( C )```pythonimport math as mymath
A. math.sqrt(3)
B. sqrt(3)
C. mymath.sqrt(3)
D.math.mymath.sqrt(3)
3.以下关于模块的说法错误的是( C )
A. 模块就是一个普通的Python程序文件
B.任何一个普通的Python程序文件可以作为模块导入
C.模块文件的扩展名可以是txt
D.Python 运行时只会从指定的目录中搜索导入的模块
4.以下对包的说法错误的是( A )
A.包可以是一个任何目录 (directory,(文件夹 , floder))
B.包可以是嵌套的
C.作为包中的目录要包含特殊的 __init .py文件
D.包目录中的init__.py文件内容可以为空
5.以下关于包和模块的说法错误的是( B )
A.包中可以包含模块
B.模块中可以包含包
C.一般在小规模的项目中使用模块就行了
D.包一般需要在大、中规模的项目中使用
6. 以下关于模块说法错误的是( C )。
A. 一个xx.py就是一个模块
B. 任何一个普通的xx.py文件可以作为模块导入
C. 模块文件的扩展名不一定是 .py
D. 运行时会从指定的目录搜索导入的模块,如果没有,会报错异常
7.在Python中要生成随机数,应该使用( B )
A:math 模块
B:random模块
C:numpy 模块
D:pygame 模块
- 什么是包
从物理上看,包就是一个文件夹,在该文件夹下包含了一个init.py文件
从逻辑上看,包的本质依然是模块
包的作用是包含多个模块,但包的本质依然是模块,因此包也可用于包含包
- 怎样定义包
创建一个文件夹,该文件夹的名称就是该包的包名
在该文件夹内添加一个init.py文件
10. 包的作用是什么?
该函数包含对外层函数作用域的引用
11. init.py文件有什么用?
将文件夹变为Python包
12. 使用相对导入时的注意事项
相对导入不能在执行文件中使用,相对导入只能在被导入的模块中使用。
13. 模块的搜索顺序
先从内存中找,再从内置中找,sys.path中找
14.os和sys模块的作用?
os经常要查找操作文件,读取配置文件信息
Sys提供对解释器使用或维护的一些变量的访问,以及与解释器的交互函数。
15. 如何生成一个随机数?
random.randint()
2.2.2 程序设计练习题
1.编写程序,计算三维坐标中的点x = (5, 6, 7)和y = (8, 9, 9)之间的距离。
x(x1,y1,z1) y=(x2,y2,z2)
dist=sqrt( (x2-x1)^2+(y2-y1)^2+(z2-z1)^2 )
import mathx = (5, 6, 7)y = (8, 9, 9)distance = math.sqrt(sum([(a - b) ** 2 for a, b in zip(x, y)]))
def distance(x, y):import mathd = (x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2 + (x[2] - y[2]) ** 2return round(math.sqrt(d), 2)a = (5, 6, 7)b = (8, 9, 9)d = distance(a, b)print(d)
2.编写程序,计算正整数的阶乘,并将阶乘的结果中各个数字相加,最后得到其和。例如,6!= 720,7+2+0=9。
import mathn=input("n=")result=math.factorial(int(n)) #math.factorial()用于计算n的阶乘print(result)sum=0for i in str(result):sum=sum+int(i)# while result != 0:# print("result=",result)# i=result % 10# sum=sum+i# print("i=",i)# print("sum=",sum)# result=result // 10print("sum=",sum)
import mathdef compute(n):n = math.factorial(n)ans = sum(int(c) for c in str(n))return ans
def fac_sum(n):from functools import reduces2 = str(reduce(lambda x, y: x*y, range(1, n+1)))sums = 0for i in s2:sums = sums + int(i)print(sums)fac_sum(6)
3.在 package_test目录下创建 test1.py、test2.py、init.py 文件,test.py 为测试调用包的代码,然后在 package_test 同级目录下创建 test.py文件并调用 package_test包。
A=999B=777def fun():print("fun is invoked.")
class X(object):def __init__(self):print("Object of class X is created.")
import package_test.test1import package_test.test2print(package_test.test1.A)print(package_test.test1.B)package_test.test1.fun()obj=package_test.test2.X()
3 异常处理
3.1 知识点思维导图
3.2 练习题
3.2.1 基础知识练习题
1.python中用来手动抛出异常的关键字是( C )
A.try B.except C.raise D.finally
2.( C )类是所有异常类的父类
A.Throwable B.Error C.Exception D.BaseException
3.对于except字句的排列,下列哪种是正确的( B )
A.父类在先,子类在后
B.子类在先,父类在后
C.没有顺序,谁在前谁先捕获
D.先有子类,其他如何排列都无关
4.在异常处理中,如释放资源、关闭文件、关闭数据库等由( C )来完成。
A.try字句 B.except子句 C.finally字句 D.raise子句
5.当方法遇到异常又不知如何处理时,下列哪种说法是正确的( B )
A.捕获异常 B.抛出异常 C.声明异常 D.嵌套异常
6. 以下哪项Python能正常启动( D )。
A. 拼写错误 B. 错误表达式 C. 缩进错误 D. 手动抛出异常
7. 有关异常说法正确的是( B )。
A. 程序中抛出异常终止程序
B. 程序中抛出异常不一定终止程序
C. 拼写错误会导致程序终止
D. 缩进错误会导致程序终止
8. 对以下程序描述错误的是( A )。
try:# 语句块1except IndexError as i:# 语句块2
A. 该程序对异常处理了,因此一定不会终止程序
B.该程序对异常处理了,不一定不会因异常引发终止
C. 语句块1,如果抛出IndexError 异常,不会因为异常终止程序
D. 语句块2 不一定会执行
9. 程序如下:
try:number = int(input("请输入数字:"))print("number:",number)print("=======hello======")except Exception as e:# 报错错误日志print("打印异常详情信息: ",e)else:print("没有异常")finally:# 关闭资源print("finally")print("end")
输入的是 结果是:( )。
A. number: 1
打印异常详情信息: invalid literal for int() with base 10:
finally
end
B. 打印异常详情信息: invalid literal for int() with base 10:
finally
end
C. ========hello===========
打印异常详情信息: invalid literal for int() with base 10:
finally
end
D. 以上都正确
10.异常和错误有什么区别?
异常是指因为程序执行过程中出错而在正常控制流以外采取的行为。严格来说,语法错误和逻辑错误不属于异常,但有些语法错误往往会导致异常,例如由于大小写拼写错误而访问不存在的对象,或者试图访问不存在的文件,等等。
3.2.2 程序设计练习题
1.定义input_password函数,提示用户输入密码.如果用户输入长度<8,抛出异常。如果用户输入长度>=8,返回输入的密码
def input_password():while True:password=input('请输入密码')try:if len(password)>8:raise Exception("len too long!")else:passfinally:print('执行一次')print(input_password())
2.定义一个异常类 OverNumberError ,当用户输入数字大于 100 时,抛出异常内容 “输入数字过大!”
class OverNumberError(Exception):def __init__(self):super(Exception, self).__init__()def __str__(self):return "输入数字过大!"try:user_input = input("输入一个数字:")if int(user_input) > 100:raise OverNumberError()except OverNumberError as e:print(e)
3.编写一个计算减法的方法,当第一个数小于第二个数时,抛出“被减数不能小于减数”的异常
def jianfa(a, b): # 定义一个函数try: # 尝试if a < b: # 如果a小于braise BaseException('被减数{}不能小于减数{}'.format(b,a))else: #否则print(a - b) # 输出a-bexcept BaseException as f : #print(f) # 触发,抛出异常jianfa(4,5) # 第一个数4,第二个数是5
4.简单使用异常处理,输入两个数a,b , 其中b必须为零,进行a/b的算式,让你的程序抛出“被除数不能为零”的异常。
try:x = int(input('请输入第一个数'))y = int(input('请输入第二个数字'))print(x / y)y = x + '5'print(x)s = input('输入一个数')except (ZeroDivisionError,TypeError) as e:print(e)
5.编写一个计算减法的方法,自己输入两个数,当第一个数小于第二个数时,抛出“被减数不能小于减数”的异常。
def jianfa(a,b):if a<b:raise BaseException('被减数不能小于减数')#return 0else:return a-btry:a=int(input())b=int(input())print(jianfa(a, b))print("没遇到自己定义的错误") #不打印except:print("被减数不能小于减数")finally:print("OK")
6.使用异常处理try … except… 打开一个不存在的文件。
try:with open('non_exist.txt',mode='r') as f1:print('file opend!')f1.close()except:print('file is not exist!')print('DONE!')
8.运算a/b,先判断b是不是等于零,如果b等于零,抛出分母为零异常。
def yunsuan(a,b):if b==0:raise Exception('分母为零')else:print('a/b')
9.编写代码,调用CCircle方法,计算圆的面积。并且自己定义一个异常类,如果半径为负值,抛出自己定义的异常。
import mathdef RadioError(Exception):def __init__(self,info):self.info=infodef show(self)print(self.info)def CCircle(r):if r<0:raise RadiosError('半径为负值')else:print(math.pi*(r**2))
10.从命令行得到5个整数,放入一列表中,然后打印输出,要求:如果输入数据不为整数,要捕获产生的异常,显示“请输入整数”,捕获输入参数不足5个的异常(越界),显示“请输入至少5个整数”。
list_1=[]for i in range(5):try:j=int(input('请输入一个整数:'))except:print('请输入整数!')else:list_1.append(j)if len(list_1) != 5:raise Exception ('请输入至少五个整数!')
4 迭代器和生成器
4.1 知识点思维导图
4.2 练习题
4.2.1 基础知识练习题
1.什么是迭代器?
就是每次重复都是基于上次结果而继续的。
2.为何要有迭代器?
列表元组等可以利用索引进行取值,但是字典和集合是无序的,没有办法根据索引进行取值,要想取字典的值就要用迭代器,就是取值的工具。
3.什么是可迭代的对象?
可能被for循环的,比如字符串,列表,字典,集合,元组。
4.什么是迭代器对象?
内置有iter 和next的方法的对象都是迭代器对象。
5.如何得到自定义的迭代器?
定义iter和next方法
6.多个叠加装饰器的加载顺序与执行顺序是?
加载顺序是:从下往上
执行顺序是:从上往下
7.请用自己的话解释一下“迭代”的概念?
“迭代”是重复反馈过程的活动,其目的通常是为了接近并达到所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。
8.迭代器是一个容器吗?
不是。因为我们耳熟能详的容器像列表、字典、元组都是可以存放数据的,而迭代器就是实现了next()方法的对象(用于遍历容器中的数据)。
9.迭代器可以回退(获取上一个值)吗?
迭代器的性质决定没有办法回退,只能往前进行迭代。但这并不是什么很大的缺点,因为我们几乎不需要在迭代中进行回退操作。
10.如何快速判断一个容器是否具有迭代功能?
判断该容器是否拥有 next() 和 iter() 魔法方法。
11. for 语句如何判断迭代器里边已经取空了?
迭代器通过 next() 方法每次返回一个元素,并指向下一个元素。如果当前位置已无元素,通过抛出 StopIteration 异常表示。
- 在 Python 原生支持的数据结构中,你知道哪一个是只能用迭代器访问的吗?
对于原生支持随机访问的数据结构(如tuple、list),可以使用迭代器或者下标索引的形式访问,但对于无法随机访问的数据结构 set 而言,迭代器是唯一的访问元素的方式。
4.2.2 程序设计练习题
1.使用生成器函数打印斐波那契数列前n项值。
def Fibonaqi_Gen(number):n, a, b = 0, 0, 1while n < number:yield ba, b = b, a+bn += 1return "Done"#生成器打印需要用循环for i in Fibonaqi_Gen(6):print(i)#或者next()函数fibonaqi3 = Fibonaqi_Gen(3)print("next()")print(next(fibonaqi3))print(next(fibonaqi3))print(next(fibonaqi3))#使用try,except来获取return返回的信息fn = Feibonacci_Gen(6)while True:try:f = next(fn)print("fibonacci:", f)except StopIteration as e:print(f"StopIteration->{e.value}")break
2.写一个迭代器,要求输出2000年至今为止的所有闰年。
import datetime as dtclass LeapYear:def __init__(self):self.now = dt.date.today().yeardef isLeapYear(self,year):if (year % 4 == 0 and year % 100 != 0) or (year % 100 == 0 ):return Trueelse:return Falsedef __iter__(self):return selfdef __next__(self):while not self.isLeapYear(self.now):self.now -= 1temp = self.nowself.now -= 1return temp
3.要求自己写一个 MyRev 类,功能与 reversed() 相同(内置函数 reversed(seq) )是返回一个迭代器,是序列 seq 的逆序显示)
class MyRev:def __init__(self,data):self.data = dataself.index = len(data)def __iter__(self):return selfdef __next__(self):if self.index == 0:raise StopIterationself.index -= 1return self.data[self.index]
5 闭包和装饰器
5.1 知识点思维导图
5.2 练习题
5.2.1 基础知识练习题
1.关于装饰器,下列说法错误的是( B)。
A. 装饰器是一个包裹函数
B. 装饰器只能有一个参数
C. 通过在函数定义的面前加上@符号和装饰器名,使得装饰器函数生效
D. 如果装饰器带有参数,则必须在装饰函数的外层再嵌套一层函数
4.判断题
闭包是内部函数对外部作用域的变量进行引用。()
当外部函数执行结束,其内部闭包引用的变量一定会立即释放。()
装饰器是一个变量。()
装饰器函数至少要接收一个函数。()
装饰器既能装饰带参数的函数,也能自己带参数。
5.内部函数引用了外部函数作用域的变量,那么内部函数叫作_。
6.装饰器本质上是一个_。
7.装饰器函数需要接收一个参数,这个参数表示_。
8.在函数定义的前面添加装饰器名和_符号,实现对函数的包装。
9.支持参数的装饰器函数需要再多一层__函数。
5.2.2 程序设计练习题
1.写一个闭包函数 clo,接收整数参数 n ,返回一个函数 foo,foo 函数的功能是把 foo 参数和 n 相乘并把结果返回。
def clo(n):def foo(*args):number = 5return number*nreturn fooprint(clo(5)())
2.编写装饰器,在每次执行被装饰函数之前打印一句’每次执行被装饰函数之前都得先经过这里,这里根据需
求添加代码
def wrapper(func): #装饰器函数def inner(*args, **kwargs): #装饰器内部函数print("每次执行被装饰函数之前都得先经过这里,这里根据需求添加代码")return func(*args, **kwargs) #调用被装饰函数return inner #返回装饰器函数内部函数名@wrapper # 这里等同于fn = wrapper(fn)def func(): #被装饰函数print("func is running...")func() #调用函数
3.编写装饰器,在每次执行被装饰函数之前让用户输入用户名,密码,给用户三次机会,登录成功之后,才能访
问该函数.
def user_auth(func): #装饰器函数def inner(*args, **kwargs): #装饰器内部函数for i in range(3, 0, -1):while 1:print("33[31;0m请先登录33[0m".center(50, "*"))name = input("Username: ").strip()if name == "":print("33[31;0m用户名不能为空.33[0m")continuepwd = input("Password: ").strip()if pwd == "":print("33[31;0m密码不能为空.33[0m")continueif name == userinfo_dic["username"] and pwd == userinfo_dic["pwd"]: #认证通过print("33[32;0m登录成功.33[0m")return func(*args, **kwargs) #调用目标函数else: #认证失败if i == 1:exit("33[31;0m用户名或密码错误.程序自动退出.33[0m")else:print("33[31;0m用户名或密码错误.您还有%s次机会哦.33[0m" % (i-1))breakreturn inner #返回装饰器函数内部函数名@user_auth # 这里等同于fn = wrapper(fn)def func(): #目标函数print("func is running...")userinfo_dic = {"username": "alex", "pwd":"123456"} #保存用户名和密码func()
6 数据库与GUI编程
6.1 知识点思维导图
6.2 练习题
6.2.1 程序设计练习题
- 随机生成10个人名和对应的密码; 人名由三个汉字或者2个汉字组成,
姓 = [许, 张, 赵, 钱, 孙, 李, 朱, 杨]
名 = [彬, 群, 宁, 盼, 龙, 欢, 丹]
密码统一6位, 由字母和字符组成;
存储上述用户信息到数据库中,保存在数据库users中的userinfo表中;
import randomfrom random import choice as choiceimport stringimport pymysql# 生成指定位数密码, 前 n-1 位为数字, 最后一位为字符;def create_passwd(count=6):nums = random.sample(string.digits, count - 1)letters = random.sample(string.ascii_letters, 1)return "".join(nums + letters)# a = create_passwd()# print(a,type(a))# 生成随机的姓名, 有两个或三个汉字组成 ;def create_name():first = ['许', '张', '赵', '钱', '孙', '李', '朱', '杨']second = ['彬', '群', '宁', '盼', '龙', '欢', '丹']last = ['彬', '群', '宁', '盼', '龙', '欢', '丹', ' ' ]name = choice(first) + choice(second)+ choice(last)return name.rstrip()# print(create_name(),type(create_name()))def main():# 1.连接数据库 host user passwd charsetconn = pymysql.connect(host='localhost',user='root',password='redhat',db='users',charset='utf8')# 2.创建游标对象cur = conn.cursor()# 3.创建表create_table='create table userinfo (name varchar(30),password varchar(30));'cur.execute(create_table)# 4.加数据插入userinfo表中n = int(input("生成数据数:"))# 往数据库表中插入 n 条随机数据 ;for i in range(n):# cur.execute('insert into userinfo values("user1", "123");')sqli = "insert into userinfo values ('%s', '%s');" %(create_name(), create_passwd())cur.execute(sqli)# 提交数据,并关闭连接 ;conn.commit()cur.close()main()
2.编写一个程序,实现如下所示的用户登录验证GUI程序。
数据库服务器:192.168.179.231
数据库:test
用户名:test
密码:123456
数据表名:users
import pymysqlimport wx#导入wxPython包class MainFrame(wx.Frame):#定义MainFrame类(代表程序的主窗体),它是wx.Frame类的子类def __init__(self):#主窗体的构造方法super().__init__(parent=None,id=-1,title="程序主窗体",size=(400,300))#调用wx.Frame类的构造方法来创建程序主窗体self.panel=wx.Panel(parent=self)#定义了panel对象,他是个wx.Panel类对象,代表一个面板self.title=wx.StaticText(parent=self.panel,label="请输入用户名和密码",pos=(140,20))#定义一个wx.StaticText控件类对象,这是一个文本标签类self.userLabel=wx.StaticText(self.panel,label="用户名:",pos=(50,50))self.userText=wx.TextCtrl(self.panel,pos=(100,50),size=(235,25),style=wx.TE_LEFT)#定义一个wx.TextCtrl控件对象,这是一个文本输入框,其中,pos代表位置,size代表大小,style代表是文本框的风格self.passLabel=wx.StaticText(self.panel,label="密 码:",pos=(50,90))self.passText=wx.TextCtrl(self.panel,pos=(100,90),size=(235,25),style=wx.TE_PASSWORD)self.btnOK=wx.Button(self.panel,label="确 定",pos=(105,130))#定义了按钮类wx.Button的对象self.btnCancel=wx.Button(self.panel,label="取 消",pos=(195,130))self.Bind(wx.EVT_BUTTON,self.OnClickOK,self.btnOK)#绑定btnOK的按钮点击事件的事件事件处理方法是OnClickOKself.Bind(wx.EVT_BUTTON,self.OnClickCancel,self.btnCancel)def validate(self,user,passwd):conn = pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test",charset="utf8")cursors = conn.cursor()sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'# print(sqlStatement)cursors.execute(sqlStatement)data = cursors.fetchone()# print(data)if data:return Trueelse:return Falsedef OnClickOK(self,event):#定义MainFrame类的方法OnClickOK,用来进行btnOk(“确定”)被点击之后事件处理#user="Tom"#passwd="123456"#这是要验证的用户名和密码userName=self.userText.GetValue()#从userText中取出输入的用户名,使用TextCtrl对象的GetValue()方法取出输入的内容userPass=self.passText.GetValue()#从passText中取出输入的密码message = ""if userName == "" or userPass == "":message = "用户名或密码不能为空"elif self.validate(userName,userPass) :message = "用户"+userName+"登录成功"else:message = "用户名或者密码不匹配"wx.MessageBox(message,"登录提示")#创建一个MessageBox对象,显示提示信息def OnClickCancel(self,event):#OnClickCancel定义Cancel按钮点击后的事件处理程序self.userText.SetValue("")#将userText文本框清空self.passText.SetValue("")if __name__ == "__main__" :app=wx.App()#定义一个wx.App类的对象appmainFrame=MainFrame()mainFrame.Show()app.MainLoop()#启动app的事件循环,等待捕获用户在GUI界面上的操作(即控件事件),然后进入事件响应程序,执行事件响应程序#执行完成以后,回到事件循环。直至捕获到退出事件发生,才结束应用程序。# import pymysql# conn = pymysql.connect(host="192.168.179.231",user="test",password="123456",database="test", charset="utf8")# cursors = conn.cursor()# user="mike"# passwd="123456"# sqlStatement='select name,passwd from users where name="'+user+'" and passwd="'+passwd+'"'# print(sqlStatement)# cursors.execute(sqlStatement)# data = cursors.fetchone()# print(data)


