复习参考:https://blog.csdn.net/a2011480169/article/details/73087097
1、面向对象三大特征
继承:类与类之间,什么是什么的关系,解决代码重用问题
多态:多态:同一个事物的多种形态:比如:动物有,人、狗、猪
多态性,可以在不考虑对象类型的情况下而直接使用对象,接口重用 分为静态多态性和动态多态性
所谓多态指的是一个父类的引用既可以指向父类的对象,也可以指向子类的对象,它可以根据当前时刻指向的不同,自动调用不同对象的方法,这就是多态的概念。
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 规范子类的调用函数,子类相同函数必须与父类一致
def talk(self):
pass
class People(Animal):
def talk(self):
print(f"{self} is talking")
pass
class Dog(Animal):
def talk(self):
print(f"{self} is talking")
pass
peo = People()
dog = Dog()
# peo.tal()
# dog.talk()
def func(obj):
obj.talk()
func(peo)
func(dog)
静态多态性指:任何类型都可以用运算符 + 进行运算
动态多态性指:
封装:明确的区分内外,控制外部对隐藏属性的操作行为,隔离复杂度
2、类的属性和对象的属性有什么区别:
类的属性:分为数据属性和函数属性。
类的数据属性时所有对象共享的,类的函数属性是绑定给对象用的,称为绑定到对象的方法。
对象的属性:可能来自类定义,即类属性。(类定义自身、类定义继承两种途径)
对象的属性还可能是该对象实例定义的,即对象属性
3、面向过程编程与面向对象编程的区别与应用场景:
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么问题。
优点:复杂问题流程化,进而简单化。缺点:可扩展性和可维护性差
适用:一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务。
面向对象编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述。与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界而非流程的模拟,是一种“上帝式”的思维方式。
优点:更容易扩展和修改,更容易理解 缺点:编程复杂度高、可控性差
适用:应用于需求经常变化的软件中,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
4、类和对象在内存中是如何保存的
以字典的方式保存,代码在类定义阶段便会执行,因而会产生新的名称空间,用来存放类的变量名和函数名,可以通过__dict__查看。
__dict__查出字典,key为属性名,value为属性值
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"
]
# item系列就是为了把对象模拟成像字典一样,就可以像字典一样访问 class A(object): 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() a['key'] = "val" print(a.__dict__) # {'key': 'val'} b = a["key"] print(b) # val del a["key"] print(a.__dict__) # {}
7、python 中的经典类和新式类的区别?
python2中有 经典类和新式类
python2中经典类,没有继承object的类,以及他的子类都称之为经典类
class Foo: pass class Bar(Foo): pass
python2中新式类,继承object的类,以及他的子类都称之为新式类
class Foo(object): pass class Bar(Foo): pass
python3,无论是否继承object,都默认继承object,均为新式类
class Foo:# 一个类没有继承object,默认继承object pass print(Foo.__bases__) 结果:(<class '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 MysqlHandler: 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): self.conn.execute(sql) return XXX def exc2(self,sql): self.conn.call_proc(sql) return XXX obj = MysqlHandler('127.0.0.0',3306,'db1') obj.exc1('select * from tb1') obj.exc2('存储过程的名字')
9、实例1,实现如下代码,会输出什么?(封装知识)
__x == _类名__x
class People(object): __name = "luffy" # 类的数据属性 正确的是 _People__name __age = 18 # 类的数据属性 p1 = People() print(p1.__name, p1.__age) # 对象p1.__name ==
出错 外部无法直接通过 __x这个名字访问,必须通过 p1._People__x 才能访问
class People(object): __name = "luffy" age = 18 p1 = People() print(p1._People__name, p1.age)
luffy 18
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__ 先访问 def __new__ 再访问 def __init__
11、请简单解释Python中 staticmethod(静态方法)和 classmethod(类方法), 并分别补充代码执行下列方法。
静态方法:非绑定方法,类和对象都可调用
类方法:绑定给类的方法,类调用
绑定到对象的方法:没有被任何装饰器装饰的方法
非绑定方法@staticmethod
不管是类中的方法,还是类中函数,默认情况下都是绑定给对象使用的,对象是自动传到类中
不管是绑定方法还是非绑定方法,对象都可以调用
当类调用类中的方法时候,是不会进行自动传值的,也就是说,函数有几个参数,
我们就得传递进去几个参数。如果想结果正常运行,那么在类名调用talk()的时候,将参数一一都传
class Foo: def __init__(self,name): self.name =name def walk(self): print('123') @classmethod # 绑定方法 绑定给类调用,对象也可以调用 def tell(cls): print(cls) @staticmethod # 非绑定方法 类和对象都可以调用 def fun(x,y): print(x+y) f = Foo('egon') f.walk() Foo.walk(Foo)#类主动传参在没有装饰器的情况下依旧可以调用类里面的函数 #--------------------------------- Foo.tell() # 类的绑定方法 f.tell() #-------------------------------- Foo.fun(1,2) # 非绑定方法 f.fun(2,3)
12、请执行以下代码,解释错误并纠正/@property 可将函数属性转化为数据属性
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()
TypeError: 'NoneType' object is not callable
更正把d.eat()------->d.eat
@property 可将函数属性转化为数据属性
将函数定义成特性(property)后,对象调用时直接 对象名.函数名 就可以调用, 不要加()
13、下面这段代码的输出结果将是什么?请解释
class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x, Child1.x, Child2.x) # 1,1,1 Child1.x = 2 print(Parent.x, Child1.x, Child2.x) # 1,2,1 Parent.x = 3 print(Parent.x, Child1.x, Child2.x) # 3,2,3
原因:
# 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 = G() ---- G--->D-->A---->B
f = F() -----F--->C--->B---->D--->A
15、请编写符合多态特性的代码
import abc # 用abc模块实现抽象类 class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def talk(self): pass class People(Animal): def talk(self): print(f"{self} is talking") pass class Dog(Animal): def talk(self): print(f"{self} is talking") pass peo = People() dog = Dog() # peo.tal() # dog.talk() def func(obj): obj.talk() func(peo) func(dog)
16、很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?
原因就是因为你还没掌握一门面向对象设计利器,即领域建模,请解释下什么是领域建模
以及如何通过其设计面向对象的程序?http://www.cnblogs.com/alex3714/articles/5188179.html 此blog最后面有详解
领域模型,顾名思义,就是需求所涉及的领域的一个建模,更通俗的讲法是业务模型。 定义: 需求到面向对象的桥梁 作用: 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 Animal: def __init__(self,name,life_value,aggressivity): self.name = name self.aggressivity = aggressivity self.life_value = life_value def attack(self,enemy): enemy.life_value -= self.aggressivity print(f"{self.name},进攻了{enemy.name},敌方剩余生命值{enemy.life_value}") class People(Animal): camp = '正方' def attack(self,enemy): super().attack(enemy) class Dog(Animal): camp = '反方' if __name__ == '__main__': print('--人狗大战游戏----') print('----请创建2个人和3条狗进行游戏---') peo = People('aa',100,20) peo2 = People('bb',120,20) dog = Dog('keke',100,20) dog2 =Dog('duole',120,15) dog3 = Dog('hashi',150,10) peo.attack(dog)
18、编写程序, 在元类中控制把自定义类的数据属性都变成大写.
19、编写程序, 在元类中控制自定义的类无需init方法.
20、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.
class Student: count = 0 def __init__(self,name,age): self.name = name self.age = age Student.count += 1 stu = Student('aa',18) stu2 = Student('bb',20) print(Student.count)
21、编写程序, A 继承了 B, 俩个类都实现了 handle 方法, 在 A 中的 handle 方法中调用 B 的 handle 方法
class B: def __init__(self): pass def __handle(self): print('调用B的handle') class A(B): def __init__(self): pass def handle(self): print('调用A的handle') a = A() a._B__handle()
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 pickle,json,time # 用json写入文件 # dict = {'egon':{'password':'123','status':'False','timeout':0}, # 'alex':{'password':'456','status':'False','timeout':0} # } # with open('account','a+',encoding='utf-8') as f: # json.dump(dict,f) class People: def __init__(self): # self.name = name # self.password = password # self.status = status # self.timeout = timeout pass @property #特性 def db(self): with open('account', 'r+', encoding='utf-8') as f: return json.load(f) def exit(self): choice = input(''' 选择 1 退出登录 选择 其它 继续 >''') if choice == '1': if dict[name]['status'] == True: dict[name]['status'] = False exit() else: exit() else: pass def start_time(self): dict[name]['timeout'] = time.time() with open('account','w+',encoding='utf-8') as f: json.dump(dict,f) def rewrite_time(self): dict[name]['timeout'] = 0 with open('account', 'w+', encoding='utf-8') as f: json.dump(dict, f) if __name__ == '__main__': obj = People() dict = obj.db count = 3 while count > 0: name = input('name:').strip() password = input('password:').strip() if name in dict: if password == dict[name]['password']: if dict[name]['timeout']!=0: #这一步很关键 if time.time() - dict[name]['timeout'] <= 10: print('-----welcome-----') dict[name]['status'] = True obj.rewrite_time() obj.exit() break else: print('锁定时间超过10秒,不允许用户再次登录,请联系管理员') break else: print('-----welcome-----') dict[name]['status'] = True obj.exit() break else: count -= 1 if count == 0: print('----密码输错三次账户锁定-----') obj.start_time() obj.exit() break else: print(f'-----密码输入错误,您还有{count}次机会------') obj.exit() continue else: print('----您输入的用户不存在------')
23、元类:python 中类方法、类 实例方法、静态方法有何区别?
类方法:是类对象的方法,在定义时需要在上方使用“@classmethod”进行装饰,形参为cls,
表示类对象,类对象和实例对象都可调用;
类实例方法:是类实例化对象的方法,只有实例对象可以调用,形参为self,指代对象本身;
静态方法:是一个任意函数,在其上方使用“@staticmethod”进行装饰,可以用对象直接调用,
静态方法实际上跟该类没有太大关系。