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