1. 簡述面向對象的三大特性。
# 答案
封裝:
封裝指的是把一堆數據屬性與方法數據放在一個容器中,這個容器就是對象。讓對象可以通過 "." 來調用對象中的數據屬性與方法屬性。
繼承:
繼承指的是子類可以繼承父類的數據屬性與方法屬性,並可以對其進行修改或使用。
多態:
在python中的多態指的是讓多種類若具備類似的數據屬性與方法屬性,都統一好命名規范,這樣可以提高開發者的代碼統一性,使得調用者更方便去理解。
2. 什么是鴨子模型?
# 答案
在python中不會強制性要求所有人的代碼都統一規范,不統一也不會報錯,若使用抽象類就會使python代碼強制統一規范,這樣不符合python動態語言的特性。所以讓大家都自覺統一好規范,若大家的對象方法都類似的話就一種規范,只要長得像鴨子,就稱之為鴨子類型。
3. super 的作用?
# 答案
'''
使用super()可以在子類中調用父類的方法或屬性, 可能你會說, 子類本來就可以調用父類中所有非私有的屬性或方法,而我現在說的是, 當子類中實現了某個方法, 父類中也有這個方法, 當你調用這個方法時, 既想執行子類的又想執行父類的, 在這種情況下就可以使用super()
'''
4. mro 是什么?
# 答案
'''
mro全稱Method Resolution Order,指的是方法解析順序。
方法調用時就需要對當前類和基類進行搜索以確定方法所在的位置。而搜索的順序就是所謂的「方法解析順序」。
'''
5. 什么是 c3 算法?
# 答案
'''
C3算法最早被提出是用於Lisp的,應用在Python中是為了解決原來基於深度優先搜索算法不滿足本地優先級,和單調性的問題。
本地優先級:指聲明時父類的順序,比如C(A,B),如果訪問C類對象屬性時,應該根據聲明順序,優先查找A類,然后再查找B類。
單調性:如果在C的解析順序中,A排在B的前面,那么在C的所有子類里,也必須滿足這個順序。
'''
6. 列舉面向對象中帶雙下划線的特殊方法。
# 答案
#__setattr__: 添加/修改屬性會觸發它的執行
#__delattr__: 刪除屬性的時候會觸發
#__getattr__: 只有在使用點調用屬性且屬性不存在的時候才會觸發
# __getattribute__: 不管是否存在,我都會執行
7. 雙下划線和單下划線的區別?
# 答案
'''
"單下划線" 開始的成員變量叫做保護變量,意思是只有類對象和子類對象自己能訪問到這些變量。
"雙下划線" 開始的是私有成員,意思是只有類對象自己能訪問,連子類對象也不能訪問到這個數據。
'''
8. 實例變量和類變量的區別?
# 答案
'''
類變量是所有對象共有,其中一個對象將它值改變,其他對象得到的就是改變后的結果;而實例變量則屬對象私有,某一個對象將其值改變,不影響其他對象;
'''
9. 靜態方法和類方法區別?
# 答案
'''
Python的類就是個語法糖。一個函數寫在類里面和寫在類外面沒有區別,唯一的區別就是參數,所謂實例方法就是第一個參數是self,所謂類方法就是第一個參數是class,而靜態方法不需要額外的參數,所以必須區分。
'''
10. isinstance 和 type 的作用?
# 答案
'''
type和isinstance都可以判斷變量是否屬於某個內建類型
type只接收一個參數,不但可以判斷變量是否屬於某個類型,而且可以得到參數變量未知的所屬的類型;而isinstance只能判斷是否屬於某個已知類型,不能直接得到變量未知的所屬的類型
'''
11. 有用過with statement(語句)嗎?它的好處是什么?
# 答案
'''
with語句會在嵌套的代碼執行之后,自動關閉文件。這種做法的還有另一個優勢就是,無論嵌套的代碼是以何種方式結束的,它都關閉文件。如果在嵌套的代碼中發生異常,它能夠在外部exception handler catch異常前關閉文件。如果嵌套代碼有return/continue/break語句,它同樣能夠關閉文件。
'''
12. 下列數據結構中,哪一種是不可迭代的
'''
A. dict
B. object
C. set
D. str
'''
# 答案:
B
13. 實現一個Singleton單例類,要求遵循基本語言編程規范(用盡量多的方 式)。
# 答案:
1.__new__
class Borg(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
ob = super(Borg, cls)
cls._instance = ob.__new__(cls, *args, **kwargs)
return cls._instance
class MyClass(Borg):
def __init__(self):
self.a = 1
2.共享屬性
class Borg2(object):
_state = {}
def __new__(cls, *args, **kwargs):
ob = super(Borg2, cls).__new__(cls, *args, **kwargs)
ob.__dict__ = cls._state
return ob
class MyClass(Borg2):
def __init__(self):
self.a = 1
3.裝飾器
def singleton(cls, *args, **kwargs):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class MyClass(object):
def __init__(self):
self.a = 1
4.import方法
# mysingleton .py
class MyClass(object):
def __init__(self):
self.a = 1
s_myclass = MyClass()
from mysingleton import s_myclass
s_myclass.a
14. 請述with的用法,如果自己的類需要支持with語句,應該如何書寫?
基本格式
with context_expression [as target(s)]:
with-body
這里 context_expression 要返回一個上下文管理器對象,該對象並不賦值給 as 子句中的 target(s) ,如果指定了 as 子句的話,會將上下文管理器的 __enter__() 方法的返回值賦值給 target(s)。
target(s) 可以是單個變量,或者由“()”括起來的元組(不能是僅僅由“,”分隔的變量列表,必須加“()”)。
自定義的上下文管理器要實現上下文管理協議所需要的 __enter__() 和 __exit__() 兩個方法
context_manager.__enter__() :進入上下文管理器的運行時上下文,在語句體執行前調用。with 語句將該方法的返回值賦值給 as 子句中的 target,如果指定了 as 子句的話
context_manager.__exit__(exc_type, exc_value, exc_traceback) :退出與上下文管理器相關的運行時上下文,返回一個布爾值表示是否對發生的異常進行處理。
15. python 中如何判斷一個對象是否可調用? 哪些對象可以是可調用對象?如何定義一個類,使其對象本身就是可調用對象?
# 答案:
# python 中如何判斷一個對象是否可調用
def func():
pass
print(callable(func)) # True
# 哪些對象可以是可調用對象
1.類對象
2.所有帶有_call_()方法的對象
# 如何定義一個類,使其對象本身就是可調用對象
一個類實例也可以變成一個可調用對象,只需要實現一個特殊方法call()。
16. 請實現一個棧。
# 答案:
class Stack(object) :
def __init__(self,size):
#類的構造函數
self.size = size
self.stack = []
def __str__(self):
#類的字符串輸出方法,類似於java的.toString()方法
return str(self.stack)
def getSize(self) :
#獲取棧當前大小
return len(self.stack)
def push(self, x) :
#入棧,棧滿拋異常
if self.isfull() :
#return -1
raise Exception("Stack is full")
self.stack.append(x)
def pop(self) :
#出棧,棧空拋異常
if self.isempty() :
#return -1
raise Exception("Stack is empty")
topElement = self.stack[-1]
self.stack.remove(topElement)
return topElement
def isempty(self) :
#判斷棧空
if len(self.stack) == 0 :
return True
return False
def isfull(self) :
#判斷棧滿
if len(self.stack) == self.size :
return True
return False
17. 關於Python類的繼承不正確的說法是?(多選)
A. Python類無法繼承
B. 可以繼承, 無法執行父類的構造函數
C. 可以有多個父類
D. 只能有一個父類
# 答案
'''
A
D
'''
18. 實現一個hashtable類,對外暴露的有add和get方法,滿足以下測試代碼
def test():
import uuid
names = {"name", "web", "python"}
ht = HashTable()
for key in names:
value = uuid.uuid4()
ht.add(key, value)
print("add 元素", key, value)
for key in names:
v = ht.get(key)
print("get 元素", key, v)
# 答案:
class HashMap(object):
def __init__(self):
# 初始化總表為,容量為2的表格(含兩個子表)
self.maps = BetterMap(2)
self.num = 0 # 表中數據個數
def get(self,k):
return self.maps.get(k)
def add(self, k, v):
# 若當前元素數量達到臨界值(子表總數)時,進行重排操作
# 對總表進行擴張,增加子表的個數為當前元素個數的兩倍!
if self.num == len(self.maps.maps):
self.resize()
# 往重排過后的 self.map 添加新的元素
self.maps.add(k, v)
self.num += 1
def resize(self):
""" 重排操作,添加新表, 注意重排需要線性的時間 """
# 先建立一個新的表,子表數 = 2 * 元素個數
new_maps = BetterMap(self.num * 2)
for m in self.maps.maps: # 檢索每個舊的子表
for k,v in m.items: # 將子表的元素復制到新子表
new_maps.add(k, v)
self.maps = new_maps # 令當前的表為新表
19.請用兩個隊列來實現一個棧(給出偽代碼即可)
# 答案:
class StackWithTwoQueues(object):
#定義兩個空隊列
def __init__(self):
self.queue1 = []
self.queue2 = []
#入棧
def push(self, item):
self.queue1.append(item)
#出棧
def pop(self):
if len(self.queue1) == 0:
return(None)
while(len(self.queue1) != 1):
self.queue2.append(self.queue1.pop(0))
self.queue1, self.queue2 = self.queue2, self.queue1
return (self.queue2.pop())
#test
if __name__ == '__main__':
ss = StackWithTwoQueues()
list = [0, 1, 2, 3, 4]
for i in range(5):
ss.push(list[i])
print(list)
for i in range(5):
print(ss.pop(), ',', end = '')
#output
#[0, 1, 2, 3, 4]
#4, 3, 2, 1, 0
20.已知如下鏈表類,請實現單鏈表逆置
class Node:
def __init__(self, value, next):
self.value = value
self.next = next
# 答案:
class Solution:
def ReverseList(self, pHead):
if not pHead or not pHead.next:
return pHead
last = None
while pHead:
tmp = pHead.next
pHead.next = last
last = pHead
pHead = tmp
return last
21.類的加載順序(類中有繼承有構造有靜態)?
1、 類對象
2、 實例對象
3、 self變量名稱問題
4、 類屬性、實例變量、局部變量
5、 類方法
6、 實例方法
7、 類方法與實例方法相互調用
8、 靜態方法
9、 繼承時三類方法的影響
22.參考下面代碼片段
class Context:
pass
with Context as ctx:
ctx.do_something()
# 請在 Context 類下添加代碼完成該類的實現
# 答案:
class Context(object):
def __enter__(self):
pass
def __exit__(self, exc_type, exc_val, exc_tb):
if all([exc_type, exc_val, exc_tb]):
print 'handler except'
print 'exception {}'.format(exc_val)
return True
def main():
with tornado.stack_context.StackContext(Contextor):
async_task()
23. 以下代碼輸出是什么?請給出答案並解釋。
class Parent:
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)
Child1.x = 3
print(Parent.x, Child1.x, Child2.x)
# 答案
'''
1 1 1
1 2 1
1 3 1
'''
24. 函數del_node(self,data)的功能:在根節點指針為root的二叉樹(又稱二叉 排序樹)上排除數值為 K 的節點,若刪除成功,返回 0,否則返回-1, 概述節點的 定義類型為
class Node(object):
def __init__(self, data):
self.data = data # 節點的數值
self.left_child = Node # 指向左右子樹的指針
self.right_child = Node
def set_data(self, data):
self.data = data
# 答案:
25. 請給出下面代碼片段的輸出,請簡述上面代碼需要改進的地方?
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
print("New")
if cls._instance is None:
print("Create")
cls._instance = super().__new__(cls,*args, **kwargs)
return cls._instance
def __init__(self):
print("Initalize")
self.prop = None
s1 = Singleton()
s2 = Singleton()
# 答案:
26. 請簡單解釋Python中的staticmethod(靜態方法)和classmethod(類方法), 並將以下代碼填寫完整。
class A:
def foo(self, x):
print('executing class_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()
# 調用 foo 函數,參數傳入 1
# ____________________
# 調用 class_foo 函數,參數傳入 1
# ____________________
# 調用 static_foo 函數,參數傳入 1
# ____________________
# 答案:
a.foo(1)
A.class_foo(1)
a.static_foo(1)
A.static_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 四種方法
使用方法如下
s = Queue(2) # 初始化一個大小為 2 的隊列
s.is_empty() # 初始化后, 隊列為空, 返回 True
s.enqueue(1) # 將 1 加入隊列
s.enqueue(2) # 將 2 加入隊列
s.isfull() # 加入了兩個元素, 隊列已滿, 返回 True 6. s.dequeue() # 移除一個元素, 返回 1
s.dequeue() # 移除一個元素, 返回 2
s.is_empty() # 隊列已經為空, 返回 True