元類
在python中一切皆對(duì)象,類也是對(duì)象,只不過類是一個(gè)創(chuàng)建對(duì)象的對(duì)象,我們可以在類中動(dòng)態(tài)的創(chuàng)建一個(gè)類,比如
def
func(name):
if
name ==
"
Plane
"
:
class
Plane(object):
pass
return
Plane
else
:
class
Metrorolite(object):
pass
return
Mrtroolite
雖然根據(jù)上述代碼可以動(dòng)態(tài)創(chuàng)建一個(gè)類,但是整個(gè)類的代碼仍需要我們編寫的
type()有兩種作用:
1、檢查對(duì)象類型
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))
#
#
檢查類的對(duì)象型
print
(type(people))
#
#
檢查類類型
print
(type(People))
#
#
檢查函數(shù)型
print
(type(people.func))
#
#
如果我們對(duì)其結(jié)果再次type()得到的結(jié)果都是type類型,這就驗(yàn)證了一切解釋對(duì)象
2、還有一個(gè)高大上的作用就是動(dòng)態(tài)的創(chuàng)建類
語法:type(類名, 由父類名稱組成的元組(可以為空), 包含屬性的字典(名稱和值))
返回值是一個(gè)類
#
空類
Chinese = type(
"
People
"
, (), {})
#
繼承父類,父類以元組的形式表達(dá)
Chinses = type(
"
People
"
, (object, ), {})
#
給類一些屬性(下述都是類屬性)和方法(方法可以自定義,依次是實(shí)例方法、類方法、靜態(tài)方法)
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是一個(gè)引用變量
元類的定義:
元類就是用來創(chuàng)建類的“東西”?
元類是類的類, 是類的模板
元類是用來控制如何創(chuàng)建類的, 正如類是創(chuàng)建對(duì)象的模板一樣, 而元類的主要目的是為了控制類的創(chuàng)建行為?
元類的實(shí)例化結(jié)果是我們用class定義的類,正如類的實(shí)例為對(duì)象?
type是python的一個(gè)內(nèi)建元類, 用來直接控制生成類?
python中任何class定義的類其實(shí)都是type類實(shí)例化的對(duì)象?
當(dāng)然了,你也可以創(chuàng)建自己的元類,需要繼承 type。
元類的定義和使用:
通過函數(shù)返回一個(gè)元類:
#
自定義函數(shù)
def
summary(a, b):
return
a+
b
#
這個(gè)函數(shù)的作用是修改當(dāng)前類的屬性的值和方法的功能,并且返回一個(gè)類
def
upper_attr(future_class_name, future_class_parent, future_class_attr):
#
可以修改當(dāng)前類定義的屬性的值和方法的功能
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
?
動(dòng)態(tài)語言
靜態(tài)語言和動(dòng)態(tài)語言的區(qū)別:
靜態(tài)語言(強(qiáng)類型語言)
靜態(tài)語言是在編譯時(shí)變量的數(shù)據(jù)類型即可確定的語言,多數(shù)靜態(tài)類型語言要 求在使用變量之前必須聲明數(shù)據(jù)類型。
例如:C++、Java、Delphi、C#等。
動(dòng)態(tài)語言(弱類型語言)
動(dòng)態(tài)語言是在運(yùn)行時(shí)確定數(shù)據(jù)類型的語言。變量使用之前不需要類型聲明, 通常變量的類型是被賦值的那個(gè)值的類型。
例如:PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。
動(dòng)態(tài)語言的特性:
運(yùn)行的過程中給對(duì)象綁定(添加)屬性
運(yùn)行的過程中給類綁定(添加)屬性
運(yùn)行的過程中給類綁定(添加)方法
運(yùn)行的過程中刪除屬性、方法
class
Person(object):
def
__init__
(self, name, age):
self.name
=
name
self.age
=
age
def
show():
print
(
"
通過類動(dòng)態(tài)增加類方法.
"
)
@classmethod
def
show2(cls):
print
(
"
通過類動(dòng)態(tài)增加類方法,并且打印id.
"
, cls.id)
if
__name__
==
"
__main__
"
:
person
= Person(
"
張三
"
, 22
)
#
運(yùn)行過程中,給對(duì)象添加屬性
person.phone =
"
1847015XXXX
"
print
(person.phone)
#
1847015XXXX
#
運(yùn)行過程中,對(duì)象是不能添加方法,否則會(huì)報(bào)錯(cuò)
#
person.func = show
#
person.func()
#
運(yùn)行過程中,給類增加屬性
Person.id = 10001
print
(
"
對(duì)象訪問類屬性
"
, person.id)
#
對(duì)象訪問類屬性10001
print
(
"
類訪問類屬性
"
, Person.id)
#
類訪問類屬性10001
#
運(yùn)行過程中給類增加方法
Person.func =
show
Person.func()
#
通過類動(dòng)態(tài)增加類方法.
#
運(yùn)行過程中給類增加類方法
Person.func =
show2
Person.func()
#
通過類動(dòng)態(tài)增加類方法,并且打印id。10001
__slots__
__slots__作用:
Python允許在定義class的時(shí)候,定義一個(gè)特殊變量__slots__來限制該 class能添加的屬性,當(dāng)前類就不能定義或者增加__slots__之外的屬性了
__slots__注意事項(xiàng):
__slots__只對(duì)類的實(shí)例化對(duì)象進(jìn)行限制,不對(duì)類進(jìn)行限制,__slots__變量值是以元組形式表示
__slots__不僅限制類對(duì)象的屬性,還限制類對(duì)象的方法
__slots__僅對(duì)當(dāng)前類起作用,對(duì)繼承的子類不起作用
在子類中定義__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
)
#
運(yùn)行過程中,給對(duì)象添加屬性實(shí)例對(duì)象屬性只限于name,age
#
person.phone = "1847015XXXX"
#
print(person.phone)
#
運(yùn)行過程中,給類增加屬性,__slots__ 不限制類
Person.id = 10001
print
(
"
對(duì)象訪問類屬性
"
, person.id)
#
對(duì)象訪問類屬性 10001
print
(
"
類訪問類屬性
"
, Person.id)
#
類訪問類屬性 10001
?
生成器
概念:Python中,這種一邊循環(huán)一邊計(jì)算的機(jī)制,稱為生成器:generator。
創(chuàng)建生成器的兩種方式:
? 方法1:列表生成式的 [ ] 改成 ( )
numbers = ( i for i in range(100))
通過 next() 函數(shù)獲得生成器的下一個(gè)返回值?
沒有更多的元素時(shí),拋出 StopIteration 的異常?
正確的方法是使用 for 循環(huán),因?yàn)樯善饕彩强傻鷮?duì)象,并且不需要關(guān)心 StopIteration 異
? 方法2:使用函數(shù)創(chuàng)建生成器(實(shí)例)
#
斐波那契數(shù)列
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
#
沒有更多的元素時(shí),拋出 StopIteration 的異常
#
正確的方法是使用 for 循環(huán),因?yàn)樯善饕彩强傻鷮?duì)象,并且不需要關(guān)心StopIteration 異常
print
(next(fi))
#
error
#
所以在使用生成器的時(shí)候,需要捕獲異常
fi = fibonacci(10
)
while
True:
try
:
print
(next(fi))
except
StopIteration as e:
print
(e)
break
另外生成器也可以傳遞參數(shù)通過send(參數(shù)值):
#
斐波那契數(shù)列
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
迭代器
可迭代對(duì)象:?
這里先提一下迭代器對(duì)象,如果一個(gè)對(duì)象可以通for循環(huán)進(jìn)行遍歷的對(duì)象一般都是迭代器對(duì)象;python提供了一個(gè)Iterable類就是鑒別對(duì)象是否是迭代器對(duì)象,在鑒別的過程中需要借助isinstance()方法,這個(gè)方法是鑒別對(duì)象是否屬于一個(gè)類的對(duì)象,這里不能用type()方法,因?yàn)閠ype()的作用是鑒別對(duì)象是否是類的實(shí)例化對(duì)象(通過繼承的是false)
首先先簡(jiǎn)單介紹兩者檢驗(yàn)對(duì)象類型的區(qū)別:
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
if
__name__
==
"
__main__
"
:
a
= 123
#
兩者檢驗(yàn)整型,類似這種,字符串、列表、元組、集合、字典都是一樣的結(jié)果
print
(type(a) == int)
#
True
print
(isinstance(a, int))
#
True
#
兩者主要的區(qū)別 直接通過類生成的對(duì)象,兩者檢驗(yàn)的結(jié)果是一樣的
b =
B()
print
(type(b) == B)
#
True
print
(isinstance(b, B))
#
True
#
若是父類就會(huì)有不一樣的結(jié)果
print
(type(b) == A)
#
False
print
(isinstance(b, A))
#
True
所以在檢驗(yàn)對(duì)象時(shí),采用isinstance()比較好,
from
collections
import
Iterable
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
#
實(shí)例生成器函數(shù)
def
func(self, a):
yield
a
a
= a + 1
if
a == 5
:
return
if
__name__
==
"
__main__
"
:
b
=
B()
print
(isinstance(b, Iterable))
#
False
#
像集合數(shù)據(jù)類型都是可迭代對(duì)象,字符串、列表、元組、集合、字典
b =
""
print
(isinstance(b, Iterable))
#
True
#
前面提到的生成器,他也是可迭代對(duì)象
a =
B()
b
=
a.func(0)
print
(isinstance(b, Iterable))
#
True
迭代器:
可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器:Iterator。
可以使用 isinstance() 判斷一個(gè)對(duì)象是否是 Iterator 對(duì)象:?
有兩種情況是迭代器:
1、通過生成器函數(shù)生成的生成器就是迭代器
2、通iter()函數(shù)將可迭代對(duì)象轉(zhuǎn)換成迭代器
from
collections
import
Iterator
class
A:
def
__init__
(self):
pass
class
B(A):
def
__init__
(self):
super().
__init__
()
#
實(shí)例生成器函數(shù)
def
func(self, a):
yield
a
a
= a + 1
if
a == 5
:
return
if
__name__
==
"
__main__
"
:
b
=
B()
print
(isinstance(b, Iterator))
#
False
#
像集合數(shù)據(jù)類型都是可迭代對(duì)象,字符串、列表、元組、集合、字典
b =
""
print
(isinstance(b, Iterator))
#
True
#
前面提到的生成器,他也是可迭代對(duì)象
a =
B()
b
=
a.func(0)
print
(isinstance(b, Iterator))
#
True
#
通過iter()函數(shù)將字符串、列表、元組、集合、字典轉(zhuǎn)換成迭代器
b =
{}
b
=
iter(b)
print
(isinstance(b, Iterator))
迭代器是可以自定義,只要重寫迭代器協(xié)議的兩個(gè)方法
迭代器對(duì)象符合迭代器協(xié)議,提供兩種方法: __iter__() 和 __next__()
__iter__ 返回迭代器對(duì)象,并在循環(huán)開始時(shí)隱式調(diào)用。?
__next__方法返回下一個(gè)值,并在每個(gè)循環(huán)增量處隱式調(diào)用。
__next__在沒有更多值返回時(shí)引發(fā)StopIteration異常,循環(huán)結(jié)構(gòu)隱式捕獲該 異常以停止迭代。?
class
Counter:
def
__init__
(self, low, high):
self.current
=
low
self.high
=
high
#
生成器的一般固定寫法
def
__iter__
(self):
return
self
#
在下面函數(shù)可以改變迭代器返回的下一個(gè)值
def
__next__
(self):
if
self.current >
self.high:
raise
StopIteration
else
:
self.current
+= 2
return
self.current -2
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

