首页 » 编程 » Python » Python学习 » 面向对象 » 正文

面向对象-练习题

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

封装:在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。

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

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

 

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

类有两种属性:数据属性和函数属性。

类的数据属性是所有对象共享的,类的函数属性是绑定给对象用的,称为绑定给对象的方法。

 

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

面向过程:核心是过程二字,过程指的是解决问题的步骤,设计一条流水线,机械式的思维方式。

优点:把复杂的问题流程化,进而简单化

缺点:可扩展性差

 

面向对象:核心就是对象二字,对象就是特征与技能的结合体

优点:可扩展性强

缺点:编程复杂度高

应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用

 

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

通过名称空间来保存的。

 

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

 

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

class A(object):
     pass

 a = A()

 a["key"] = "val"  # 触发 __getitem__方法
 a = a["key"]  # 触发 __setitem__方法
 del a["key"]  # 触发 __delitem__方法

 

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

经典类和新式类的区别只存在于python2中。

经典类是指没有继承object类的类以及其子类都是经典类。

新式类是指继承了object类的类以及其子类都是新式类。

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 DB:
    host = "127.0.0.1"
    port = 3306
    db = "db1"
    charset = "utf8"

    def __init__(self, host, port, db, charset):
        self.host = host
        self.port = port
        self.db = db
        self.charset = charset

    def connect(self):
        print("开始连接数据库...")
        print(self.host, self.port, self.db, self.charset)
        print("连接成功")

    def select(self, sql):
        print("开始select: ", sql)

    def proc(self, proc_name):
        print("开始proc: ", proc_name)


d1 = DB("127.0.0.1", 3306, "db1", "utf8")
d1.connect()
d1.select("select * from tb1")
d1.proc("存储过程名字")

执行结果如下:

开始连接数据库…
127.0.0.1 3306 db1 utf8
连接成功
开始select: select * from tb1
开始proc: 存储过程名字

 

9. 示例1, 现有如下代码, 会输出什么:

 class People(object):
      __name = "luffy"
      __age = 18

  p1 = People()
  print(p1.__name, p1.__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__

因为__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()

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(1)
a.class_foo(2)
a.static_foo(3)

A.foo(A, 1)
A.class_foo(2)
A.static_foo(3)

运行输出如下:

executing foo(<__main__.A object at 0x000001EE67B40240>, 1)
executing class_foo(<class ‘__main__.A’>, 2)
executing static_foo(3)
executing foo(<class ‘__main__.A’>, 1)
executing class_foo(<class ‘__main__.A’>, 2)
executing static_foo(3)

 

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

运行后错误如下:

Traceback (most recent call last):
ChenRonghua is eating
File “D:/PycharmProjects/python_fullstack_middle/第三模块·面向对象&网络编程基础/第1章·面向对象/练习题/12题.py”, line 26, in <module>
d.eat()
TypeError: ‘NoneType’ object is not callable

原因:因为给eat加了property装饰器,就使得在调用的时候可以像调用数据属性那样进行调用,不能加括号了,将括号去掉就行。

去掉后运行结果如下:

ChenRonghua is eating

 

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:
    def talk(self):
        pass


class Chinese(People):
    def talk(self):
        print("中国人在说")


class US(People):
    def talk(self):
        print("美国人在说")


c = Chinese()
u = US()
c.talk()
u.talk()

运行结果:

中国人在说
美国人在说

 

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

 

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

class Animal:
    def __init__(self, name, life, attck):
        self.name = name
        self.life = life
        self.attck = attck

    def attack(self, person):
        person.life -= self.attck
        print("%s 攻击 %s, %s 生命值还有 %s" % (self.name, person.name, person.name, person.life))


class People(Animal):
    def __init__(self, name, life, attck, wapon):
        super().__init__(name, life, attck)
        self.wapon = wapon

    def attack(self, person):
        person.life -= self.attck
        print("%s 使用<%s>攻击 %s, %s 生命值还有 %s" % (self.name, self.wapon, person.name, person.name, person.life))


class Dog(Animal):
    pass


p1 = People("p1", 100, 20, "棍子")
p2 = People("p2", 100, 23, "枪")
d1 = Dog("d1", 100, 15)
d2 = Dog("d2", 100, 13)
d3 = Dog("d3", 100, 18)

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

运行结果:

p1 使用<棍子>攻击 d1, d1 生命值还有 80
p1 使用<棍子>攻击 d1, d1 生命值还有 60
d1 攻击 p1, p1 生命值还有 85
d3 攻击 p2, p2 生命值还有 82
d2 攻击 d3, d3 生命值还有 87

 

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

class MyMeta(type):
    print("进入MyMeta..")

    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 Test(metaclass=MyMeta):
    name = "alex"
    age = 18


print(Test.__dict__)

输出:

进入MyMeta..
{‘__module__’: ‘__main__’, ‘NAME‘: ‘alex’, ‘AGE‘: 18, ‘__dict__’: <attribute ‘__dict__’ of ‘Test’ objects>, ‘__weakref__’: <attribute ‘__weakref__’ of ‘Test’ objects>, ‘__doc__’: None}

 

19. 编写程序, 在元类中控制自定义的类无需init方法.

class MyMeta(type):

    def __call__(self, *args, **kwargs):
        if args:
            raise TypeError("类中不能有init方法")
        obj = object.__new__(self)
        return obj


class Test(metaclass=MyMeta):
    name = "alex"
    age = 18


t = Test()
print(t.name)
print(t.age)

运行输出:

alex
18

 

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

class Student:
    count = 0

    def __init__(self, name):
        self.name = name
        Student.count += 1


s1 = Student("alex")
s2 = Student("jack")
print(s1.count)

运行输出:

2

 

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

class B:
    def handle(self):
        print("B-handle..")


class A(B):
    def handle(self):
        B.handle(A)


a = A()
a.handle()

运行输出:

B-handle..

 

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

1)自定义用户信息数据结构, 写入文件, 然后读取出内容, 利用json模块进行数据的序列化和反序列化

eg:

{
    "egon":{"password":"123",'status':False,'timeout':0},
    "alex":{"password":"456",'status':False,'timeout':0},
}

2) 定义用户类,定义方法db,例如 执行obj.db可以拿到用户数据结构

3) 在该类中实现登录、退出方法, 登录成功将状态(status)修改为True, 退出将状态修改为False(退出要判断是否处于登录状态).密码输入错误三次将设置锁定时间(下次登录如果和当前时间比较大于10秒即不允许登录)

 

 

 

 

赞 (0)

发表评论

*