1. 程式人生 > >Python 11.05錯題本

Python 11.05錯題本

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

import copy a = [1, 2, 3, 4, ['a', 'b']]  b = a     # 引用,除非直接給a重新賦值,否則a變則b變,b變則a變 c = copy.copy(a)   # 淺複製,只會拷貝父物件, 不會拷貝父物件中的子物件,所以若a的子物件變則c 變,但是父物件變c不會變 d = copy.deepcopy(a) #深拷貝,完全拷貝,完全獨立於原物件,a變也不變 a.append(5) # 改變父物件

a[4].append('c')  #改變父物件中的 ['a', 'b']子物件

# a=[1, 2, 3, 4, ['a', 'b','c'],5] 

b=[1, 2, 3, 4, ['a', 'b','c'],5] 

c=[1, 2, 3, 4, ['a', 'b','c']] 

d=[1, 2, 3, 4, ['a', 'b']] 

本題在 Python2 下答案選 C,在 Python3 下全部錯誤。

選項 A:Python2 與 Python3 均不支援複數比較大小,Python2 中會丟擲以下錯誤:

TypeError: no ordering relation is defined for complex numbers

Python3 中會丟擲以下錯誤:

TypeError: '>' not supported between instances of 'complex' and 'complex'

tuple 的比較是從兩者的第一個元素的 ASCII 碼開始,直至兩個元素不相等為止,若前面元素都相等,則元素個數多的 tuple 較大。

1

2

3

4

(1,9) < (2,3) # True

(8,9) < (1,2,3) # False

(1,2,3) == (1,2,3) # True

(3,

2) < ('a','b') # True

選項 D:字串的比較與 tuple 類似,也是從第一個字元開始比較 ASCII 碼,直到兩個字元不相等為止。

字母與數字的ASCII 碼大小範圍是 "a-z" > "A-Z" > "0-9",D選項中 'a' < 'x',因此

1

'abc' 'xyz' # False

__new__和__init__的區別

class A(object):
    def __init__(self,*args, **kwargs):
        print "init A"
    def __new__(cls,*args, **kwargs):
        print "new A %s"%cls
     #return super(A, cls).__new__(cls, *args, **kwargs)
        return object.__new__(cls, *args, **kwargs)

1、繼承自object的新式類才有__new__

2、__new__至少要有一個引數cls,代表當前類,此引數在例項化時由Python直譯器自動識別

3、__new__必須要有返回值,返回例項化出來的例項,這點在自己實現__new__時要特別注意,可以return父類(通過super(當前類名, cls))__new__出來的例項,或者直接是object的__new__出來的例項

4、__init__有一個引數self,就是這個__new__返回的例項,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值

5、如果__new__建立的是當前類的例項,會自動呼叫__init__函式,通過return語句裡面呼叫的__new__函式的第一個引數是cls來保證是當前類例項,如果是其他類的類名,那麼實際建立返回的就是其他類的例項,其實就不會呼叫當前類的__init__函式,也不會呼叫其他類的__init__函式。

class B(A):
    def __init__(self,*args, **kwargs):
        print "init B"
    def __new__(cls,*args, **kwargs):
        print "new B %s"%cls
     #return super(B, cls).__new__(cls, *args, **kwargs)
        return object.__new__(cls, *args, **kwargs)

1、在定義子類時沒有重新定義__new__()時,Python預設是呼叫該類的直接父類的__new__()方法來構造該類的例項,如果該類的父類也沒有重寫__new__(),那麼將一直按此規矩追溯至object的__new__()方法,因為object是所有新式類的基類。

2、而如果子類中重寫了__new__()方法,那麼你可以自由選擇任意一個的其他的新式類(必定要是新式類,只有新式類必定都有__new__(),因為所有新式類都是object的後代,而經典類則沒有__new__()方法)的__new__()方法來製造例項,包括這個新式類的所有前代類和後代類,只要它們不會造成遞迴死迴圈。反正肯定不能呼叫自己的__new__,這肯定是死迴圈。

3、對於子類的__init__,其呼叫規則跟__new__是一致的,當然如果子類和父類的__init__函式都想呼叫,可以在子類的__init__函式中加入對父類__init__函式的呼叫。

4、我們在使用時,儘量使用__init__函式,不要去自定義__new__函式,因為這兩者在繼承派生時的特性還是很不一樣的。

class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))


i = PositiveInteger(-3)
print i

1、__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的例項化過程的途徑。

假如我們需要一個永遠都是正數的整數型別,通過整合int,我們可能會寫出這樣的程式碼。 

但執行後會發現,結果根本不是我們想的那樣,我們仍然得到了-3。這是因為對於int這種 不可變的物件,我們只有過載它的__new__方法才能起到自定義的作用。  這是修改後的程式碼: 

class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))


i = PositiveInteger(-3)
print i

通過過載__new__方法,我們實現了需要的功能。

2、實現單例

事實上,當我們理解了__new__方法後,我們還可以利用它來做一些其他有趣的事情,比如實現 設計模式中的 單例模式(singleton) 。  因為類每一次例項化後產生的過程都是通過__new__來控制的,所以通過過載__new__方法,我們 可以很簡單的實現單例模式。 

class Singleton(object):
    def __new__(cls):
        # 關鍵在於這,每一次例項化的時候,我們都只會返回這同一個instance物件
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance


obj1 = Singleton()
obj2 = Singleton()


obj1.attr1 = 'value1'
print obj1.attr1, obj2.attr1
print obj1 is obj2

輸出結果:
value1 value1
True
可以看到obj1和obj2是同一個例項。

class Singleton(object):
    __instance = None


    def __init__(self, *args, **kwargs):
        pass


    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            # if not hasattr(cls, 'instance'):
            cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
            cls.__instance.aa = args[0]
            print type(cls), type(cls.__instance), type(cls.__instance.aa)
        return cls.__instance

obj1 = Singleton(1, 2, 3, b=2)
obj2 = Singleton(1, 2, 3, b=2)

obj1.attr1 = 'value1'
obj2.attr2 = 'value2'
print obj1.attr1, obj1.attr2
print obj1 is obj2
print obj1.aa, obj2.attr1

結果:
<type 'type'> <class '__main__.Singleton'> <type 'int'>
value1 value2
True
1 value1

 

3、實現自定義的metaclass。