第四章 面向對象

1. 簡述面向對象的三大特性。html

  參考連接node

  繼承,封裝和多態python

  • 繼承:
    • 繼承就是繼承的類直接擁有被繼承類的屬性而不須要在本身的類體中從新再寫一遍,其中被繼承的類叫作父類、基類,繼承的類叫作派生類、子類。
  • 封裝:
    • 封裝就是把類中的屬性和方法定義爲私有的,方法就是在屬性名或方法名前加雙下劃線,而一旦這樣定義了屬性或方法名後,python會自動將其轉換爲_類名__屬性名(方法名)的格式,在類的內部調用仍是用雙下劃線加屬性名或方法名,在類的外部調用就要用_類名__屬性名(方法名)。父類的私有屬性和方法,子類沒法對其進行修改。
  • 多態:
    • 多態就是不一樣的對象能夠調用相同的方法而後獲得不一樣的結果,有點相似接口類的感受,在python中到處體現着多態,好比無論你是列表仍是字符串仍是數字均可以使用+和*。

2. 什麼是鴨子模型?web

  鴨子類型(英語:duck typing)是動態類型的一種風格。在這種風格中,一個對象有效的語義,不是由繼承自特定的類或實現特定的接口,而是由當前方法和屬性的集合決定。若是具備__iter__,__next__就是迭代器算法

3. super 的做用?編程

 當子類中的方法與父類中的方法重名時,子類中的方法會覆蓋父類中的方法,那麼,若是咱們想實現同時調用父類和子類中的同名方法,就須要使用到super()這個函數,用法爲super().函數名()數據結構

4. mro 是什麼?app

  類名.mro()能夠直接刪除當前類的繼承執行順序編程語言

  • 對於支持繼承的編程語言來講,其方法(屬性)可能定義在當前類,也可能來自於基類,因此在方法調用時就須要對當前類和基類進行搜索以肯定方法所在的位置。而搜索的順序就是所謂的「方法解析順序」(Method Resolution Order,或MRO)。

5. 什麼是 c3 算法?函數

  c3算法是python新式類中用來產生mro順序的一套算法。即多繼承的查找規則。

6. 列舉面向對象中帶雙下劃線的特殊方法。

  __new__:能夠調用其它類的構造方法或者直接返回別的對象來做爲本類的實例。

   __init__: 負責類的實例化

   __call__:對象後邊加括號,觸發執行

  __str__:print打印一個對象時。

  __repr__:print打印一個對象時(沒有__str__時執行)。

  __enter__與__exit__:配合with使用。

  __doc__:類的註釋,該屬性是沒法繼承的。

  __getattr__:在使用調用屬性(方式、屬性)不存在的時候觸發

  __setattr__:添加/修改屬性會觸發它的執行

   __dellattr__:刪除屬性的時候會觸發

  __delete__:採用del刪除屬性時,觸發

7. 雙下劃線和單下劃線的區別?

  • "單下劃線" 開始的成員變量叫作保護變量,意思是隻有類對象和子類對象本身能訪問到這些變量;
  • "雙下劃線" 開始的是私有成員,意思是隻有類對象本身能訪問,連子類對象也不能訪問到這個數據。

8. 實例變量和類變量的區別?

  • 實例變量是對於每一個實例都獨有的數據
  • 類變量是該類全部實例共享的屬性和方法

9. 靜態方法和類方法區別?

  • 實例方法:第一個參數必須是實例對象,一般爲self。實例方法只能由實例對象調用。
  • 類方法:使用裝飾器@classmethod。第一個參數爲當前類的對象,一般爲cls。實例對象和類對象均可以調用類方法。
  • 靜態方法:使用裝飾器@staticmethod。沒有self和cls參數。方法體中不能使用類或者實例的任何屬性和方法。實例對象和類對象均可以調用。

10. isinstance 和 type 的做用?

  • 二者都用來判斷對象的類型
  • 對於一個對象的直屬類型判斷可使用type,可是非直屬類型判斷就須要isinstance

