天天看點

python 要掌握面向對象,你得會做這些題

1,面向對象三大特性,各有什麼用處,說說你的了解。

繼承:解決代碼重用問題

多态:多态性,可以在不考慮對象類型的情況下而直接使用對象

封裝:明确的區分内外,控制外部對隐藏屬性的操作行為,隔離複雜度
      

  

2,類的屬性和對象的屬性有什麼差別?

類的屬性:資料屬性和函數屬性,資料屬性是所有對象共有的,函數屬性是綁定對象使用的

對象的屬性:對象是類的執行個體化
      

3,面向過程程式設計與面向對象程式設計的差別與應用場景?

面向過程:複雜的問題流程化,簡單化
應用場景:不再需要擴充了,監測腳本,自動部署腳本,軟體解壓安裝

面向對象:特征與技能的結合體 一切皆對象
應用場景:使用者需求經常變化,網際網路應用,遊戲,企業内部應用
      

4,類和對象在記憶體中是如何儲存的。

類和對象的屬性:以字典的形式儲存的
      

5,什麼是綁定到對象的方法、綁定到類的方法、解除綁定的函數、如何定義,如何調用,給誰用?有什麼特性

綁定到對象的方法:就應該由對象來調用,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):
     pass

 a = A()

 a["key"] = "val"
 a = a["key"]
 del a["key"]
      
# class A(object):
#     def __setitem__(self, key, value):
#         self.__dict__[key] = value
#
#     def __getitem__(self, item):
#         # return self.__dict__[item]
#         return self.__dict__.get(item)
#
#     def __delitem__(self, key):
#         del self.__dict__[key]
#
# a = A()
# a["key"] = "val"
# print(a.__dict__)
# # a = a["key"]
# # print(a)
# del a["key"]
# print(a.__dict__)
      

7,python中經典類和新式類的差別

經典類:py2 沒有繼承object的類,以及它的子類都稱之為經典類  --> 深度優先

新式類:py3 繼承object的類,以及它的子類都稱之為新式類       -->廣度優先
      

8,如下示例, 請用面向對象的形式優化以下代碼

1、在沒有學習類這個概念時,資料與功能是分離的
   def exc1(host,port,db,charset):
     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','存儲過程的名字')
      

9,示例1, 現有如下代碼, 會輸出什麼:

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

  p1 = People()
  print(p1.__name, p1.__age)
      
class People(object):
    __name = "luffy"
    __age = 18


p1 = People()

# print(p1.__name, p1.__age)
# 報錯:AttributeError: 'People' object has no attribute '__name'

