1. 程式人生 > >Python標準內建函式(11-15)

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}