11. 有用過 with statement(語句)嗎?它的好處是什麼?

  參考連接簡單使用

  • 使用with後無論with中的代碼出現什麼錯誤,都會進行對當前對象進行清理工做。例如file的file.close()方法,不管with中出現任何錯誤,都會執行file.close()方法
  • 只有支持上下文管理器的對象才能使用with,即在對象內實現了兩個方法:enter()和__exit__()

12. 下列數據結構中,哪種是不可迭代的

  A. dict  B. object  C. set   D. str

13. 實現一個 Singleton 單例類, 要求遵循基本語言編程規範(用盡可能多的方式)。

# 1.__new__實現單例模式
'''
class A(object):
    __flag=None
    def __new__(cls, *args, **kwargs):
        if cls.__flag==None:
            cls.__flag=object.__new__(cls)
            # cls.__flag=super(A,self).__new__(cls)
        return cls.__flag

    def __init__(self,name,age):
        self.name=name
        self.age=age

a=A("zhang",12)
print(a.__dict__,id(a))
b=A("yang",13)
print(b.__dict__,id(b))
print(a.__dict__,id(a))
a.age=22
print(b.__dict__,id(b))
print(a.__dict__,id(a))
'''


#2。裝飾器實現單例模式
'''
def wrapper(cls):
    l=[]
    def inner(*args,**kwargs):
        if not l:
            l.append(cls(*args,**kwargs))
        return l[0]

    return inner

@wrapper
class A(object):
    def __init__(self):
        pass
a1=A()
a2=A()
print("類裝飾器單例:",id(a1),id(a2))
'''

#3.外部模塊類實例導入
'''
class A(object):
    def __init__(self):
        pass
a=A()
from . import a
print(a)
'''


# 線程單例
from threading import Thread,Lock
def wrap(func):
    func.__lock__=Lock()
    def inner(*args,**kwargs):
        with func.__lock__:
            return func(*args,**kwargs)
    return inner

class B(object):
    __flag = None
    @wrap
    def __new__(cls, *args, **kwargs):
        if cls.__flag==None:
            cls.__flag=super().__new__(cls)
        return cls.__flag
    def __init__(self):
        pass

b1=B()
b2=B()
print(id(b1),id(b2))



#線程基於__new__的單例
import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with cls._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = object.__new__(cls)
        return cls._instance

    def __init__(self):
        pass

#使用元類建立
import threading
class SingletonType(type):
    _instance_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super().__call__(*args, **kwargs)
        return cls._instance


class Singleton(metaclass=SingletonType):
    def __init__(self):
        pass


obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)

14. 請描述 with 的用法, 若是本身的類須要支持 with 語句, 應該如何書寫?  

在類中實現兩個方法:enter()和__exit__()
class W(object):
    def __init__(self):
        pass
    def __enter__(self):
        print('進入with語句')
        return self
        
    def __exit__(self,*args,**kwargs):
        print('退出with語句')
        
with W() as w:
    print('以前')
    print(w)
    print('以後')

15. python 中如何判斷一個對象是否可調用? 那些對象能夠是可調用對象?如何定義一個類, 使其對象自己就是可調用對象?

  • 使用callable函數判斷。
  • 可調用對象有7類:
    • 用戶自定義函數
    • 內置函數
    • 內置方法
    • 方法(定義在類中的函數)
    • 類實例(若是類中定義了__call__方法,那麼這個類的實例就是可調用對象)
    • 生成器函數
  • 在類中定義__call__方法,實例對象加()是即調用__call__的方法

16. 請實現一個棧。  

