面向对象--本章总结---练习题

复习参考: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["key"= "val"

= 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”进行装饰,可以用对象直接调用,
静态方法实际上跟该类没有太大关系。



原文地址:https://www.cnblogs.com/foremostxl/p/9613636.html