isinstance()
判斷isinstance(obj,cls)中obj是否是cls類的對(duì)象
class
Person:
def
__init__
(self,name):
self.name
=
name
p
= Person(
'
Jane
'
)
print
(isinstance(p,Person))
#
True
issubclass()
判斷issubclass(sub,super)中sub是否是super類的派生類
class
Person:
def
__init__
(self,name):
self.name
=
name
class
Father(Person):
pass
print
(issubclass(Father,Person))
#
True
print
(issubclass(Person,Father))
#
False
反射
反射就是用字符串類型的名字去操作變量,python中的一切事物皆為對(duì)象(都可以使用反射)
1.hasattr()
函數(shù)用于判斷對(duì)象是否包含對(duì)應(yīng)的屬性,通常和getattr一起搭配使用,先用hasattr判斷是否這個(gè)對(duì)象含有這個(gè)屬性,如果有就通過(guò)getattr來(lái)拿值,如果沒(méi)有就提示沒(méi)有這個(gè)屬性
class
Person:
age
= 20
def
__init__
(self,name,height,weight):
self.name
=
name
self.height
=
height
self.weight
=
weight
def
fuc(self):
print
(
'
weight...height...
'
)
#1
if
hasattr(Person,
'
age
'
):
print
(getattr(Person,
'
age
'
))
#
20
else
:
print
(
'
沒(méi)有這個(gè)類屬性!
'
)
#2
p
= Person(
'
Adson
'
,1.6,75
)
if
hasattr(p,
'
bmi
'
):
print
(getattr(p,
'
bmi
'
))
else
:
print
(
'
沒(méi)有這個(gè)屬性!
'
)
#
沒(méi)有這個(gè)屬性!
#3
if
hasattr(p,
'
fuc
'
):
getattr(p,
'
fuc
'
)()
#
weight...height...
else
:
print
(
'
沒(méi)有這個(gè)方法!
'
)
2.getattr()
函數(shù)用于返回一個(gè)對(duì)象屬性值
(1)反射對(duì)象的屬性
class
A:
def
__init__
(self,name):
self.name
=
name
a
= A(
'
Adson
'
)
ret
= getattr(a,
'
name
'
)
print
(ret)
#
Adson
(2)反射對(duì)象的方法
class
A:
def
fuc(self):
print
(
'
This is fuc!
'
)
a
=
A()
ret
= getattr(a,
'
fuc
'
)
print
(ret)
#
<__main__.A object at 0x00000000024E1C88>> 獲得一個(gè)綁定方法的地址
ret()
#
This is fuc! 在ret后加上括號(hào)去調(diào)用方法
(3)反射類的屬性
class
A:
age
= 18
ret
= getattr(A,
'
age
'
)
print
(ret)
#
18
(4)反射類的方法(classmethod、staticmethod)
一般的調(diào)用方式是類名.方法名
class
A:
@classmethod
def
fuc(cls):
print
(
'
This is class fuc!
'
)
ret
= getattr(A,
'
fuc
'
)
print
(ret)
#
> 獲得一個(gè)綁定方法
ret()
#
This is class fuc!
getattr(A,
'
fuc
'
)()
#
This is class fuc! 簡(jiǎn)寫
(5)反射模塊的變量
先建立一個(gè)模塊,模塊名pyfile.py,增加一個(gè)變量
dic = {
'
apple
'
: 18,
'
banana
'
: 20}
然后通過(guò)我的模塊反射pyfile模塊的變量
import
pyfile
print
(pyfile.dic)
#
{'apple': 18, 'banana': 20}
ret = getattr(pyfile,
'
dic
'
)
print
(ret)
#
{'apple': 18, 'banana': 20}
(6)反射模塊的方法
先建立一個(gè)模塊,模塊名pyfile.py,增加一個(gè)方法
def
fuc():
print
(
'
abc123aaa!!!
'
)
然后通過(guò)我的模塊反射pyfile模塊方法
import
pyfile
ret
= getattr(pyfile,
'
fuc
'
)
print
(ret)
#
ret()
#
abc123aaa!!!
getattr(pyfile,
'
fuc
'
)()
#
abc123aaa!!!
(7)反射模塊的類
先建立一個(gè)模塊,模塊名pyfile.py,增加一個(gè)類
class
B:
price
= 200
def
__init__
(self,name):
self.name
=
name
def
fuc(self):
print
(
'
This classB fuc..
'
+ self.name)
然后通過(guò)我的模塊反射pyfile模塊方法
import
pyfile
b
= getattr(pyfile,
'
B
'
)(
'
Josn
'
)
#
getattr相當(dāng)于拿到了這個(gè)模塊的B類 并進(jìn)行實(shí)例化了一個(gè)b對(duì)象
print
(b.
__dict__
)
#
{'name': 'Josn'}
print
(b.price)
#
200
b.fuc()
#
This classB fuc..Josn
(8)反射自身模塊的變量
通過(guò)sys.modules['__main__']找到當(dāng)前的模塊
import
time
import
sys
t
=
time.asctime(time.localtime(time.time()))
print
(t)
#
Mon Sep 9 22:36:40 2019
print
(sys.modules[
'
__main__
'
])
#
print
(sys.modules[
'
__main__
'
].t)
#
Mon Sep 9 22:38:01 2019
ret = getattr(sys.modules[
'
__main__
'
],
'
t
'
)
print
(ret)
#
Mon Sep 9 22:39:05 2019
(9)反射自身模塊的方法
import
sys
def
fuc():
print
(
'
abc123...
'
)
ret
= getattr(sys.modules[
'
__main__
'
],
'
fuc
'
)
print
(ret)
#
ret()
#
abc123...
getattr(sys.modules[
'
__main__
'
],
'
fuc
'
)()
#
abc123...
3.setattr()
用于設(shè)置屬性值,該屬性不一定是存在的
class
Person:
age
= 20
def
__init__
(self,name,height,weight):
self.name
=
name
self.height
=
height
self.weight
=
weight
#
對(duì)一個(gè)對(duì)象修改
p = Person(
'
Adson
'
,1.6,75
)
setattr(p,
'
name
'
,
'
Jane
'
)
setattr(p,
'
height
'
,1.7
)
setattr(p,
'
gender
'
,
'
male
'
)
print
(p.
__dict__
)
#
{'name': 'Jane', 'height': 1.7, 'weight': 75, 'gender': 'male'}
#
對(duì)一個(gè)類修改
print
(Person.
__dict__
)
#
{'__module__': '__main__', 'age': 20, '__init__':
,
'__dict__':
, '__weakref__':
, '__doc__': None}
setattr(Person,
'
age
'
,21
)
setattr(Person,
'
name
'
,
'
Jane
'
)
setattr(Person,
'
height
'
,1.7
)
setattr(Person,
'
gender
'
,
'
male
'
)
print
(Person.
__dict__
)
#
{'__module__': '__main__', 'age': 21, '__init__':
,
'__dict__':
, '__weakref__':
, '__doc__': None,
'name': 'Jane', 'height': 1.7, 'gender': 'male'}
這里的不同之處在于對(duì)象和類它們存放值的命名空間不同
4.delattr()
用于刪除屬性
class
Person:
age
= 20
def
__init__
(self,name,height,weight):
self.name
=
name
self.height
=
height
self.weight
=
weight
p
= Person(
'
Adson
'
,1.6,75
)
print
(p.
__dict__
)
#
{'name': 'Adson', 'height': 1.6, 'weight': 75}
delattr(p,
'
height
'
)
print
(p.
__dict__
)
#
{'name': 'Adson', 'weight': 75}
print
(Person.
__dict__
[
'
age
'
])
#
20
delattr(Person,
'
age
'
)
print
(Person.
__dict__
[
'
age
'
])
#
KeyError: 'age'
?
內(nèi)置類方法
內(nèi)置的類方法和內(nèi)置函數(shù)之間有著千絲萬(wàn)縷的關(guān)系
1.__str__
當(dāng)我們定義一個(gè)類,并實(shí)例化一個(gè)對(duì)象,再對(duì)這個(gè)對(duì)象去print
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(str(a))
#
<__main__.A object at 0x00000000020D7A58>
這里返回了這個(gè)對(duì)象的內(nèi)存地址,我們?cè)僭贏類里面添加一個(gè)__str__方法,看一看結(jié)果是什么
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__str__
(self):
return
'
name = %s,price = %s,types = %s
'
%
(self.name,self.price,self.types)
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(a)
#
name = AAA,price = 200,types = A
可以這么說(shuō)我們?cè)诿看未蛴∫粋€(gè)對(duì)象的時(shí)候就是在調(diào)用obj.__str__,且__str__方法需要返回一個(gè)字符串,當(dāng)做這個(gè)類的描寫;當(dāng)我們使用print這個(gè)對(duì)象時(shí)會(huì)打印出__str__方法return出來(lái)的字符串
2.__repr__
先說(shuō)一下repr()方法,它能讓我們輸入的數(shù)據(jù)原形畢露
print
(repr(1))
#
1
print
(repr(
'
1
'
))
#
'1'
print
(repr(
'
aaa
'
))
#
'aaa'
print
(repr({
'
a
'
:1,
'
b
'
:2}))
#
{'a': 1, 'b': 2}
和__str__一樣我們?cè)诙x一個(gè)類后去print它實(shí)例化的對(duì)象,會(huì)獲得到一個(gè)對(duì)象的內(nèi)存地址
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
a = A(
'
AAA
'
,200,
'
A
'
)
print
(repr(a))
#
<__main__.A object at 0x00000000024E7A58>
然后我們?cè)僭贏中添加__repr__方法看一下print的結(jié)果
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__repr__
(self):
return
'
name = %s,price = %s,types = %s
'
%
(self.name, self.price, self.types)
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(repr(a))
#
name = AAA,price = 200,types = A
print
(a)
#
name = AAA,price = 200,types = A
因?yàn)槲覀冊(cè)陬愔卸x了一個(gè)__repr__方法,這里我們print對(duì)象a的時(shí)候就相當(dāng)于是調(diào)用了里面的__repr__方法即a.__repr__
如果一個(gè)類中的__str__和__repr__同時(shí)存在的話,那么最后的打印結(jié)果是什么呢?
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__str__
(self):
return
'
str(name = %s,price = %s,types = %s)
'
%
(self.name,self.price,self.types)
def
__repr__
(self):
return
'
repr(name = %s,price = %s,types = %s)
'
%
(self.name, self.price, self.types)
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(repr(a))
#
repr(name = AAA,price = 200,types = A) 即a.__repr__
print
(
'
%r
'
%a)
#
repr(name = AAA,price = 200,types = A)
print
(str(a))
#
str(name = AAA,price = 200,types = A) 即a.__str__
print
(
'
%s
'
%a)
#
str(name = AAA,price = 200,types = A)
print
(a)
#
str(name = AAA,price = 200,types = A)
如果一個(gè)類中 有 __str__方法,那么它就會(huì)先找__str__, 沒(méi)有 的話就再找__repr__方法,再 沒(méi)有 的話就會(huì)找它父類的__str__方法
__str__方法和__repr__方法能夠返回該對(duì)象一個(gè)規(guī)范化的信息
3.__len__
我們將一個(gè)實(shí)例化的對(duì)象直接print它的len看一看會(huì)出現(xiàn)什么結(jié)果
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
a = A(
'
AAA
'
,200,
'
A
'
)
print
(len(a))
#
TypeError: object of type 'A' has no len()
結(jié)果報(bào)錯(cuò)說(shuō)A少了一個(gè)len函數(shù),也就是我們只有在A中加上一個(gè)__len__的方法才能去計(jì)算長(zhǎng)度相關(guān)的東西
計(jì)算屬性的長(zhǎng)度:
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__len__
(self):
return
len(self.name)
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(len(a))
#
3
計(jì)算一個(gè)列表屬性有幾個(gè)元素:
class
A:
def
__init__
(self,goods =
[]):
self.goods
=
[]
def
__len__
(self):
return
len(self.goods)
a
=
A()
print
(len(a))
#
0
a.goods.append(
'
Banana
'
)
a.goods.append(
'
Apple
'
)
a.goods.append(
'
Orange
'
)
a.goods.append(
'
Pear
'
)
print
(len(a))
#
4
4.__call__
用于打印這個(gè)對(duì)象的屬性
class
A:
gender
=
'
male
'
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__call__
(self, *args, **
kwargs):
return
self.name,self.price,self.types,self.gender
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(a())
#
('AAA', 200, 'A', 'male')
print
(A(
'
AAA
'
,200,
'
A
'
)())
#
('AAA', 200, 'A', 'male')
5.__eq__
class
A:
__instance
=
False
def
__init__
(self,name,age,height):
self.name
=
name
self.age
=
age
self.height
=
height
def
__eq__
(self, other):
if
self.name == other.name
and
self.height ==
other.height:
return
True
else
:
return
False
a1
= A(
'
Jane
'
,20,55
)
a2
= A(
'
Jane
'
,18,55
)
print
(a1 == a2)
#
True
6.__hash__
控制對(duì)象中的哈希值和另外一個(gè)對(duì)象的哈希值是否相等
class
A:
def
__init__
(self,name,age,height):
self.name
=
name
self.age
=
age
self.height
=
height
def
__hash__
(self):
return
hash(self.age + self.height) +
hash(self.name)
a1
= A(
'
Jane
'
,20,55
)
a2
= A(
'
Jane
'
,18,55
)
print
(hash(a1))
#
-1393240518857837779
print
(hash(a2))
#
-1393240518857837781
7.__new__
創(chuàng)建一個(gè)對(duì)象
class
A:
height
= 18
def
__init__
(self):
self.name
=
'
Aane
'
self.price
= 300
self.types
=
'
aaa
'
def
__new__
(cls, *args, **
kwargs):
print
(
'
實(shí)例化一個(gè)對(duì)象...
'
)
return
object.
__new__
(cls, *args, **
kwargs)
a
= A()
#
實(shí)例化一個(gè)對(duì)象...
print
(a.
__dict__
)
#
{'name': 'Aane', 'price': 300, 'types': 'aaa'}
單例模式:限制一個(gè)類始終只有一個(gè)實(shí)例,因?yàn)橐话銇?lái)講一個(gè)類可以產(chǎn)生無(wú)數(shù)個(gè)對(duì)象
在這里我們創(chuàng)建三個(gè)對(duì)象并打印它們的內(nèi)存地址可以發(fā)現(xiàn)它們是不同的
class
A:
def
__init__
(self):
self.name
=
'
aaa
'
a1
=
A()
a2
=
A()
a3
=
A()
print
(a1)
#
<__main__.A object at 0x00000000025B1D68>
print
(a2)
#
<__main__.A object at 0x00000000025CD0F0>
print
(a3)
#
<__main__.A object at 0x00000000025CD128>
所以在我們第一次實(shí)例化這個(gè)類的時(shí)候就創(chuàng)建一個(gè)實(shí)例化的對(duì)象,那么我們?cè)僖淮螌?shí)例化一個(gè)對(duì)象的話該如何再去使用之前的實(shí)例化對(duì)象呢?
class
A:
__instance
=
False
def
__init__
(self,name,age):
self.name
=
name
self.age
=
age
def
__new__
(cls,*args,**
kwargs):
if
cls.
__instance
:
return
cls.
__instance
cls.
__instance
= object.
__new__
(A)
return
cls.
__instance
a1
= A(
'
Jogn
'
,33
)
a2
= A(
'
Jane
'
,35
)
a3
= A(
'
KKK
'
,55
)
print
(a1)
#
<__main__.A object at 0x000000000217D198>
print
(a1.
__dict__
)
#
{'name': 'KKK', 'age': 55}
print
(a2)
#
<__main__.A object at 0x000000000217D198>
print
(a2.
__dict__
)
#
{'name': 'KKK', 'age': 55}
print
(a3)
#
<__main__.A object at 0x000000000217D198>
print
(a3.
__dict__
)
#
{'name': 'KKK', 'age': 55}
print
(id(a1),id(a2),id(a3))
#
41734552 41734552 41734552
8.__del__
析構(gòu)函數(shù):當(dāng)對(duì)象結(jié)束其生命周期,如對(duì)象所在的函數(shù)已調(diào)用完畢時(shí),系統(tǒng)自動(dòng)執(zhí)行析構(gòu)函數(shù),它往往用來(lái)做"清理善后"的工作。當(dāng)我們直接刪除一個(gè)實(shí)例化的對(duì)象再去打印它,就會(huì)報(bào)錯(cuò)告訴我們這個(gè)對(duì)象已經(jīng)不存在了
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
a
= A(
'
AAA
'
,200,
'
A
'
)
del
a
print
(a)
#
NameError: name 'a' is not defined
我們?cè)僭贏中添加一個(gè)__del__方法
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__del__
(self):
print
(
'
這個(gè)對(duì)象%s已被刪除!
'
%
self.name)
del
self
a
= A(
'
AAA
'
,200,
'
A
'
)
del
a
#
這個(gè)對(duì)象AAA已被刪除! 這里相當(dāng)于調(diào)用了a.__dict__
print
(a)
#
NameError: name 'a' is not defined
8.__getitem__
模擬字典的方式來(lái)拿值
class
A:
gender
=
'
male
'
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__getitem__
(self, item):
if
hasattr(self,item):
return
getattr(self,item)
return
'
沒(méi)有找到這個(gè)值!
'
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(a[
'
name
'
])
#
AAA
print
(a[
'
price
'
])
#
200
print
(a[
'
types
'
])
#
A
print
(a[
'
gender
'
])
#
male
print
(a[
'
sex
'
])
#
沒(méi)有找到這個(gè)值!
9.__setitem__
模擬字典的方式來(lái)設(shè)值
class
A:
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__setitem__
(self,key,value):
#
重新設(shè)定一個(gè)新的值
self.
__dict__
[
'
key
'
] =
value
a
= A(
'
AAA
'
,200,
'
A
'
)
print
(a.
__dict__
)
#
{'name': 'AAA', 'price': 200, 'types': 'A'}
a.
__dict__
[
'
name
'
] =
'
BBB
'
a.
__dict__
[
'
price
'
] = 300
a.
__dict__
[
'
types
'
] =
'
C
'
a.
__dict__
[
'
gender
'
] =
'
male
'
#
增加了一個(gè)新的屬性gender
print
(a.
__dict__
)
#
{'name': 'BBB', 'price': 300, 'types': 'C', 'gender': 'male'}
10.__delitem__
模擬字典的方式來(lái)刪除
class
A:
gender
=
'
male
'
def
__init__
(self,name,price,types):
self.name
=
name
self.price
=
price
self.types
=
types
def
__delitem__
(self, key):
print
(
'
%s已刪除!
'
%
key)
del
self.
__dict__
[key]
a
= A(
'
AAA
'
,200,
'
A
'
)
del
a[
'
name
'
]
#
name已刪除!
del
a[
'
price
'
]
#
price已刪除!
print
(a.
__dict__
)
#
{'types': 'A'}
?
問(wèn)題總結(jié)
1.有很多對(duì)象,它們的姓名和性別相同但是年齡不同,如何這種情況的對(duì)象去重?
class
A:
def
__init__
(self,name,sex,age):
self.name
=
name
self.sex
=
sex
self.age
=
age
def
__eq__
(self, other):
if
self.name == other.name
and
self.sex ==
other.sex:
return
True
return
False
def
__hash__
(self):
return
hash(self.name+
self.sex)
a
= A(
'
Json
'
,
'
male
'
,26
)
b
= A(
'
Json
'
,
'
male
'
,30
)
print
(set((a,b)))
#
set()依賴對(duì)象的 __eq__和__hash__ {<__main__.A object at 0x0000000002761DD8>}
2.撲克牌問(wèn)題
import
json
from
collections
import
namedtuple
Card
= namedtuple(
'
Card
'
,[
'
rank
'
,
'
suit
'
])
#
rank牌面的大小 suit牌面的花色
class
FrenchDeck:
ranks
= [str(n)
for
n
in
range(2,11)] + list(
'
JQKA
'
)
suits
= [
'
紅心
'
,
'
方塊
'
,
'
梅花
'
,
'
黑桃
'
]
def
__init__
(self):
self._cards
= [Card(rank,suit)
for
rank
in
FrenchDeck.ranks
for
suit
in
FrenchDeck.suits]
def
__len__
(self):
return
len(self._cards)
def
__getitem__
(self, item):
return
self._cards[item]
def
__setitem__
(self,key,value):
self._cards[key]
=
value
def
__str__
(self):
return
json.dumps(self._cards,ensure_ascii=
False)
deck
=
FrenchDeck()
print
(deck[10])
#
Card(rank='4', suit='梅花')
from
random
import
choice
print
(choice(deck))
#
Card(rank='3', suit='方塊')
print
(choice(deck))
#
Card(rank='9', suit='方塊')
from
random
import
shuffle
shuffle(deck)
print
(deck[10])
#
Card(rank='2', suit='方塊')
print
(deck)
#
打印所有牌色
print
(deck[:5])
#
[Card(rank='6', suit='梅花'), Card(rank='3', suit='方塊'), Card(rank='10', suit='紅心'),
#Card(rank='9', suit='紅心'), Card(rank='4', suit='方塊')]
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

