类与对象练习
1、面向对象三大特性,各有什么用处,说说你的理解。
答案: 封装:明确区分内外,控制外部对隐藏属性的操作行为,隔离复杂度。 隐藏实现细节,使代码模块化 多态:多种形态。好处:1、增加程序的灵活性(以不变应万变,不论对象千变万化,同一种方式调用。) 2、增加了程序的可扩展性 一个基类派生出多个子类,子类在继承了方法名的同时,又对父类的方法做出了不同的实现 接口的重用(同一种接口,多种实现) 继承:子类继承父类的特性,但同时又可以拥有自己独特的属性。解决代码重用问题。 扩展已存在的代码
2、类的属性和对象的属性有什么区别?
类的属性分为函数属性与数据属性:数据属性是对所有对象共享的,函数属性是与对象绑定的。 对象的属性是实例化,可能来自于类定义,也可能依据实例化后定义的。
3、面向过程编程与面向对象编程的区别与应用场景?
面向过程编程:好处是复杂问题流程化,简洁化。缺点是可扩展性差。适用于实现后很少改动的程序,或者是一次行的程序。 面向对象编程:好处是可扩展性高,缺点是复杂度远高于面向过程。适用于需求多变的任务中,例如游戏,用户层等。
4、类和对象在内存中是如何保存的。
类是在定义阶段便生成命名空间,以字典形式保存。通过__dict__查看 对象以字典形式保存。
5、什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性?
(1)绑定到对象的方法:在类中定义没有加装饰器修饰的方法。 对象.bound_method() 自动将对象当做第一个参数传入 (2)绑定到类的方法:在类中定义的装饰器@classmethod修饰的方法。 类.bound_method() 自动将类当第一个参数传入 (3)非绑定方法:在类中用@staticmethod装饰器装饰的方法。 没有自动传值,不绑定类和对象,类和对象均可调用。
6、使用实例进行获取、设置、删除数据, 分别会触发类的什么私有方法。
class A(object):
pass
a = A()
a["key"] = "val"
a = a["key"]
del a["key"]
class A(): def __init__(self,msg): self.key = msg def __getitem__(self, item): return self.__dict__.get(item) def __setitem__(self, key, value): self.__dict__[key]=value def __delitem__(self, key): del self.__dict__[key] a = A("name") print(a.__dict__) a["key"] print(a.key) a["key"] = "val" print(a.__dict__) # print(a.key) del a["key"] print(a.__dict__)
7、python中经典类和新式类的区别
多继承中,首先object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。 在python2中,没有显式继承object类的类,以及该类的子类都是经典类。 python2中,显式地声明继承object类,以及该类的子类都是新式类。 新式类是广度优先,python3中都是新式类,根据mro列表中的顺序
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 Exc(object): def __init__(self,host,port,db,charset = "utf-8"): self.host = host self.port = port self.db = db self.charset = charset self.conn = connect(self.host,self.port,self.db,self.charset) def exc1(self,sql): return self.conn.execute(sql) def exc1(self,sql): return self.conn.call_proc(sql) obj = Exc('127.0.0.1',3306,'db1') obj.exc1('select * from tb1;') obj.exc2('存储过程的名字')
9、示例1, 现有如下代码, 会输出什么:
class People(object):
__name = "luffy"
__age = 18
p1 = People()
print(p1.__name, p1.__age)
报错 print(p1._People__name,p1._People__age)
10、示例2, 现有如下代码, 会输出什么:
class People(object):
def __init__(self):
print("__init__")
def __new__(cls, *args, **kwargs):
print("__new__")
return object.__new__(cls, *args, **kwargs)
People()
__new__ __init__
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(10) a.class_foo(23) A.static_foo(12) a.static_foo(23)
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
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指向了新的内存地址
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 A
15、 请编写一段符合多态特性的代码.
class People(object): def talk(self): print("Lalalalala......") class Dog(object): def talk(self): print("woof") class Cat(object): def talk(self): print("mew") def func(animal): animal.talk() p = People() d = Dog() c = Cat() func(p) func(d) func(c)
16、 很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?
原因就是因为你还没掌握一门面向对象设计利器,即领域建模,请解释下什么是领域建模,以及如何通过其设计面向对象的程序?
领域模型,顾名思义,就是需求所涉及的领域的一个建模,更通俗的讲法是业务模型。 定义: 需求到面向对象的桥梁 作用: 1.发掘重要的业务领域概念 2.建立业务领域概念之间的关系 方法: 从用例中找名词 领域建模的三字经方法:找名词、加属性、连关系。 参考:http: // www.cnblogs.com / linhaifeng / articles / 6182264.# html # _label15 http: // www.cnblogs.com / linhaifeng / articles / 7341318.# html
17、 请写一个小游戏,人狗大站,2个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,
人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。注意,请按题14领域建模的方式来设计类。
class People(object): def __init__(self,name,hp=100,hit=50): self.name = name self.hit = hit self.hp = hp def attack(self,obj): obj.hp = obj.hp - self.hit class Dog(object): def __init__(self,name,hp=80,hit=30): self.name = name self.hit = hit self.hp = hp def bite(self,obj): obj.hp = obj.hp - self.hit p1=People("alex") p2=People("jack") d1 = Dog("1") d2 = Dog("2") d3 = Dog("3") d1.bite(p1) p2.attack(d2) print(p1.__dict__) print(d2.__dict__)
18、编写程序, 在元类中控制把自定义类的数据属性都变成大写.
class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): for i in class_dic: if super(Mymeta, self).__init__(class_name,class_bases,class_dic)
19、编写程序, 在元类中控制自定义的类无需init方法
20、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.
class Student(): __count = 0 def __init__(self,name,age): self.name = name self.age = age Student.__count+=1 @staticmethod def total(): print("共有学生%s名"% Student.__count) return # @property std1.info def info(self): print("student:%s,age:%s"%(self.name,self.age)) std1 = Student("alex",19) std2 = Student("Jack",20) Student.total() std1.info()
21、编写程序, A继承了B, 俩个类都实现了handle方法, 在A中的handle方法中调用B的handle方法
class B(): def handle(self): print("B") class A(B): def handle(self): # print("A") super(A, self).handle() a = A() a.handle()
22、编写程序, 如下有三点要求:
a、自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化
e.g
{
"egon": {"password": "123", 'status': False, 'timeout': 0},
"alex": {"password": "456", 'status': False, 'timeout': 0},
}
b、定义用户类,定义方法db,例如执行obj.db可以拿到用户数据结构
c、在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).
密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)用面向对象的形式编写一个老师角色,
并实现以下功能, 获取老师列表, 创建老师、删除老师、创建成功之后通过pickle序列化保存到文件里,并在下一次重启程序时能
import json,time class User(): def __init__(self,name,password): self.name = name self.password = password self.status = False self.timeout = 0 def db(self): f = open("习题5.json","r",encoding="utf-8") data = json.load(f) return data def save(self): obj = {} obj[self.name] = {"password":self.password,"status":self.status,"timeout":self.timeout} f= open("习题5.json","w",encoding="utf-8") json.dump(obj,f) def login(self): f =open("习题5.json","r+",encoding="utf-8") data = json.load(f) count = 0 while count < 3: password = input("password>>:").strip() if password != data[self.name]["password"]: count += 1 continue else: if data[self.name]["timeout"] != 0: if time.time() - data[self.name]["timeout"] >= 10: print("超出时间,不能登录!") break else: data[self.name]["status"] = True f.truncate(0) json.dump(data,f) print("Welcome......") break else: data[self.name]["status"] = True f.truncate(0) json.dump(data, f) print("Welcome......") break else: data[self.name]["status"] = time.time() f.truncate(0) json.dump(data, f) def exit(self): f = open("习题5.json", "r+", encoding="utf-8") data = json.load(f) if data[self.name]["status"] == True: data[self.name]["status"] == False f.truncate(0) json.dump(data, f) else: print("退出状态") user1 = User("alex","123") user1.save() user1.exit() user1.login()