天天看點

Python标準内置函數(11-15)

1.11  函數classmethod()

在Python程式中,函數classmethod()的功能是将函數包裝成類方法。其文法格式如下所示:

classmethod(function)
           

在Python程式中,經常使用@classmethod修飾符的用法。在聲明一個類方法時,通常使用如下所示的用法:

class C:

    @classmethod

    def f(cls, arg1, arg2, ...): ...
           

修飾符@classmethod對應的函數不需要執行個體化,不需要 self 參數,但第一個參數需要是表示自身類的 cls 參數,可以來調用類的屬性,類的方法,執行個體化對象等。@classmethod形式的用法是一個函數裝飾器,用于檢視函數定義中關于函數定義的詳細說明。@classmethod既可以在類上調用(如C.f()),也可以在執行個體上調用(如C().f())。除了執行個體的類,執行個體本身被忽略。如果一個類方法在子類上調用,那麼子類對象被傳遞為隐式的第一個參數。類方法不同于C++或Java中的靜态方法,如果需要靜态方法,請參考本章後面介紹的staticmethod()函數。

在下面的執行個體檔案xiu.py中,示範了使用@classmethod修飾符的過程。

class A(object):

    bar = 1



    def func1(self):

        print('foo')



    @classmethod

    def func2(cls):

        print('func2')

        print(cls.bar)

        cls().func1()  # 調用 foo 方法

A.func2()  # 不需要執行個體化
           

執行後會輸出:

func2

1

foo
           

在下面的執行個體檔案xiu1.py中,示範了使用修飾符@classmethod修飾指定方法的過程。

class C:

    @classmethod

    def f(cls, arg1):

        print(cls)

        print(arg1)

C.f('類對象調用類方法')

c = C()

c.f('類執行個體對象調用類方法')
           

執行後會輸出:

<class '__main__.C'>

類對象調用類方法

<class '__main__.C'>

類執行個體對象調用類方法
           

在類中使用修飾符@classmethod後,當類被繼承後,子類也可以調用父類的類方法,但是第一個參數傳入的是子類的類對象。例如下面的執行個體檔案xiu2.py示範了這一用法。

class C:

    @classmethod

    def f(cls, arg1):

        print(cls)

        print(arg1)



class D(C):

    pass



D.f("子類的類對象調用父類的類方法")
           

執行後會輸出:

<class '__main__.D'>

子類的類對象調用父類的類方法
           

1.12  函數compile()

在Python程式中,函數compile()的功能是将一個字元串編譯為位元組代碼。使用函數compile()的文法格式如下所示。

compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
           
  1. source:字元串或者AST(Abstract Syntax Trees)對象,函數compile()能夠将source編譯成代碼對象,或者AST(Abstract Syntax Tree,抽象文法樹)對象。代碼對象可以由exec()或eval()執行。源可以是普通字元串,位元組字元串或AST對象。
  2. filename:代碼檔案名稱,如果不是從檔案讀取代碼則傳遞一些可辨認的值;
  3. mode:指定編譯代碼的模式,可以指定為 exec、eval、single。如果source由語句序列組成,則它可以是'exec';如果它是單個語句,則可以使用'eval';如果它由單個互動式語句組成,則可以使用'single'。
  4. flags:變量作用域,局部命名空間,如果被提供,可以是任何映射對象;
  5. flags和dont_inherit:是用來控制編譯源碼時的标志。
  6. optimize:指定編譯器的優化級别;預設值-1選擇由-O選項給出的解釋器的優化級别。顯式級别為0(無優化; __debug__為真),1(聲明被删除,__debug__為假 )或2(docstrings也被删除)。

在上述參數中,可選參數flags和dont_inherit控制哪些未來版本的語句會應用于源編譯。如果兩者都不存在(或兩者都為零),則使用在調用compile()的代碼中生效的未來語句來編譯代碼。如果給出了flags參數且沒有給出dont_inherit參數(或者為0),除了本該使用的future語句之外,由flags參數指明的future語句也會影響編譯。如果dont_inherit是非0整數,flags參數被忽略(調用compile周圍的有效的future語句被忽略)。

在下面的執行個體檔案com.py中,示範了使用函數compile()編譯字元串的過程。

str = "for i in range(0,10): print(i)"

c = compile(str,'','exec')   # 編譯為位元組代碼對象

print(c)

print(exec(c))



str = "3 * 4 + 5"

a = compile(str,'','eval')

print(eval(a))
           

在上述代碼中分别使用了函數compile()的exec和eval兩種編譯類型,執行後會輸出:

<code object <module> at 0x0000026B6382EA50, file "", line 1>

0

1

2

3

4

5

6

7

8

9

None

17
           

在下面的執行個體檔案comp.py中,示範了在互動語句中使用single的過程。

#流程語句使用exec

code1 = 'for i in range(0,10): print (i)'

compile1 = compile(code1,'','exec')

print(exec (compile1))



#簡單求值表達式用eval

code2 = '1 + 2 + 3 + 4'

compile2 = compile(code2,'','eval')

print(eval(compile2))



#互動語句用single

code3 = 'name = input("please input your name:")'

compile3 = compile(code3,'','single')

①print(exec(compile3)) #執行時顯示互動指令,提示輸入

②print(name) #執行後name變量有值
           

執行後會輸出:

0

1

2

3

4

5

6

7

8

9

None

10

please input your name:py

None

py
           

在上述代碼中,當執行到①時會顯示一個互動指令語句,提示我們輸入一個變量值,這樣變量name便會有一個值,執行②代碼時不會出錯。如果在執行②前變量name的值不存在,則會出現執行錯誤,例如下面代碼的執行過程:

>>> #互動語句用single

>>> code3 = 'name = input("please input your name:")'

>>> compile3 = compile(code3,'','single')

