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.下列说法中不正确的是( )。
A.类是对象的模板,而对象是类的实例
B.实例属性名如果以__开头,就变成了一个私有变量
C.只有在类的内部才可以访问类的私有变量,外部不能访问
D.在Python中,一个子类只能有一个父类
2.下列选项中不是面向对象程序设计基本特征的是( )。
A.继承 B.多态 C.可维护性 D.封装
3.在方法定义中,访问实例属性x的格式是( )。B
A.x B.self.x C.self[x] D.self.getx()
4. 在面向对象开发中,由类创建的实例,我们称之为()
A. 对象 B.变量 C.方法 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.下列程序的执行结果是( )。class C():f=10class C1(C):passprint(C.f,C1.f)
A.10 10 B.10 pass C.pass 10 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
该类的类名是 ,其中定义了 属性和 属性,它们都是 属性。如果在属性名前加两个下划线(),则属性是 属性。将该类实例化创建对象p,使用的语句为 ,通过p来访问属性,格式为 、 。
person,name,score,公有,私有,p=person(),p.name,p.score
10.Python类的构造方法是 ,它在 对象时被调用,可以用来进行一些属性 操作;类的析构方法是 , 它在 对象时调用,可以进行一些释放资源的操作。
init,生成,初始化,del__,释放
11.可以从现有的类来定义新的类,这称为类的 ,新的类称为 ,而原来的类称为 、父类或超类。
继承,子类,基类
12.创建对象后,可以使用 运算符来调用其成员。
13.下列程序的运行结果为 。100class 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)self.v2=paramobj=child(100)print(obj.v1,obj.v2)
下列程序的运行结果为 。400
class account:def __init__(self,id,balance):self.id=idself.balance=balancedef 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中如何定义一个类的格式
class 类名(object):
成员(方法)
18. 类(class)由哪三个部分构成
类名,属性,方法。
19. 类名的命名规则是什么
要遵循标识符的命名规范,尽量使用大驼峰命名法,命名时做到“见名思意”。
20 . python中如何通过类创建对象
对象名 = 类名()
21 定义类如下:
class Hello(object):
pass
下面说明错误的是( D )。
A. 该类实例中包含dir()方法
B. 该类实例中包含hash()方法
C. 该类实例中包含dir(),还包含hash()
D. 该类没有定义任何方法,所以该实例中没有包含任何方法
22. 定义类如下:class Hello():def showInfo(self):print(self.x)
下面描述正确的是( C )。
A. 这个类的语法有问题
B. 该类可以实例化
C. 在pycharm工具中会出现语法错误,说self没有定义
D. 该类可以实例化,并且能正常通过对象调用showInfo()
23. 关于Python类说法错误的是( B )。
A. 类的实例方法必须创建对象后才可以调用
B. 类的实例方法必须创建对象前才可以调用
C. 类的类方法可以用对象和类名来调用
D. 类的静态属性可以用类名和对象来调用
24. 定义类如下:class Hello(object):def __init__(self,name)self.name=namedef showInfo(self)print(self.name)
下面代码能正常执行的( C )。
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")
以下程序能执行的结果是( D )。
A. a,b,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:def __init__(self,number,name):self.setNumber(number)self.setName(name)def setNumber(self,number):self.__number = numberdef setName(self,name):self.__name = namedef getNumber(self):return self.__numberdef getName(self):return self.__namedef show(self):print("编号:{0},姓名:{1}".format(self.getNumber(),self.getName()))class Student(Person):def __init__(self,number,name,ban,fen):super(Student,self).__init__(number,name)self.setBan(ban)self.setFen(fen)def setBan(self,ban):self.__ban = bandef setFen(self,fen):
4.定义一个水果类,然后通过水果类,创建苹果对象、橘子对象、西瓜对象并分别添加上颜色属性 ```python
水果类
class Fruits(object): pass
苹果对象
apple = Fruits() apple.color = “red”
橘子对象
tangerine = Fruits() tangerine.color = “orange”
西瓜对象
watermelon = Fruits() watermelon.color = “green”
[<br />](https://blog.csdn.net/qq_44034384/article/details/107600403)[<br />](https://blog.csdn.net/qq_44034384/article/details/107600403)<br />[<br />](https://blog.csdn.net/qq_44034384/article/details/107600403)<a name="xLTDq"></a># 2 模块与包<a name="HUdpi"></a>## 2.1 知识点思维导图<a name="vpbxh"></a>### 2.1.1 模块<a name="TdlBF"></a>### 2.1.2 包<a name="gGbBX"></a>## 2.2 练习题<a name="HfHgc"></a>### 2.2.1 基础知识练习题1.以下导入模块方式中错误的是( )<br />A. import mo B. from mo import *<br />C. import mo as moo D.import * from mo<br />2.对于以下导入方式中使用模块math中的sqrt函数正确的方式是( )<br />import math as mymath<br />A. math.sqrt(3) B. sqrt(3) C. mymath.sqrt(3) D.math.mymath.sqrt(3)<br />3.以下关于模块的说法错误的是( )<br />A. 模块就是一个普通的Python程序文件 B.任何一个普通的Python程序文件可以作为模块导入<br />C.模块文件的扩展名可以是txt D.Python 运行时只会从指定的目录中搜索导入的模块<br />4.以下对包的说法错误的是( )<br />A.包可以是一个任何目录 <br />B.包可以是嵌套的<br />C.作为包中的目录要包含特殊的_ __init _ __.py文件<br />D.包目录中的__init__.py文件内容可以为空<br />5.以下关于包和模块的说法错误的是( )<br />A.包中可以包含模块 B.模块中可以包含包<br />C.一般在小规模的项目中使用模块就行了 D.包一般需要在大、中规模的项目中使用<br />6. 以下关于模块说法错误的是( C )。<br />A. 一个xx.py就是一个模块<br />B. 任何一个普通的xx.py文件可以作为模块导入<br />C. 模块文件的扩展名不一定是 .py<br />D. 运行时会从制定的目录搜索导入的模块,如果没有,会报错异常<br />7.在Python中要生成随机数,应该使用()<br />A:math 模块<br /> B:random模块<br /> C:numpy 模块<br /> D:pygame 模块8. 什么是包从物理上看,包就是一个文件夹,在该文件夹下包含了一个__init__.py文件<br />从逻辑上看,包的本质依然是模块<br />包的作用是包含多个模块,但包的本质依然是模块,因此包也可用于包含包9. 怎样定义包创建一个文件夹,该文件夹的名称就是该包的包名<br />在该文件夹内添加一个__init__.py文件<br />10. 包的作用是什么?(1分)<br />该函数包含对外层函数作用域的引用<br />11. __init__.py文件有什么用?(1分)<br />将文件夹变为Python模块<br />12. 使用相对导入时的注意事项(1分)<br />相对导入不能在执行文件中使用,相对导入只能在被导入的模块中使用。<br />13. 模块的搜索顺序(1分)<br />先从内存中找,再从内置中找,sys.path中找<br />14.os和sys模块的作用?(1分)<br />os经常要查找操作文件,读取配置文件信息<br /> Sys提供对解释器使用或维护的一些变量的访问,以及与解释器的交互函数。<br />15. 如何生成一个随机数?(1分)<br />random.randint()<a name="k2fOe"></a>### 2.2.2 程序设计练习题1.编写程序,计算三维坐标中的点x = (5, 6, 7)和y = (8, 9, 9)之间的距离。```pythonimport 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 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包。
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字句的排列,下列哪种是正确的( C )
A.父类在先,子类在后
B.子类在先,父类在后
C.没有顺序,谁在前谁先捕获
D.先有子类,其他如何排列都无关
4.在异常处理中,如释放资源、关闭文件、关闭数据库等由( C )来完成。
A.try字句 B.catch子句 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")
输入的是 结果是:( B )。
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.关于装饰器,下列说法错误的是()。
A. 装饰器是一个包裹函数
B. 装饰器智能有一个参数
C. 通过在函数定义的面前加上@符号阿和装饰器名,使得装饰器函数生效
D. 如果装饰器带有参数,则必须在装饰函数的外层再嵌套一层函数
2.下列函数中,用于使用函数对制定序列进行过滤的是()。
A. map函数 B. select函数 C.filter函数 D.reduce函数
3.下列选项中,不能作为filter函数参数的是()。
A. 列表 B. 元祖 C.字符串 D.整数
4.判断题
闭包是内部函数对外部作用域的变量进行引用。()
当外部函数执行结束,其内部闭包引用的变量一定会立即释放。()
装饰器是一个变量。()
装饰器函数至少要接收一个函数。()
装饰器既能装饰带参数的函数,也能自己带参数。
5.内部函数引用了外部函数作用域的变量,那么内部函数叫作_。
6.装饰器本质上是一个_。
7.装饰器函数需要接收一个参数,这个参数表示_。
8.在函数定义的前面添加装饰器名和_符号,实现对函数的包装。
9.支持参数的装饰器函数需要再多一层__函数。
10._函数会根据提供的函数对制定的序列做映射。
11.map的两个序列的元素个数不一致,那么元素少的序列会以__补齐。
12._函数会对制定序列执行过滤操作。
13.filter传入的函数的返回值是__值。
14.reduce传入的是带有__个参数的函数,该函数不能为None。
15.请简述闭包满足的三个条件
16.请简述装饰器的应用场景
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)


