題目與解答
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
