• 面向对象编程(练习题)


    1、面向对象三大特性,各有什么用处,说说你的理解

      继承:解决代码重用

      多态:不考虑对象类型的情况下直接使用对象

      封装:明确的区分内外,控制外部对隐藏属性进行操作,隔离复杂度

    2、 类的属性和对象的属性有什么区别?

      类的属性:数据属性,和函数属性,函数绑定给对象使用

      对象的属性:对象就是实例化的类

    3、面向过程编程与面向对象编程的区别与应用场景?

      面向过程:复杂的问题简单化,但是可扩展性差,主要用于,脚本,自动部署,监控等等

      面向对象:对比之下更为复杂,扩展能力强,一切皆对象,主要用于,程序开发,游戏等等

    4、类和对象在内存中是如何保存的。

      以 dict的形式保存正在内存中

    5、什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性

      绑定对象: f1=Foo()#生成对象    foo.func#绑定到对象,绑定到对象之后将会自动传值给func

      绑定到类:就是由类来调用,在需要绑定的函数添加装饰器 @classmethod 

      非绑定方法: 不与类或对象绑定,谁都可以调用 ,需要按正常函数传参,需要在非绑定函数添加装饰器 @staticmethod

    6、使用实例进行 获取、设置、删除 数据, 分别会触发类的什么私有方法

    # item系列就是为了把对象模拟成像字典一样,就可以像字典一样访问
    class A(object):
        def __getitem__(self, item):
            return self.__dict__.get(item)#这里用get进行访问,值不存在也不会报错
    
        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__)   # {}
    
    #输出
    
    {'key': 'val'}
    val
    {}

    7、python中经典类和新式类的区别

      经典类:在python2中,没有继承object的类,以及子类都称之为经典类,继承查找方式为 深度优先。

    #python2 中定义
    class
    A:#经典类 pass class B(object):#新式类 pass

      新式类: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 Sql:
        host= '127.0.0.1'
        port=3306
        db='db1'
        charset='utf8'
        sql='select * from tb1;'
        proc_name='存储过程的名字'
        def __init__(self,*args):
            self.args=args
        def connect(self):
            pass
        def exc(self):
            if self.args == self.sql:
                conn = self.connect(self.host,self.port,self.db,self.charset)
                res=conn.execute(self.sql)
                return res
            elif self.args == self.proc_name:
                conn = self.connect(self.host, self.port, self.db, self.charset, self.proc_name)
                res = conn.call_proc(self.sql)
                return res
    ex=Sql('select * from tb1;')
    print(ex.__dict__)
    
    #输出
    {'args': ('select * from tb1;',)}

    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。(想想也是,不可能是self,对象还没创建,哪来的self) 
    init : 对象的初始化, 是一个实例方法,第一个参数是self。 
    call : 对象可call,注意不是类,是对象。 
    先有创建,才有初始化。即先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()
    class A(object):
        def __init__(self,name):
            self.name=name
    
        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('mlliu')
    a.foo('xiaojiu')
    A.class_foo('xiaojiu')
    a.static_foo('xiaojiu')
    
    #@classmethod 绑定类,自动传值
    #@staticmethod 不绑定类或者对象,普通func,正常传值
    
    #输出
    executing foo(<__main__.A object at 0x000001A2DC5375F8>, xiaojiu)
    executing class_foo(<class '__main__.A'>, xiaojiu)
    executing static_foo(xiaojiu)

    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()
    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
    
    #输出
     ChenRonghua is eating
    #因为@property是自动执行函数,所以在最后调用该方法的时候,不需要加后面的()

    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)

    #111

    #121

    #323

    使用mro()可以看出类的继承顺序,[<class '__main__.Child1'>, <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
    A

    新式类广度优先,super不管当前类的继承关系,会按照实例化的类的MRO列表,一直往后找。
    [<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

    [<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]



    15、请编写一段符合多态特性的代码
    import abc
    
    class Student(metaclass=abc.ABCMeta):
        @abc.abstractmethod #抽象类
        def height(self):
            pass
    
    class Xiaoming(Student):
        @property
        def height(self):
            print('185')
    class Zhangsan(Student):
        @property
        def height(self):
            print('176')
    p1 =Zhangsan()
    p1.height
    p2 =Xiaoming()
    p2.height
    
    #输出
    176
    185

    #多态的好处是你不用管他是什么类型都用同样的方式去调用他

    16、很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?原因就是因为你还没掌握一门面向对象设计利器,即领域建模,请解释下什么是领域建模,以及如何通过其设计面向对象的程序?http://www.cnblogs.com/alex3714/articles/5188179.html 此blog最后面有详解

    领域建模的三字经方法:找名词、加属性、连关系。 

    17、请写一个小游戏,人狗大站,2个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。注意,请按题领域建模的方式来设计类。


    名词:人、狗、血、攻击力、武器、
    加属性:
    人:血、攻击力、武器
    狗:
    血、攻击力、武器
    class Role:
        def __init__(self,name,hp,ad):
            self.name=name
            self.hp=hp
            self.ad=ad
        def attack(self,obj):
            obj.hp -= self.ad
    class People(Role):
        def attack(self,obj):
            super().attack(obj)
            print('%s attack %s'%(self.name,obj.name))
    class Dog(Role):
        def attack(self,obj):
            super().attack(obj)
            print('%s attack %s'%(self.name,obj.name))
    
    
    p1=People ('张三',100,20)
    p2=People('李四',120,25)
    d1=Dog('二哈',200,10)
    d2=Dog('三哈',210,9)
    d3=Dog('三哈',220,8)
    p1.attack(d1)
    print(d1.hp)
    d1.attack(p1)
    print(p1.hp)
    d3.attack(p1)
    print(p1.hp)
    
    #输出
    张三 attack 二哈
    180
    二哈 attack 张三
    90
    三哈 attack 张三
    82

     

    18、编写程序, 在元类中控制把自定义类的数据属性都变成大写.

    class Mymetaclass(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=Mymetaclass):
        country='China'
        tag='Legend of the Dragon' #龙的传人
        def walk(self):
            print('%s is walking' %self.name)
    print(Chinese.__dict__)
    
    
    #输出
    {'__module__': '__main__', 'COUNTRY': 'China', 'TAG': 'Legend of the Dragon', 'walk': <function Chinese.walk at 0x000001EAF1E25730>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None}

    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__)
    
    #输出
    
    <__main__.Chinese object at 0x000002E5068A7358>
    {'NAME': 'egon', 'AGE': 18, 'SEX': 'male'}

    20、编写程序, 编写一个学生类, 要求有一个计数器的属性, 统计总共实例化了多少个学生.

    class Student:
        count =0
        def __init__(self,name,age):
            self.name=name
            self.age=age
            Student.count +=1
    
    stu1=Student('zhangsan',17)
    stu2=Student('lisi',17)
    stu3=Student('xiaohua',17)
    print(Student.count)
    
    #输出
    3

    21、编写程序, A 继承了 B, 俩个类都实现了 handle 方法, 在 A 中的 handle 方法中调用 B 的 handle 方法

    class B:
        def handle(self):
            print('form is B')
    class A(B):
        @property
        def handle(self):
            super().handle()
            print('form is A')
    
    
    a=A()
    a.handle
    
    #输出
    form is B
    form is A

    22、

    编写程序, 如下有三点要求:

    1. 自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化
      e.g
      {
          "egon":{"password":"123",'status':False,'timeout':0},
          "alex":{"password":"456",'status':False,'timeout':0},
      }
    1. 定义用户类,定义方法db,例如 执行obj.db可以拿到用户数据结构
    2. 在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import json
    import time
    info_dic = {
        "egon":{"password":"123",'status':False,'timeout':0},
        "alex":{"password":"456",'status':False,'timeout':0},
    }
    
    
    class User:
    
        def __init__(self):
            self.file_name = 'info.json'
            self.fn_load = open(self.file_name, 'r+', encoding='utf-8')
            self.read_info = json.load(self.fn_load)
            count = 0
            while count<3:
                self.name = input('name').strip()
                self.password = input('password').strip()
                if  self.read_info.get(self.name) and self.read_info[self.name]['password'] == self.password :
                    if time.mktime(time.localtime()) - self.read_info[self.name]['timeout'] > 10:
                        print('登陆成功')
                        self.read_info[self.name]['status'] = 'True'
                        self.read_info[self.name]['timeout'] = (time.mktime(time.localtime()))
                        return
                    else:
                        print('与上一次登陆间隔{}秒,过于频繁禁止登陆'.format(time.mktime(time.localtime()) - self.read_info[self.name]['timeout']))
                        count =3
                else:
                    count += 1
                    print('用户名或密码不正确,请重新输入')
                    continue
            else:
                raise KeyError('登陆失败')
    
        @property
        def db(self):
            print(self.read_info[self.name])
            return self.read_info
        def exit(self):
            self.read_info[self.name]['status'] = 'False'
            self.fn_load.seek(0)
            json.dump(self.read_info,self.fn_load)
            self.fn_load.close()
    
    p1=User()
    p1.db
    p1.exit()
    # p2=User()
    # p2.db
    
    #输出
    nameegon
    password123
    登陆成功
    {'password': '123', 'status': 'True', 'timeout': 1526121027.0}

    定义MySQL类

    要求:

    1.对象有id、host、port三个属性

    2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一

    3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化

    4.为对象定制方法,save和get_obj_by_id,save能自动将对象序列化到文件中,文件路径为配置文件中DB_PATH,文件名为id号,保存之前验证对象是否已经存在,若存在则抛出异常,;get_obj_by_id方法用来从文件中反序列化出对象

    # -*- coding: utf-8 -*-
    import time
    import hashlib
    import json
    import time
    import  sys
    import os
    FILE = 'user_info.json'
    def user():
        return json.load(open(FILE))
    user_info = user()
    
    class Mysql:
        def __init__(self,host,port):
            self.host = host
            self.port = port
            self.id = Mysql.create_id(self)
        def create_id(self):
    
            m = hashlib.md5(str(time.clock()).encode('utf-8'))
            self.id = m.hexdigest()
            return m.hexdigest()
        def save(self):
            for root, dirs, files in os.walk(os.path.dirname(__file__)):
                if self.id in files:
                    raise FileNotFoundError('文件已存在')
    
            json.dump(self.__dict__,open(self.id,'w',encoding='utf-8'))
        def get_obj_by_id(self,id):
            dic1 = json.load(open(id))
    
            print(dic1)
    stu1 = Mysql('127.0.0.1',3306)
    print(stu1.id,stu1.host,stu1.port)
    stu1.get_obj_by_id('f0fbad80768437dfabc5050e0ebd4504')
    stu1.save()
    stu2 = Mysql(user_info['host'],user_info['port'])#
    print(stu2.id,stu2.host,stu2.port)
    stu2.save()
    
    
    
    #输出
    
    
    
    Traceback (most recent call last):
    30565a8911a6bb487e3745c0ea3c8224 127.0.0.1 3306
      File "G:/python练习/网络编程/class_练习题.py", line 36, in <module>
        stu1.save()
    {'host': '127.0.0.1', 'port': 3306, 'id': 'f0fbad80768437dfabc5050e0ebd4504'}
      File "G:/python练习/网络编程/class_练习题.py", line 26, in save
        raise FileNotFoundError('文件已存在')
    FileNotFoundError: 文件已存在

    本章作业

    题目:选课系统开发,要求有四种角色:学校、学员、课程、讲师

    详细要求:

    1. 创建北京、上海 2 所学校

    2. 创建linux , python , go 3个课程 , linuxpy 在北京开, go 在上海开

    3. 课程包含,周期,价格,通过学校创建课程

    4. 通过学校创建班级, 班级关联课程、讲师

    5. 创建学员时,选择学校,关联班级

    6. 创建讲师角色时要关联学校

    7. 提供两个角色接口

    8. 为学员、讲师、管理员分别提供用户界面,并提供对应功能: 1 学员视图, 可以注册, 交学费, 选择班级, 2 讲师视图, 讲师可管理自己的班级, 上课时选择班级, 查看班级学员列表 , 修改所管理的学员的成绩 3 管理视图,创建讲师, 创建班级,创建课程

    注1:上面的操作产生的数据都通过pickle序列化保存到文件里 注2:此作业必须画流程图,图中标注好不同类或对象之间的调用关系



  • 相关阅读:
    python检测挖矿特征的几种方式
    python检测当前端口是否使用
    matlab界面UI设计资料
    python中struct.pack()函数和struct.unpack()函数
    网络编程:主机字节序和网络字节序
    【原创】python中文编码问题深入分析(三):python2.7文件读写中文编码问题
    【原创】python中文编码问题深入分析(二):print打印中文异常及显示乱码问题分析与解决
    ivew定制主题 less ^3.0 时报错 .bezierEasingMixin(); Inline JavaScript is not enabled. Is it set in your options?
    Vue子组件中 data 从props中动态更新数据
    Vue 自动吸顶
  • 原文地址:https://www.cnblogs.com/mjiu/p/9020558.html
Copyright © 2020-2023  润新知