"""
棧的抽象數據類型定義:棧的抽象數據類型應該由如下結構和操做定義。棧操做以下: 

    Stack() 建立一個空的新棧。 它不須要參數,並返回一個空棧。
    push(item)將一個新項添加到棧的頂部。它須要 item 作參數並不返回任何內容。
    pop() 從棧中刪除頂部項。它不須要參數並返回 item 。棧被修改。
    peek() 從棧返回頂部項,但不會刪除它。不須要參數。 不修改棧。
    isEmpty() 測試棧是否爲空。不須要參數,並返回布爾值。
    size() 返回棧中的 item 數量。不須要參數,並返回一個整數。
"""
class Stack(object):
    def __init__(self):
        self.stack = []

    def __str__(self):
        return str(self.stack)

    def push(self, item):
        self.stack.append(item)

    def pop(self):
        return self.stack.pop() if self.stack else "Stack is empty!"

    def peek(self):
        return len(self.stack) - 1

    def isEmpty(self):
        return self.stack == []

    def size(self):
        return len(self.stack)


s=Stack()
s.push(1)
s.push(3)
print(s)

17. 關於 Python 類的繼承不正確的說法是?(多選)

  A. Python類沒法繼承  B. 能夠繼承, 沒法執行父類的構造函數

  C. 能夠有多個父類      D. 只能有一個父類

18. 實現一個 hashtable 類, 對外暴露的有 add 和 get 方法, 知足如下測試代碼  

 1 def test():
 2     import uuid
 3     name = {"name", "web", "python"}
 4     ht = HashTable()
 5      for key in names:
 6         value = uuid.uuid4()
 7         ht.add(key,value)
 8         print("add元素",key,value)    
 9 
10      for key in names:
11          v = ht.get(key)
12          print("get 元素",key, v)
class HashTable(object):
    def __init__(self):
        self.dic = {}
    def add(self,key,value):
        self.dic[key] = value
    def get(self,key):
        return self.dic.get(key)

19. 請用兩個隊列來實現一個棧(給出僞代碼便可)

class Stack(object):
    def __init__(self):
        self.head = []
        self.tail = []

    def push(self, x):
        self.head.append(x)

    def pop(self):
        if self.head == []:
            return None
        while len(self.head) > 1:
            self.tail.append(self.head.pop(0))
        self.head, self.tail = self.tail, self.head
        return self.tail.pop()

    def __str__(self):
        return str(self.head)


s = Stack()
s.push(2)
s.push(333)
s.push(3)
s.pop()
s.pop()
s.push(1)
print(s)

20. 已知以下鏈表類, 請實現單鏈表逆置

1 class Node:
2     def __init__(self, value, next):
3     self.value = value
4     self.next = next
class LinkReverse(object):
    def reverse(self, head):
        if not head or not head.next:return head#若是鏈表爲空或者只有一個元素是返回自己
        #反轉關聯表的都指針定義
        last = None
        #將原鏈表的節點指向進行翻轉
        while head:
            temp = head.next
            head.next = last
            last = head
            head = temp
        return last

21. 類的加載順序(類中有繼承有構造有靜態)?

 

  1. 在堆內存中生成class對象, 把靜態變量和靜態方法加載到方法區, 這個堆內存中的class對象是方法區數據的入口
  2. 靜態變量默認初始化
  3. 靜態變量顯式初始化
  4. 執行靜態代碼塊
  5. 成員變量默認初始化, 顯示初始化
  6. 執行構造函數

22. 參考下面代碼片斷  

class Context:
    pass

with Content() as ctx:
    ctx.do_something()

  請在 Context類下添加代碼完成該類的實現  

class Context:
    def do_something(self):
        # print(1122)
        pass
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

with Context() as ctx:
    ctx.do_something()

23. 如下代碼輸出是什麼? 請給出答案並解釋。  

 1 class Parent(object):
 2     x = 1
 3 
 4 class Child1(Parent):
 5     pass
 6 
 7 class Child2(Parent):
 8     pass
 9 
10 print Parent.x, Child1.x, Child2.x
11 
12 Child1.x = 2
13 print Parent.x, Child1.x, Child2.x
14 
15 Parent.x = 3
16 print Parent.x, Child1.x, Child2.x

1 1 1
1 2 1
3 2 3

