题目与解答
1-10
#1.面向过程编程与面向对象编程的区别与应用场景?
# 面向过程编程可扩展性较弱,适合写部署脚本,算法编写
# 面向对象编程可扩展性较强,把事物分解为不同对象,适合编写复杂程序开发
#2. 类和对象在内存中是如何保存的。
# 类和对象的属性在内存中是通过dict形式保存的,python创建对象时,会在内存中开辟一块空间
#3. 什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性
# obj.func 绑定到对象的方法,把obj自动传给self
# @classmethod绑定到类的方法,由类来调用把类名自动传给cls
# @staticmethod非绑定方法,不绑定类与对象,类与对象都可以调用。按正常形式传参
# 4.使用实例进行 获取、设置、删除 数据, 分别会触发类的什么私有方法
class A(object):
def __setitem__(self, key, value):
print('setitem')
self.__dict__[key] = value
def __getitem__(self, item):
print('getitem')
return self.__dict__.get(item)
def __delitem__(self, key):
print('delitem')
del self.__dict__[key]
a = A()
print(a.__dict__)
a["key"] = "val"
print(a.__dict__)
del a["key"]
print(a.__dict__)
# --输出结果--
# {}
# setitem
# {'key': 'val'}
# delitem
# {}
#5.python中经典类和新式类的区别
# python2经典类没有继承objcect,查找属性为深度优先
# Python2:经典类
# class A:
#
# 新式类:继承object
# class A(object)查找属性为广度优先
# python3都是新式类,全部继承object
# 8、如下示例, 请用面向对象的形式优化以下代码
#
# def exc1(host, port, db, charset, sql):
# conn = connect(host, port, db, charset)
# conn.execute(sql)
# return xxx
#
#
# def exc2(host, port, db, charset, proc_name)
# conn = connect(host, port, db, charset)
# conn.call_proc(sql)
# return xxx
#
#
# # 每次调用都需要重复传入一堆参数
# exc1('127.0.0.1', 3306, 'db1', 'utf8', 'select * from tb1;')
# exc2('127.0.0.1', 3306, 'db1', 'utf8', '存储过程的名字')
class A:
host = '127.0.0.1'
port = 3306
db = 'db1'
charset = 'utf-8'
def exec1(self,sql):
conn = self.connect()
conn.execute(sql)
@staticmethod
def connect():
print('conn host<%s> port<%s> db<%s> charset<%s>')
def exec2(self,proc_name):
conn = self.connect()
conn.call_proc(proc_name)
# 9、示例1, 现有如下代码, 会输出什么:
class People(object):
__name = "luffy"
__age = 18
p1 = People()
print(p1.__name, p1.__age)
# 会报错,无法通过对象名+属性访问私有属性
# 会抛出错误,因为__name及__age,隐藏了所以不能直接调用,__开头在类执行的时候已经将属性名称更改为'_People__name',
10、示例2, 现有如下代码, 会输出什么:
class People(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
return object.__new__(cls, *args, **kwargs)
# __new__
# __init__
# 先执行__new__方法,再执行__init__,
# __new__创建新的对象,是一个静态方法,第一个参数是cls。
# __init__对象的初始化方法,第一个参数的self,实例本身
# __call__对象的调用方法
11-15
#11 请简单解释Python中 staticmethod(静态方法)和 classmethod(类方法), 并分别补充代码执行下列方法。
class A(object):
def foo(self, x):
print("executing foo(%s, %s)" % (self,x))
@classmethod
def class_foo(cls, x):
print("executing class_foo(%s, %s)" % (cls,x))
@staticmethod
def static_foo(x):
print("executing static_foo(%s)" % (x))
a = A()
a.foo(1)
A.class_foo(2)
a.static_foo(3)
A.static_foo(4)
# 静态方法是非绑定方法,类与对象都可以调用,按照正常形式传参
# classmethod方法是绑定到类方法,第一参数是cls,一般通过类名+方法访问,类名会自动传值给cls
# --输出结果---
# executing foo(<__main__.A object at 0x00000000126AACC0>, 1)
# executing class_foo(<class '__main__.A'>, 2)
# executing static_foo(3)
# executing static_foo(4)
# 12 请执行以下代码,解释错误原因,并修正错误。
class Dog(object):
def __init__(self,name):
self.name = name
@property
def eat(self):
print(" %s is eating" %self.name)
d = Dog("ChenRonghua")
# d.eat()
d.eat
# eat通过@property装饰后,通过d.eat形式访问
# 13 下面这段代码的输出结果将是什么?请解释。
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
# 1 1 1 继承自父类的类属性x,所以都一样,指向同一块内存地址
# 1 2 1 更改Child1,Child1的x指向了新的内存地址
# 3 2 3 更改Parent,Parent的x指向了新的内存地址
print(Child2.mro())
# 继承顺序[<class '__main__.Child2'>, <class '__main__.Parent'>, <class 'object'>]
# 14多重继承的执行顺序,请解答以下输出结果是什么?并解释。
class A(object):
def __init__(self):
print('A')
super(A, self).__init__()
class B(object):
def __init__(self):
print('B')
super(B, self).__init__()
class C(A):
def __init__(self):
print('C')
super(C, self).__init__()
class D(A):
def __init__(self):
print('D')
super(D, self).__init__()
class E(B, C):
def __init__(self):
print('E')
super(E, self).__init__()
class F(C, B, D):
def __init__(self):
print('F')
super(F, self).__init__()
class G(D, B):
def __init__(self):
print('G')
super(G, self).__init__()
if __name__ == '__main__':
g = G()
f = F()
# G
# D
# A
# B
# F
# C
# B
# D
# 新式类按照广度优先搜索
print(G.mro())
# [<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
print(F.mro())
# [<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
# 15、请编写一段符合多态特性的代码
import abc
class Animals(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class Cat(Animals):
def talk(self):
print('miaomiao')
class Dog(Animals):
def talk(self):
print('wangwang')
c = Cat()
c.talk()
d = Dog()
d.talk()
# miaomiao
# wangwang
16-21
# 16 什么是领域建模,以及如何通过其设计面向对象的程序
# 领域建模指的是构建业务模型
# 领域建模的三字经方法:找名词,加属性,连关系
#
# 17 请写一个小游戏,人狗大站,2个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,
# 人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。注意,请按题14领域建模的方式来设计类。
# 名词:人,狗,
# 属性:血,攻击力,武器
class Animals(object):
def __init__(self,name,life,weapon):
self.name = name
self.life = life
self.weapon = weapon
def attack(self,obj):
obj.life -= self.weapon
class People(Animals):
def attack(self,obj):
super().attack(obj)
print('%s attack %s'%(self.name,obj.name))
class Dog(Animals):
def attack(self, obj):
super().attack(obj)
print('%s attack %s' % (self.name, obj.name))
p1 = People('张三',100, 20)
p2 = People('李四',100, 30)
d1 = Dog('刺狼',100, 40)
d2 = Dog('狼1',100, 30)
d3 = Dog('狼2',100, 20)
p1.attack(d1)
print(d1.life)
p2.attack(d2)
print(d2.life)
#
d1.attack(p1)
print(p1.life)
d2.attack(p2)
print(p2.life)
d3.attack(p1)
print(p1.life)
# # 18、编写程序, 在元类中控制把自定义类的数据属性都变成大写.
class Mymeta(type):
def __new__(cls, name, bases,attrs):
update_attrs = {}
for k,v in attrs.items():
if not callable(v) and not k.startswith('__'):
update_attrs[k.upper()] = v
else:
update_attrs[k] = v
return type.__new__(cls, name, bases, update_attrs)
class Chinese(metaclass=Mymeta):
country='China'
tag = 'Legend'
def walk(self):
print('%s is walking' %self.name)
print(Chinese.__dict__)
# 19、编写程序, 在元类中控制自定义的类无需init方法.
class Mymetaclass(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError('must use keyword argument for key function')
obj = object.__new__(self) #创建对象,self为类Foo
for k,v in kwargs.items():
obj.__dict__[k.upper()]=v
return obj
class Chinese(metaclass=Mymetaclass):
country='China'
tag='Legend of the Dragon' #龙的传人
def walk(self):
print('%s is walking' %self.name)
p=Chinese(name='egon',age=18,sex='male')
print(p.__dict__)
# 20、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.
class Student:
count = 0
def __init__(self,name):
Student.count += 1
self.name = name
s1 = Student('k1')
s2 = Student('k2')
s3 = Student('k3')
print(s3.count)
# 21、编写程序, A 继承了 B, 俩个类都实现了 handle 方法, 在 A 中的 handle 方法中调用 B 的 handle 方法
class B:
def handle(self):
print('handle B')
class A(B):
def handle(self):
super().handle()
print('handle A')
a1 = A()
a1.handle()
22
# 22.编写程序, 如下有三点要求:
#
#
# 自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化
# e.g
# {
# "egon":{"password":"123",'status':False,'timeout':0},
# "alex":{"password":"456",'status':False,'timeout':0},
# }
# 定义用户类,定义方法db,例如 执行obj.db可以拿到用户数据结构
# 在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).\
# 密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)
import json
import time
import os
user_dict = {
"egon":{"password":"123",'status':False,'timeout':0},
"alex":{"password":"456",'status':False,'timeout':0}
}
class User():
def __init__(self):
if not os.path.isfile('user.json'):
self.write()
def db(self):
with open('user.json','r',encoding='utf-8') as f:
return json.load(f)
def login(self):
count = 0
while count < 3:
user = input('user > ').strip()
passwd = input('password >').strip()
user_info = self.db()
if user in user_info.keys():
password = user_info.get(user).get("password")
time_o = user_info.get(user).get("timeout")
login_t = time.time()
print(user, login_t, time_o)
if login_t - time_o > 10:
if passwd == password:
print('user login success')
user_info.get(user)["status"] = True
user_info.get(user)["timeout"] = time.time()
break
else:
print('user or password is incorrect')
count += 1
else:
print('过于频繁禁止登陆,请间隔至少10s')
continue
else:
print('user login count > 3')
user_info.get(user)["timeout"] = time.time()
self.save_user(user_info)
def exit(self,user):
user_info = self.db()
if user in user_info.keys():
if user_info.get(user)["status"]:
print('用户 %s 正在登陆,准备退出' %user)
time.sleep(2)
user_info.get(user)["status"] = False
self.save_user(user_info)
else:
print('user is not exist')
@staticmethod
def save_user(obj):
with open('user.json', 'r+', encoding='utf-8') as f:
json.dump(obj, f, ensure_ascii=False, indent=2)
@staticmethod
def write():
with open('user.json','w',encoding='utf-8') as f:
json.dump(user_dict,f,ensure_ascii=False, indent=2)
u = User()
# u.write() # 写入json
# print(u.db()) # 读 json文件
# u.login()
# u.exit('egon')
23-27
23.用面向对象的形式编写一个老师角色, 并实现以下功能, 获取老师列表, 创建老师、删除老师、创建成功之后通过 pickle 序列化保存到文件里,并在下一次重启程序时能
# 读取到创建的老师, 例如程序目录结构如下.
# .
# |-- bin/
# | |-- main.py 程序运行主体程序(可进行菜单选择等)
# |-- config/
# | |-- settings.py 程序配置(例如: 配置存储创建老师的路径相关等)
# |-- db 数据存储(持久化, 使得每次再重启程序时, 相关数据对应保留)
# | |-- teachers/ 存储所有老师的文件
# | |-- ... ...
# |-- src/ 程序主体模块存放
# | |-- __init__.py
# | |-- teacher.py 例如: 实现老师相关功能的文件
# | |-- group.py 例如: 实现班级相关的功能的文件
# |-- manage.py 程序启动文件
# |-- README.md 程序说明文件
# 24根据23 题, 再编写一个班级类, 实现以下功能, 创建班级, 删除班级, 获取班级列表、创建成功之后通过 pickle 序列化保存到文件里,并在下一次重启程序时能
# 读取到创建的班级.
#
# 25根据 23题, 编写课程类, 实现以下功能, 创建课程(创建要求如上), 删除课程, 获取课程列表
#
# 26根据23 题, 编写学校类, 实现以下功能, 创建学校, 删除学校, 获取学校列表
#
# 27通过23题, 它们雷同的功能, 是否可以通过继承的方式进行一些优化
代码:
MyPickle.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/6/3 17:30
# @File : MyPickle.py
# @Software: luffy_test
import pickle
import os
class MyPickle(object):
def __init__(self,file_name):
self.file_name = file_name
def dump(self,obj):
with open(self.file_name,'ab') as f:
pickle.dump(obj,f)
def loaditer(self):
if os.path.isfile(self.file_name):
with open(self.file_name, 'rb') as f:
while True:
try:
obj = pickle.load(f)
yield obj
except:
break
def edit(self,obj): # 编辑,修改
f2 = MyPickle(self.file_name+'.old')
for item in self.loaditer():
if item.name == obj.name:
f2.dump(obj)
else:
f2.dump(item)
os.remove(self.file_name)
os.rename(self.file_name+'.old',self.file_name)
def delobj(self, obj):
f2 = MyPickle(self.file_name + '.old')
for item in self.loaditer():
if item.name != obj.name:
f2.dump(item)
else:
print('del name',obj.name)
os.remove(self.file_name)
os.rename(self.file_name + '.old', self.file_name)
settings.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/6/21 23:00
# @File : settings.py
# @Software: python_utils
import os
path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),'db')
teacher.py
from config.settings import path
from src.MyPickle import MyPickle
from prettytable import PrettyTable
import os
class Behavior(object):
path = ''
def fetchobj(self, obj):
pick = MyPickle(obj.path)
iter_obj = pick.loaditer()
for item in iter_obj:
if item.name == obj.name:
print('find obj ',item.__dict__)
return obj
else:
print('obj is not exist')
def createobj(self,obj):
pick = MyPickle(obj.path)
if not self.fetchobj(obj):
pick.dump(obj)
print('create object', obj.__dict__)
else:
print('object exists')
def delobj(self,obj):
pick = MyPickle(obj.path)
pick.delobj(obj)
print('del object', obj.__dict__)
def fetchall(self,obj):
pick = MyPickle(obj.path)
iter_obj = pick.loaditer()
obj_list = []
for item in iter_obj:
obj_list.append(item)
return obj_list
def printobj(self,obj):
obj_list = self.fetchall(obj)
tb = PrettyTable()
k = 0
for item in obj_list:
if k == 0:
tb.field_names = item.__dict__.keys() # 字段名
tb.add_row(item.__dict__.values()) # 增加行
tb.align = 'l'
k += 1
# print(item.__dict__)
print(tb)
class Teacher(Behavior):
path = os.path.join(path, "teacher_obj")
def createobj(self):
self.name = input('teacher name >')
self.age = input('teacher age >')
super().createobj(self)
class Classes(Behavior):
path = os.path.join(path, "class_obj")
def createobj(self):
self.name = input('class name >')
super().createobj(self)
class School(Behavior):
path = os.path.join(path, "school_obj")
def createobj(self):
self.name = input('school name >')
self.addr = input('school addr >')
super().createobj(self)
class Subject(Behavior):
path = os.path.join(path, "subject_obj")
def createobj(self):
self.name = input('subject name >')
super().createobj(self)
main.py
def interactive(object):
menu = """
------- {obj}管理 ---------
1. 创建{obj}(功能已实现)
2. 查看{obj}(功能已实现)
3. 删除{obj}(功能已实现)
4. 查看{obj}列表
5. 退出
""" .format(obj=object.__name__) # 获得类名
menu_dic = {
'1': 'createobj',
'2': 'fetchobj',
'3': 'delobj',
'4': 'printobj'
}
exit_flag = False
while not exit_flag:
print(menu)
user_option = input(">>:").strip()
if user_option in menu_dic:
obj = object()
if obj.fetchall(obj):
print('last create obj', obj.fetchall(obj)[-1].__dict__) # 打印上次创建对象
if user_option == '2' or user_option == '3':
obj.name = input('input {obj} name >'.format(obj=object.__name__))
getattr(obj, menu_dic.get(user_option))(obj) # 反射调用对象的方法
elif user_option == '1':
getattr(obj, menu_dic.get(user_option))()
elif user_option == '4':
print('{0:*^30}'.format(object.__name__ + ' List'))
getattr(obj, menu_dic.get(user_option))(obj)
else:
print('EXIT')
exit_flag = True
else:
print("Option does not exist!", "error")
exit_flag = True
manage.py
from bin import main
from src.teacher import Teacher
from src.teacher import Classes
from src.teacher import School
from src.teacher import Subject
if __name__ == '__main__':
main.interactive(School)
main.interactive(Teacher)
main.interactive(Subject)
---执行结果--
------- School管理 ---------
1. 创建School(功能已实现)
2. 查看School(功能已实现)
3. 删除School(功能已实现)
4. 查看School列表
5. 退出
>>:1
last create obj {'name': 'kk', 'addr': 'bei'}
school name >老男孩
school addr >沙河
obj is not exist
create object {'name': '老男孩', 'addr': '沙河'}
------- School管理 ---------
1. 创建School(功能已实现)
2. 查看School(功能已实现)
3. 删除School(功能已实现)
4. 查看School列表
5. 退出
>>:4
last create obj {'name': '老男孩', 'addr': '沙河'}
*********School List**********
{'name': 'luffy', 'addr': 'shahe'}
{'name': 'kk', 'addr': 'bei'}
{'name': '老男孩', 'addr': '沙河'}
------- School管理 ---------
1. 创建School(功能已实现)
2. 查看School(功能已实现)
3. 删除School(功能已实现)
4. 查看School列表
5. 退出
>>:3
last create obj {'name': '老男孩', 'addr': '沙河'}
input School name >kk
del name kk
del object {'name': 'kk'}
------- School管理 ---------
1. 创建School(功能已实现)
2. 查看School(功能已实现)
3. 删除School(功能已实现)
4. 查看School列表
5. 退出
>>:4
last create obj {'name': '老男孩', 'addr': '沙河'}
*********School List**********
{'name': 'luffy', 'addr': 'shahe'}
{'name': '老男孩', 'addr': '沙河'}
------- School管理 ---------
1. 创建School(功能已实现)
2. 查看School(功能已实现)
3. 删除School(功能已实现)
4. 查看School列表
5. 退出
>>:5
Option does not exist! error
------- Teacher管理 ---------
1. 创建Teacher(功能已实现)
2. 查看Teacher(功能已实现)
3. 删除Teacher(功能已实现)
4. 查看Teacher列表
5. 退出
>>:2
last create obj {'name': 'egon', 'age': '30'}
input Teacher name >alex
find obj {'name': 'alex', 'age': '18'}
------- Teacher管理 ---------
1. 创建Teacher(功能已实现)
2. 查看Teacher(功能已实现)
3. 删除Teacher(功能已实现)
4. 查看Teacher列表
5. 退出
>>:4
last create obj {'name': 'egon', 'age': '30'}
*********Teacher List*********
{'name': 'hyang', 'age': '12', 'classes': 'p9', 'subject': 'python'}
{'name': '4', 'age': 'dd', 'classes': 'ad', 'subject': 'dg'}
{'name': 'jk', 'age': '11', 'classes': 'dd', 'subject': 'pyhton'}
{'name': 'alex', 'age': '18'}
{'name': 'egon', 'age': '30'}
------- Teacher管理 ---------
1. 创建Teacher(功能已实现)
2. 查看Teacher(功能已实现)
3. 删除Teacher(功能已实现)
4. 查看Teacher列表
5. 退出
>>:1
last create obj {'name': 'egon', 'age': '30'}
teacher name >yuan
teacher age >20
obj is not exist
create object {'name': 'yuan', 'age': '20'}
------- Teacher管理 ---------
1. 创建Teacher(功能已实现)
2. 查看Teacher(功能已实现)
3. 删除Teacher(功能已实现)
4. 查看Teacher列表
5. 退出
>>:4
last create obj {'name': 'yuan', 'age': '20'}
*********Teacher List*********
{'name': 'hyang', 'age': '12', 'classes': 'p9', 'subject': 'python'}
{'name': '4', 'age': 'dd', 'classes': 'ad', 'subject': 'dg'}
{'name': 'jk', 'age': '11', 'classes': 'dd', 'subject': 'pyhton'}
{'name': 'alex', 'age': '18'}
{'name': 'egon', 'age': '30'}
{'name': 'yuan', 'age': '20'}
------- Teacher管理 ---------
1. 创建Teacher(功能已实现)
2. 查看Teacher(功能已实现)
3. 删除Teacher(功能已实现)
4. 查看Teacher列表
5. 退出
>>:5
Option does not exist! error
------- Subject管理 ---------
1. 创建Subject(功能已实现)
2. 查看Subject(功能已实现)
3. 删除Subject(功能已实现)
4. 查看Subject列表
5. 退出
>>:1
last create obj {'name': 'python'}
subject name >C++
obj is not exist
create object {'name': 'C++'}
------- Subject管理 ---------
1. 创建Subject(功能已实现)
2. 查看Subject(功能已实现)
3. 删除Subject(功能已实现)
4. 查看Subject列表
5. 退出
>>:2
last create obj {'name': 'C++'}
input Subject name >python
find obj {'name': 'python'}
------- Subject管理 ---------
1. 创建Subject(功能已实现)
2. 查看Subject(功能已实现)
3. 删除Subject(功能已实现)
4. 查看Subject列表
5. 退出
>>:2
last create obj {'name': 'C++'}
input Subject name >java
obj is not exist
------- Subject管理 ---------
1. 创建Subject(功能已实现)
2. 查看Subject(功能已实现)
3. 删除Subject(功能已实现)
4. 查看Subject列表
5. 退出
>>:4
last create obj {'name': 'C++'}
*********Subject List*********
+--------+
| name |
+--------+
| C |
| python |
| C++ |
+--------+
------- Subject管理 ---------
1. 创建Subject(功能已实现)
2. 查看Subject(功能已实现)
3. 删除Subject(功能已实现)
4. 查看Subject列表
5. 退出
>>:5
Option does not exist! error
Process finished with exit code 0