print(p1.__dict__)          #{}
print(People.__dict__)
# {'__module__': '__main__', '_People__name': 'luffy', 
# '_People__age': 18, '__dict__': <attribute '__dict__' of 'People' objects>, 
# '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
print(p1._People__name,p1._People__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__
      

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('alice')
# a.foo('alice')
# A.class_foo('alice')
# a.static_foo('alice')
# A.static_foo('alice')
'''
executing foo(<__main__.A object at 0x000002A5FED12AC8>, alice)
executing class_foo(<class '__main__.A'>, alice)
executing static_foo(alice)
executing static_foo(alice)
'''
      

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

 報錯内容:

Traceback (most recent call last):
  File "D:/py.py", line 27, in <module>
    d.eat()
TypeError: 'NoneType' object is not callable
      

改正如下:

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
      

  因為有了property,使用者就可以直接輸入得到結果,對于使用者來說,感覺不到其屬性,這就是使用property的友善之處,此方法必須有一個傳回值。return 或者print都可以。

為什麼要用property?

   一個類的函數定義成特性以後,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然後計算出來的,這種特性的使用方式遵循了統一通路的原則

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,多重繼承的執行順序,請解答以下輸出結果是什麼?并解釋。

super()表示的是 子類的mro()清單中的下一個
    print(G.mro())
        [<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    print(F.mro())
        [<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
      
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 Animal:
    def __init__(self, name):
        self.name = name


class People(Animal):
    def talk(self):
        print('%s is talking' % self.name)


class Dog(Animal):
    def talk(self):
        print('%s is talking' % self.name)


def func(animal):
    animal.talk()

# p=People('alice')
# d=Dog('wang')
# func(p)
# func(d)
'''
alice is talking
wang is talking
'''
      

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.life_value = life_value
        self.aggressivity = aggressivity

    def attack(self,enemy):
        enemy.life_value -= self.aggressivity


class People(Animal):
    camp='home'
    def attack(self,enemy):
        super().attack(enemy)
        print('from people')

class Dog(Animal):
    camp='wo'
    def attack(self,enemy):
        super().attack(enemy)
        print('from dog')

p1=People('alice',80,30)
p1=People('alex',80,30)
d1=Dog('w1',90,50)
d2=Dog('w2',90,50)
d3=Dog('w3',90,50)

# print(p1.life_value)
# d1.attack(p1)
# print(p1.life_value)

# print(d1.life_value)
# p1.attack(d1)
# print(d1.life_value)
      

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 0x0000000001E7B950>,
 '__dict__': <attribute '__dict__' of 'Chinese' objects>,                                         
 '__weakref__': <attribute '__weakref__' of 'Chinese' objects>,
 '__doc__': None}
'''
      

19,編寫程式, 在元類中控制自定義的類無需init方法.

class Mymeta(type):
    def __new__(cls,class_name,class_bases,class_dic):
        update_dic = {}
        for i in class_dic:
            if not callable(class_dic[i]) and not i.startswith('__'):
                update_dic[i.upper()]=class_dic[i]
            else:
                update_dic[i]=class_dic[i]
        return type.__new__(cls,class_name,class_bases,update_dic)

    def __call__(self, *args, **kwargs):
        obj=object.__new__(self)
        if args:
            raise TypeError('must be keyword argument')
        for i in kwargs:
            obj.__dict__[i]=kwargs[i]
        return obj

class Chinese(metaclass=Mymeta):
    country='china'
    tag='legend of the dragon'

    def talk(self):
        print('%s is talking'%self.name)

# print(Chinese.__dict__)
# ch=Chinese(name='alice',age=18)
# ch.talk()
# print(ch.__dict__)
      

20,編寫程式, 編寫一個學生類, 要求有一個計數器的屬性, 統計總共執行個體化了多少個學生.

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

    @property
    def talk(self):
        print('%s is talking' % self.name)

    @staticmethod
    def tell_count():
        print('總共執行個體化了 %s 人' % Student.__count)

# s1 = Student('alice', 18)
# s2 = Student('alex', 20)
# s3 = Student('egon', 28)
# Student.tell_count()
# s1.tell_count()
# s1.talk
# s2.talk
      

 結果:

# 結果:
# 1
# {'name': 'james', 'sex': 'male', 'age': 32}
# 2
# {'name': 'enbede', 'sex': 'male', 'age': 23}
# 2
# {'__module__': '__main__', '_count': 2, '__init__': <function Student.__init__ at 0x00000190B1B959D8>, 'learn': <property object at 0x00000190B19047C8>, 'tell_count': <staticmethod object at 0x00000190B1B9CAC8>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
# 總共執行個體化了:2
# james is learning
      
# _*_ coding: utf-8 _*_
'''
練習1:編寫一個學生類,産生一堆學生對象, (5分鐘)
要求:
有一個計數器(屬性),統計總共執行個體了多少個對象
'''
class Student:
    count = 0
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
        Student.count +=1

    def learn(self):
        print("%s is learning"%self.name)

stu1 = Student('james','male',32)
print(stu1.count)
print(stu1.__dict__)
stu2 = Student('enbede','male',23)
print(stu2.count)
print(stu2.__dict__)
print(Student.count)
print(Student.__dict__)
# 結果:
# 1
# {'name': 'james', 'sex': 'male', 'age': 32}
# 2
# {'name': 'enbede', 'sex': 'male', 'age': 23}
# 2
# {'__module__': '__main__', 'count': 2, '__init__': <function Student.__init__ at 0x000001E5DA9759D8>, 'learn': <function Student.learn at 0x000001E5DA975A60>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
# 
# Process finished with exit code 0
      

21,編寫程式, A 繼承了 B, 倆個類都實作了 handle 方法, 在 A 中的 handle 方法中調用 B 的 handle 方法

class B:
    def handle(self):
        print('from B handle')

class A(B):
    def handle(self):
        super().handle()
        # print('from A handle')
# a=A()
# a.handle()
      

22,編寫程式, 如下有三點要求:

  1. 自定義使用者資訊資料結構, 寫入檔案, 然後讀取出内容, 利用json子產品進行資料的序列化和反序列化
  2. 定義使用者類,定義方法db,例如 執行obj.db可以拿到使用者資料結構
  3. 在該類中實作登入、退出方法, 登入成功将狀态(status)修改為True, 退出将狀态修改為False(退出要判斷是否處于登入狀态).密碼輸入錯誤三次将設定鎖定時間(下次登入如果和目前時間比較大于10秒即不允許登入)
import json
import time
class User:
    def __init__(self, name, password):
        self.name = name
        self.password = password
        self.status = False
        self.timeout = 0

    @property
    def db(self):
        with open(self.name+'.txt', 'r', encoding='utf-8') as f:
            data = json.load(f)
        return data

    def save(self):
        obj={}
        obj[self.name]={'password':self.password,'status':self.status,'timeout':self.timeout}
        with open(self.name+'.txt', 'w', encoding='utf-8') as f:
            json.dump(obj,f)

    def login(self):
        with open(self.name+'.txt', 'r+', encoding='utf-8') as f:
            data = json.load(f)
            count = 0
            while count < 3:
                password = input('password>>:').strip()
                if password != data[self.name]['password']:
                    count += 1
                    continue
                else:
                    if data[self.name]['timeout'] != 0:
                        if time.time() - data[self.name]['timeout'] > 10:
                            print('不允許登入了!逾時')
                            break
                        else:
                            data[self.name]['status'] = True
                            f.seek(0)
                            f.truncate()
                            json.dump(data, f)
                            print('----welcome----')
                            break
                    else:
                        data[self.name]['status'] = True
                        f.seek(0)
                        f.truncate()
                        json.dump(data, f)
                        print('----welcome----')
                        break

            else:
                data[self.name]['timeout']=time.time()
                f.seek(0)
                f.truncate()
                json.dump(data,f)


    def quit(self):
        with open(self.name+'.txt', 'r+', encoding='utf-8') as f:
            data = json.load(f)
            if data[self.name]['status'] == True:
                data[self.name]['status'] = False
                f.seek(0)
                f.truncate()
                json.dump(data, f)
            else:
                print('您是退出狀态!')


# alex=User('alex','123')
# egon=User('egon','456')
# # alex.save()
# # egon.save()
# # print(alex.db)
# # print(egon.db)
# # alex.login()
# alex.quit()
# # egon.quit()
# print(alex.db)
# print(egon.db)

# alex.login()
# egon.login()
      

23,用面向對象的形式編寫一個老師角色, 并實作以下功能, 擷取老師清單, 建立老師、删除老師、建立成功之後通過 pickle 序列化儲存到檔案裡,并在下一次重新開機程式時能讀取到建立的老師, 例如程式目錄結構如下.

.
|-- bin/
|   |-- main.py         程式運作主體程式(可進行菜單選擇等)
|-- config/
|   |-- settings.py     程式配置(例如: 配置存儲建立老師的路徑相關等)
|-- db                  資料存儲(持久化, 使得每次再重新開機程式時, 相關資料對應保留)
|   |-- teachers/          存儲所有老師的檔案
|   |-- ...                ...
|-- src/                程式主體子產品存放
|   |-- __init__.py
|   |-- teacher.py      例如: 實作老師相關功能的檔案
|   |-- group.py        例如: 實作班級相關的功能的檔案
|-- manage.py           程式啟動檔案
|-- README.md           程式說明檔案
      

24,根據23 題, 再編寫一個班級類, 實作以下功能, 建立班級, 删除班級, 擷取班級清單、建立成功之後通過 pickle 序列化儲存到檔案裡,并在下一次重新開機程式時能讀取到建立的班級.

25,根據 23題, 編寫課程類, 實作以下功能, 建立課程(建立要求如上), 删除課程, 擷取課程清單

26,根據23 題, 編寫學校類, 實作以下功能, 建立學校, 删除學校, 擷取學校清單

27,通過23題, 它們雷同的功能, 是否可以通過繼承的方式進行一些優化

僞代碼
class Behavior(object):

    def fetch(self, keyword):
        通過 keyword 參數 查詢出對應的資料清單

class School(Behavior):

    pass

class Teacher(Behavior):

    pass

s = School()
t = Teacher()

s.fetch("school")
t.fetch("teacher")
      

28:編寫一個學生類,産生一堆學生對象

  要求:有一個計數器(屬性),統計總共執行個體了多少個對象

class Studentclass:
    school = 'jiaotong university'
    count = 0

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex =sex
        Studentclass.count +=1
    def learn(self):
        print('%s is learning'%self.name)
stu1 = Studentclass('james',23,'male')
stu2 = Studentclass('poal',24,'male')
stu3 = Studentclass('harden',25,'male')
print(Studentclass.count)
print(stu1.__dict__)
print(stu2.__dict__)
print(stu3.__dict__)
print(stu1.count)
print(stu2.count)
print(stu3.count)
      

29:模仿王者榮耀定義兩個英雄類

  要求:

  1. 英雄需要有昵稱、攻擊力、生命值等屬性;
  2. 執行個體化出兩個英雄對象;
  3. 英雄之間可以互毆,被毆打的一方掉血,血量小于0則判定為死亡。
class Hero:
    def __init__(self,nickname,life_value,aggresivity):
        self.nickname = nickname
        self.life_value = life_value
        self.aggresivity = aggresivity
    def attack(self,enemy):
        enemy.life_value -= self.aggresivity

class Garen(Hero):
   pass

class Riven(Hero):
    pass
g1=Garen('草叢論',100,20)
r1 = Riven('放逐之刃',80,50)

print(r1.life_value)
g1.attack(r1)
print(r1.life_value)
      

不經一番徹骨寒 怎得梅花撲鼻香

繼續閱讀