24. 函數 del_node(self,data)的功能: 在根節點指針爲 root 的二叉樹(又稱二叉排序樹)上排除數值爲 K 的節點,若刪除成功,返回 0,不然返回-1, 概述節點的 定義類型爲  

1 class Node(object):
2     def __init__(self,data):
3         self.data = data # 節點的數值
4         self.left_child = Node # 指向左右子樹的指針
5         self.right_child = Node
6 
7     def set_data(self,data):
8         self.data = data

25. 請給出下面代碼片斷的輸出,請簡述上面代碼須要改進的地方?  

 1 class Singleton:
 2     _instance = None
 3 
 4     def __new__(cls, *args, **kwargs):
 5         print("New")
 6         if cls._instance is None:
 7             print("Create")
 8             cls._instance = super().__new__(cls, *args, **kwargs)
 9         return cls._instance
10 
11     def __init__(self):
12         print("Initalize")
13         self.prop = None
14 
15 
16 s1 = Singleton()
17 s2 = Singleton()

New
Create
Initalize
New
Initalize

26.請簡單解釋Python中的staticmethod(靜態方法)classmethod(類方法),並將如下代碼填寫完整。  

 1 class A(object):
 2     def foo(self,x)
 3         print 'executing foo(%s, %s)'%(self,x)
 4 
 5     @classmethod
 6     def class_foo(cls,x):
 7         print 'executing class_foo(%s, %s)'%(cls,x)
 8 
 9     @staticmethod
10     def static_foo(x):
11         print 'executing static_foo(%s)'%(x)
12 
13 a= A()
14 # 調用 foo函數,參數傳入 1
15 a.foo(1)
16 # 調用 class_foo函數,參數傳入 1
17 A.class_foo(1)
18 # 調用 static_foo函數,參數傳入 1
19 A.static_foo(1) /  a.ststic_foo(1)

27. 已知一個訂單對象(tradeOrder)有以下字段:  

字段英文名

中文名

字段類型

取值

Id

主鍵

Long

123456789

Name

姓名

String

張三

Items

商品列表集合

List<商品>(關聯商品)

查找商品對象,一個訂單有兩個商品。商品字段任意取值

IsMember

是不是會員

Boolean

True

CouponAmount

優惠券金額

Bigdecimal

Null

  

    商品對象

字段英文名稱     

中文名 字段類型 取值
Id 主鍵 Long 987654321
Name 商品名稱 String 手機

    問題:若將訂單對象轉成 JSON 格式,請書寫出轉換後的 JSON 字符串。

 

28. 寫代碼(棧與隊列)

  編程實現一個先進先出的隊列類, 能指定初始化時的隊列大小, 以及enqueue,dequeue,isempty, isfull 四種方法

  使用方法以下:    

1 s = Queue(2) # 初始化一個大小爲 2的隊列
2 s.is_empty() # 初始化後, 隊列爲空, 返回 True
3 s.enqueue(1) # 將 1加入隊列
4 s.enqueue(2) # 將 2加入隊列
5 s.isfull() # 加入了兩個元素, 隊列已滿, 返回 True
6 s.dequeue() # 移除一個元素, 返回 1
7 s.dequeue() # 移除一個元素, 返回 2
8 s.is_empty() # 隊列已經爲空, 返回 True

 

class Queue(object):
    def __init__(self, size):
        self.__size = size
        self.__queue = []

    def enqueue(self, x):
        if len(self.__queue) < self.__size:
            self.__queue.insert(0,x)
        else:
            return 'The queue is full!!!'

    def dequeue(self):
        return None if not len(self.__queue) else self.__queue.pop()

    def is_empty(self):
        return not len(self.__queue)

    def isfull(self):
        return len(self.__queue) == self.__size

s = Queue(2)
print(s.is_empty())
s.enqueue(1)
s.enqueue(2)
print(s.isfull())
print(s.dequeue())
print(s.dequeue())
print(s.is_empty())
相關文章
相關標籤/搜索