1. 程式人生 > >python幾個面試題目:單例模式,淺拷貝與深拷貝

python幾個面試題目:單例模式,淺拷貝與深拷貝

主要參考git上一篇面試題目,連結如下https://github.com/taizilongxu/interview_python#2-python%E4%B8%AD%E7%9A%84%E5%85%83%E7%B1%BBmetaclass

實現單例模式,對每種方式新增更詳細的分析。

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls)
            cls._instance.__init__(*args, **kwargs)
        return cls._instance
    def __init__(self, *args, **kwargs):
        pass
a = Singleton()
b = Singleton()
print(id(a))
print(id(b))
每個物件的初始化會先呼叫__new__生成物件,再呼叫__init__完成後續的初始化,super(para1, cls)中的para1表示,在mro序列中從para1開始尋找下一個類,也就是繼承樹中的para1之前的第一個類,後邊的__new__為尋找到的類的函式,由於所有類都繼承自object,而object類的__new__函式被定義為static型別,故還要再傳入cls引數。
class Singleton(object):
    __instance = None
    def __init__(self, *args, **kwargs):
        pass
    @classmethod
    def get_instance(cls, *args, **kwargs):
        if Singleton.__instance is None:
            Singleton.__instance = Singleton(*args, **kwargs)
        return Singleton.__instance

a = Singleton.get_instance()
b = Singleton.get_instance()
print(id(a))
print(id(b))
這個方式生成物件要呼叫類方法get_instance,不夠方便,可以使用裝飾器方法實現。
def singleton(cls):
    _instance = None
    def get_instance(*args, **kwargs):
        if not _instance:
            obj = cls(*args, **kwargs)
        return obj
    return get_instance

@singleton
#想達到的目的程式碼obj = MyClass(*args, **kwargs)
#裝飾器作用MyClass = singleton(MyClass),將MyClass指向get_instance函式
#實際執行程式碼obj = get_instance(*args, **kwargs)
class MyClass(object):
    pass

a = MyClass()
b = MyClass()
print(id(a))
print(id(b))
import模組是天然的單例模式,在模組裡建好例項,每次使用從模組中引入例項。
#singelton.py
class Singeton(object):
    def __init__(*args, **kwargs):
        pass
    def foo(self):
        pass
singelton_obj = Singeton()

#to use
from singleton import singelton_obj
print(id(singelton_obj))
from singleton import singelton_obj
print(id(singelton_obj))
再整理下引用,copy與deepcopy的區別。
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a#傳物件的引用
c = copy.copy(a)#物件拷貝,淺拷貝
d = copy.deepcopy(a)#物件拷貝,深拷貝

a.append(5)
a[4].append('c')

print(a)#[1, 2, 3, 4, ['a', 'b', 'c'], 5]
print(b)#[1, 2, 3, 4, ['a', 'b', 'c'], 5]
print(c)#[1, 2, 3, 4, ['a', 'b', 'c']]
print(d)#[1, 2, 3, 4, ['a', 'b']]
賦值只是改變引用,原來物件資料變化,b也跟著變化。淺拷貝後為兩個獨立物件,但子物件為引用,仍然指向原來的子物件,故改變子物件資料,c也會跟著改變。深拷貝將所有物件資料獨立,原物件的改變不會影響d。