元類
在python中一切皆對象,類也是對象,只不過類是一個創建對象的對象,我們可以在類中動態的創建一個類,比如
def func(name): if name == " Plane " : class Plane(object): pass return Plane else : class Metrorolite(object): pass return Mrtroolite
雖然根據上述代碼可以動態創建一個類,但是整個類的代碼仍需要我們編寫的
type()有兩種作用:
1、檢查對象類型
class People(object): def __init__ (self, id, name, employees): self.id = id self.name = name def func(self): return if __name__ == " __main__ " : id = 1001 name = " abc " employees = [1,2,3 ] people = People(id, name, employees) # 檢查整型 print (type(id)) ## 檢查字符串型 print (type(name)) # # 檢查列表型 print (type(employees)) # # 檢查類的對象型 print (type(people)) # # 檢查類類型 print (type(People)) # # 檢查函數型 print (type(people.func)) # # 如果我們對其結果再次type()得到的結果都是type類型,這就驗證了一切解釋對象
2、還有一個高大上的作用就是動態的創建類
語法:type(類名, 由父類名稱組成的元組(可以為空), 包含屬性的字典(名稱和值))
返回值是一個類
# 空類 Chinese = type( " People " , (), {}) # 繼承父類,父類以元組的形式表達 Chinses = type( " People " , (object, ), {}) # 給類一些屬性(下述都是類屬性)和方法(方法可以自定義,依次是實例方法、類方法、靜態方法) def sayHI(self): print ( " HI " ) @classmethod def sayHello(cls): print ( " Hello " ) @staticmethod def sayBye(): print ( " Bye " ) Chinese = type( " People " , (object, ), { " id " : 1001, " name " : " zhangsan " , " func1 " : sayHI, " func2 " : sayHello, " func3 " : sayBye}) # Chinese 不是類名,People是類名,Chinese是一個引用變量
元類的定義:
元類就是用來創建類的“東西”?
元類是類的類, 是類的模板
元類是用來控制如何創建類的, 正如類是創建對象的模板一樣, 而元類的主要目的是為了控制類的創建行為?
元類的實例化結果是我們用class定義的類,正如類的實例為對象?
type是python的一個內建元類, 用來直接控制生成類?
python中任何class定義的類其實都是type類實例化的對象?
當然了,你也可以創建自己的元類,需要繼承 type。
元類的定義和使用:
通過函數返回一個元類:
# 自定義函數 def summary(a, b): return a+ b # 這個函數的作用是修改當前類的屬性的值和方法的功能,并且返回一個類 def upper_attr(future_class_name, future_class_parent, future_class_attr): # 可以修改當前類定義的屬性的值和方法的功能 newAttr = {} for name, value in future_class_attr.items(): if name == " bar " : newAttr[name] = " 變量值修改了 " if name == " func " : newAttr[name] = summary return type(future_class_name, future_class_parent, newAttr) class Operation(object, metaclass= upper_attr): bar = " 修改之前的值 " func = None if __name__ == " __main__ " : print (Operation.bar) # 變量值修改了 print (Operation.func(2, 4)) # 返回值6
通過繼承type生成元類(博主也沒有看懂,了解即可,用到極少):
class Meta(type): def __init__ (cls, *args, ** kwargs): super(). __init__ (* args) def __new__ (cls, *args, **kwargs):
name, bases, attrs = args
return super().__new__(cls, name, bases, attrs)
class M_Class(metaclass=Meta):
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
def __init__(self):
pass
?
動態語言
靜態語言和動態語言的區別:
靜態語言(強類型語言)
靜態語言是在編譯時變量的數據類型即可確定的語言,多數靜態類型語言要 求在使用變量之前必須聲明數據類型。
例如:C++、Java、Delphi、C#等。
動態語言(弱類型語言)
動態語言是在運行時確定數據類型的語言。變量使用之前不需要類型聲明, 通常變量的類型是被賦值的那個值的類型。
例如:PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
動態語言的特性:
運行的過程中給對象綁定(添加)屬性
運行的過程中給類綁定(添加)屬性
運行的過程中給類綁定(添加)方法
運行的過程中刪除屬性、方法
class Person(object): def __init__ (self, name, age): self.name = name self.age = age def show(): print ( " 通過類動態增加類方法. " ) @classmethod def show2(cls): print ( " 通過類動態增加類方法,并且打印id. " , cls.id) if __name__ == " __main__ " : person = Person( " 張三 " , 22 ) # 運行過程中,給對象添加屬性 person.phone = " 1847015XXXX " print (person.phone) # 1847015XXXX # 運行過程中,對象是不能添加方法,否則會報錯 # person.func = show # person.func() # 運行過程中,給類增加屬性 Person.id = 10001 print ( " 對象訪問類屬性 " , person.id) # 對象訪問類屬性10001 print ( " 類訪問類屬性 " , Person.id) # 類訪問類屬性10001 # 運行過程中給類增加方法 Person.func = show Person.func() # 通過類動態增加類方法. # 運行過程中給類增加類方法 Person.func = show2 Person.func() # 通過類動態增加類方法,并且打印id。10001
__slots__
__slots__作用:
Python允許在定義class的時候,定義一個特殊變量__slots__來限制該 class能添加的屬性,當前類就不能定義或者增加__slots__之外的屬性了
__slots__注意事項:
__slots__只對類的實例化對象進行限制,不對類進行限制,__slots__變量值是以元組形式表示
__slots__不僅限制類對象的屬性,還限制類對象的方法
__slots__僅對當前類起作用,對繼承的子類不起作用
在子類中定義__slots__,子類允許定義的屬性就是自身的__slots__加上父類的 __slots__
class Person(object): __slots__ = ( " name " , " age " ) def __init__ (self, name, age): self.name = name self.age = age if __name__ == " __main__ " : person = Person( " 張三 " , 22 ) # 運行過程中,給對象添加屬性實例對象屬性只限于name,age # person.phone = "1847015XXXX" # print(person.phone) # 運行過程中,給類增加屬性,__slots__ 不限制類 Person.id = 10001 print ( " 對象訪問類屬性 " , person.id) # 對象訪問類屬性 10001 print ( " 類訪問類屬性 " , Person.id) # 類訪問類屬性 10001
?
生成器
概念:Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。
創建生成器的兩種方式:
? 方法1:列表生成式的 [ ] 改成 ( )
numbers = ( i for i in range(100))
通過 next() 函數獲得生成器的下一個返回值?
沒有更多的元素時,拋出 StopIteration 的異常?
正確的方法是使用 for 循環,因為生成器也是可迭代對象,并且不需要關心 StopIteration 異
? 方法2:使用函數創建生成器(實例)
# 斐波那契數列 def fibonacci(num): a = 0 b = 1 count = 0 temp = 1 while count < num: yield b a, b = b, a+ b count += 1 fi = fibonacci(4 ) print (next(fi)) # 1 print (next(fi)) # 1 print (next(fi)) # 2 print (next(fi)) # 3 # 沒有更多的元素時,拋出 StopIteration 的異常 # 正確的方法是使用 for 循環,因為生成器也是可迭代對象,并且不需要關心StopIteration 異常 print (next(fi)) # error # 所以在使用生成器的時候,需要捕獲異常 fi = fibonacci(10 ) while True: try : print (next(fi)) except StopIteration as e: print (e) break
另外生成器也可以傳遞參數通過send(參數值):
# 斐波那契數列 def fibonacci(num): a = 0 b = 1 count = 0 temp = 1 while count < num: temp = yield temp* b print ( " temp{}:{} " .format(count, temp)) a, b = b, a+ b count += 1 fi = fibonacci(10 ) print (next(fi)) while True: try : print (fi.send(1 )) except : break
迭代器
可迭代對象:?
這里先提一下迭代器對象,如果一個對象可以通for循環進行遍歷的對象一般都是迭代器對象;python提供了一個Iterable類就是鑒別對象是否是迭代器對象,在鑒別的過程中需要借助isinstance()方法,這個方法是鑒別對象是否屬于一個類的對象,這里不能用type()方法,因為type()的作用是鑒別對象是否是類的實例化對象(通過繼承的是false)
首先先簡單介紹兩者檢驗對象類型的區別:
class A: def __init__ (self): pass class B(A): def __init__ (self): super(). __init__ () if __name__ == " __main__ " : a = 123 # 兩者檢驗整型,類似這種,字符串、列表、元組、集合、字典都是一樣的結果 print (type(a) == int) # True print (isinstance(a, int)) # True # 兩者主要的區別 直接通過類生成的對象,兩者檢驗的結果是一樣的 b = B() print (type(b) == B) # True print (isinstance(b, B)) # True # 若是父類就會有不一樣的結果 print (type(b) == A) # False print (isinstance(b, A)) # True
所以在檢驗對象時,采用isinstance()比較好,
from collections import Iterable class A: def __init__ (self): pass class B(A): def __init__ (self): super(). __init__ () # 實例生成器函數 def func(self, a): yield a a = a + 1 if a == 5 : return if __name__ == " __main__ " : b = B() print (isinstance(b, Iterable)) # False # 像集合數據類型都是可迭代對象,字符串、列表、元組、集合、字典 b = "" print (isinstance(b, Iterable)) # True # 前面提到的生成器,他也是可迭代對象 a = B() b = a.func(0) print (isinstance(b, Iterable)) # True
迭代器:
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator。
可以使用 isinstance() 判斷一個對象是否是 Iterator 對象:?
有兩種情況是迭代器:
1、通過生成器函數生成的生成器就是迭代器
2、通iter()函數將可迭代對象轉換成迭代器
from collections import Iterator class A: def __init__ (self): pass class B(A): def __init__ (self): super(). __init__ () # 實例生成器函數 def func(self, a): yield a a = a + 1 if a == 5 : return if __name__ == " __main__ " : b = B() print (isinstance(b, Iterator)) # False # 像集合數據類型都是可迭代對象,字符串、列表、元組、集合、字典 b = "" print (isinstance(b, Iterator)) # True # 前面提到的生成器,他也是可迭代對象 a = B() b = a.func(0) print (isinstance(b, Iterator)) # True # 通過iter()函數將字符串、列表、元組、集合、字典轉換成迭代器 b = {} b = iter(b) print (isinstance(b, Iterator))
迭代器是可以自定義,只要重寫迭代器協議的兩個方法
迭代器對象符合迭代器協議,提供兩種方法: __iter__() 和 __next__()
__iter__ 返回迭代器對象,并在循環開始時隱式調用。?
__next__方法返回下一個值,并在每個循環增量處隱式調用?! ?
__next__在沒有更多值返回時引發StopIteration異常,循環結構隱式捕獲該 異常以停止迭代。?
class Counter: def __init__ (self, low, high): self.current = low self.high = high # 生成器的一般固定寫法 def __iter__ (self): return self # 在下面函數可以改變迭代器返回的下一個值 def __next__ (self): if self.current > self.high: raise StopIteration else : self.current += 2 return self.current -2
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
