首页 > 技术文章 > 面向对象练习题

mike-liu 2018-07-03 09:36 原文

1、面向对象三大特性,各有什么用处,说说你的理解。
封装(Encapsulation):在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法

继承(Inheritance):一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承

多态(Polymorphism):多态是面向对象的重要特性,简单点说:一种接口,多种实现,指一个基类中派生出不同的子类,且每个子类在继承了同样的方法
名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态

  

2、类的属性和对象的属性有什么区别?
类有两种属性:数据属性和函数属性
类的数据属性:是所有对象共享的
类的函数属性:是绑定给对象用的,称为绑定到对象的方法
对象的属性是类的实例化

  

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

面向过程:
概念:核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么,基于面向过程设计程序就好比在设计一条流水线,是一种机械化的思维方式
优点是:
复杂的问题流程化,进而简单化

缺点是:
扩展性比较差

面向对象:
概念:核心是“对象”二字,

优点是:
可扩展性好

缺点是:
编程的复杂度比较高

应用场景:
需求经常变化的软件中

面向过程:个人视角
面向对象:上帝视角

4、类和对象在内存中是如何保存的。
类的对象的属性:以字典形式保存的
5、什么是绑定到对象的方法、绑定到类的方法、解除绑定的函数、如何定义,如何调用,给谁用?有什么特性
①、绑定到对象的方法:没有被任何装饰器装饰的方法
为对象量身定制
对象.boud_method(),自动将对象当作第一个参数传入
(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)
由对象来调用,
def tell_info(self):
obj.tell_info()

②、绑定到类的方法:用classmethod 装饰器的方法
由类来调用
def from_conf(cls):
class.from_conf()

③、非绑定方法
不与类和对象绑定,谁都可以调用,没有自动传值
@staticmethod
def create_id():
obj.create_if()/class.create_id()

  

6、使用实例进行获取、设置、删除数据, 分别会触发类的什么私有方法  
class A(object):
    def __getitem__(self, item):
        return self.__dict__.get(item)

    def __delitem__(self, key):
        del self.__dict__[key]

    def __setitem__(self, key, value):
        self.__dict__[key] = value


a = A()

a["key"] = "val"
print(a.__dict__)
# a = a["key"]
# print(a)
del a["key"]
print(a.__dict__)

  

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

1.只有在Python2中才分新式类和经典类,Python3中统一都是新式类
2.在Python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在Python2中,显式的声明继承object的类,以及该类的子类,都是新式类
4.在Python3中,无论是否继承object,都默认继承object,即Python3中所有类都是新式类

当类是经典类时,按照:深度优先的方式查找
当类是新式类时,按照:广度优先的方式查找

  

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):
        return self.conn.execute(sql)

    def exc2(self, sql):
        return self.conn.call_proc(sql)

obj = MySQLHandler('127.0.0.1', 3306, 'db1')
obj.exc1('select * from tb1;')
obj.exc2('存储过程的名字')

  

9、请简单解释Python中staticmethod(静态方法)和 classmethod(类方法), 并分别补充代码执行下列方法。

staticmethod(静态方法):不与类和对象绑定,类和对象都可以调用,但是没有自动传值那么一说
classmethod(类方法):绑定到类的方法,是给类使用,类在使用时会将类本身当做参数传给类方法的第一个参数

  

10、下面这段代码的输出结果将是什么?请解释

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指向了新的内存地址

  

11、多重继承的执行顺序,请解答以下输出结果是什么?并解释。

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

  

12、请编写一段符合多态特性的代码

  

import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass

class People(Animal):
    def talk(self):
        print('say hello')

  

13、请写一个小游戏,人狗大站,2 个角色,人和狗,游戏开始后,生成2个人,3条狗,互相混战,人被狗咬了会掉血,狗被人打了也掉血,狗和人的攻击力,具备的功能都不一样。


class Animal:
    def __init__(self, name, life_value, gjl):
        self.name = name
        self.life_value = life_value
        self.gjl = gjl



class People(Animal):
    def attack(self, enemy):
        if not isinstance(enemy, People):
            enemy.life_value -= self.gjl
            if enemy.life_value <= 0:
                print("已经死亡")
            else:
                print("剩下的生命值为:", enemy.life_value)
            print('人进行攻击')
        else:
            print('同类')



class Dog(Animal):
    def attack(self, enemy):
        if not isinstance(enemy, Dog):
            enemy.life_value -= self.gjl
            print(self.gjl)
            if enemy.life_value <= 0:
                print("已经死亡")
            else:
                print("剩下的生命值为:", enemy.life_value)
            print('狗咬人')
        else:
            print('同类')


p1 = People('tom', 100, 30)
p2 = People('jack', 100, 50)

d1 = Dog('dog1', 100, 20)
d2 = Dog('dog2', 100, 30)

d1.attack(d2)
p1.attack(d2)
p2.attack(d2)
p1.attack(d2)

  

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

 
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__)

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

class Student:
    count = 0
    def __init__(self, name, country, age):
        self.name = name
        self.country = country
        self.age = age
        Student.count += 1

s1 = Student('mike', 'china', 18)
s2 = Student('mike1', 'china', 18)
print(Student.count)

  

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



自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用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:
            username = input("请输入用户名:").strip()
            password = input("请输入密码:").strip()
            user_info = self.db()
            if username in user_info.keys():
                passwd = user_info.get(username).get("password")
                time_o = user_info.get(username).get("timeout")
                login_t = time.time()
                print(username, login_t, time_o)
                if login_t - time_o > 10:
                    if passwd == password:
                        print("欢迎登录,%s" % username)
                        user_info.get(username)["status"] = True
                        user_info.get(username)["timeout"] = time.time()
                        break
                    else:
                        print("用户名或密码错误!")
                        count += 1
                else:
                    print("登录过于频繁,请间隔10秒再登录")
            else:
                print("用户名不存在!")

        else:
            print("错误次数大于三次")
            user_info.get(username)["timeout"] = time.time()
        self.save_user(user_info)

    def exit(self, username):
        user_info = self.db()
        if username in user_info.keys():
            if user_info.get(username)["status"]:
                print("用户%s 已经登录,准备退出" % username)
                time.sleep(3)
                user_info.get(username)["status"] = False
                self.save_user(user_info)
        else:
            print("用户名不存在!")

    @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)


login = User()
# login.write()
# print(login.db())
# login.login()
login.exit('egon')

  

  


 

推荐阅读