>>> name #執行前name變量不存在

Traceback (most recent call last):

  File "<pyshell#29>", line 1, in <module>

    name

NameError: name 'name' is not defined
           

1.13  函數complex()

在Python程式中,函數complex()的功能是建立一個值為“real + imag * j”的複數或者轉化一個字元串或數為複數。如果第一個參數為字元串,則不需要指定第二個參數。使用函數complex()的文法格式如下所示。

class complex([real[, imag]])

real:int、long、float或字元串;
imag:int、long或float類型。
           

函數complex()的傳回值形式為“real + imag * j”的複數,或将字元串或數字轉換為複數。如果第一個參數是一個字元串,它将被解釋成複數,同時函數不能有第二個參數。第二個參數不能是字元串。每個參數必須是數值類型(包括複數)。如果省略參數imag,則預設為零,構造函數會像int和float一樣進行轉換。如果省略這兩個參數,則傳回0j。

在下面的執行個體檔案compl.py中,示範了使用函數complex()建立複數的過程。

print(complex())        #當兩個參數都不提供時,傳回複數 0j。

print(complex(1, 2))

print(complex(1))       # 數字

print(complex("1"))     # 當做字元串處理
           
# 注意:下面的代碼在"+"号兩邊不能有空格,也就是不能寫成"1 + 2j",應該是"1+2j",否則會報錯

print(complex("1+2j"))



print(complex(2))       #當第一個參數為int或者float時,第二個參數可為空,表示虛部為0

print((2+0j))           #如果提供第二個參數,第二個參數也需為int或者float。
           

執行後會輸出:

0j

(1+2j)

(1+0j)

(1+0j)

(1+2j)

(2+0j)

(2+0j)
           

在Python程式中,當函數complex()中的第一個參數為字元串時,在調用時不能提供第二個參數。此時的字元串參數,需要是一個能表示複數的字元串,而且加号或者減号左右不能出現空格。例如在下面的代碼中,函數complex()的第一個參數為字元串,不能接受第二個參數。接受第二個參數時會出錯。

>>> complex('1+2j',2) #第一個參數為字元串,不能接受第二個參數,

Traceback (most recent call last):

  File "<pyshell#2>", line 1, in <module>

    complex('1+2j',2)

TypeError: complex() can't take second arg if first is a string
           

在函數complex()中的"+"号兩邊不能有空格,否則也會出現編譯錯誤,例如下面的代碼。

>>> complex('1 + 2j') #不能有空格

Traceback (most recent call last):

  File "<pyshell#3>", line 1, in <module>

    complex('1 + 2j')

ValueError: complex() arg is a malformed string
           

1.14  函數delattr()

在Python程式中,函數delattr()的功能是删除指定對象的某個屬性。使用函數delattr()的文法格式如下所示。

delattr(object, name)
           
  1. object:對象;
  2. name:是一個字元串,這個字元串必須是對象的某個屬性的名字。

例如代碼“delattr(x, 'foobar')”等同于“del x.foobar”,表示删除對象x中的屬性foobar。在下面的執行個體檔案del.py中,示範了使用函數delattr()删除指定屬性的過程。

class Coordinate:

    x = 10

    y = -5

    z = 0



point1 = Coordinate()



print('x = ', point1.x)

print('y = ', point1.y)

print('z = ', point1.z)



delattr(Coordinate, 'z')



print('--删除 z 屬性後--')

print('x = ', point1.x)

print('y = ', point1.y)



# 因為已經删除了,是以執行後會觸發錯誤

print('z = ', point1.z)
           

執行後會輸出:

x =  10

Traceback (most recent call last):

y =  -5

  File " del.py", line 19, in <module>

z =  0

    print('z = ', point1.z)

--删除 z 屬性後--

AttributeError: 'Coordinate' object has no attribute 'z'

x =  10

y =  -5
           

當使用函數delattr()删除某個屬性時,如果這個屬性不存在則會報錯,例如下面的代碼:

>>> a.name #屬性name已經删掉,不存在

Traceback (most recent call last):

  File "<pyshell#47>", line 1, in <module>

    a.name

AttributeError: 'A' object has no attribute 'name'



>>> delattr(a,'name') #再删除會報錯

Traceback (most recent call last):

  File "<pyshell#48>", line 1, in <module>

    delattr(a,'name')

AttributeError: name
           

當使用函數delattr()删除某個屬性時,不能删除對象的方法,否則将會出錯,例如下面的示範代碼:

>>> a.sayHello

<bound method A.sayHello of <__main__.A object at 0x03F014B0>>

>>> delattr(a,'sayHello') #不能用于删除方法

Traceback (most recent call last):

  File "<pyshell#50>", line 1, in <module>

    delattr(a,'sayHello')

AttributeError: sayHello

>>>
           

1.15  函數dict()

在Python程式中,函數dict()的功能是建立一個字典。在現實中有如下三種使用函數dict()的文法格式。

class dict(**kwarg)

class dict(mapping, **kwarg)

class dict(iterable, **kwarg)
           
  1. **kwargs:關鍵字;
  2. Mapping:元素的容器;
  3. Iterable:可疊代對象。

在下面的執行個體檔案dict.py中,示範了使用函數dict()建立字典的過程。

#不傳入任何參數時,傳回空字典。

print(dict())

#可以傳入鍵值對建立字典。

print(dict(a = 1))

print(dict(a = 1,b = 2))

#可以傳入映射函數建立字典。

print(dict(zip(['a','b'],[1,2])))

#可以傳入可疊代對象建立字典。

print(dict((('a',1),('b',2))))
           

執行後會輸出:

{}

{'a': 1}

{'a': 1, 'b': 2}

{'a': 1, 'b': 2}

{'a': 1, 'b': 2}