特殊屬性
創(chuàng)新互聯(lián)公司專注于噶爾企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),商城網(wǎng)站建設(shè)。噶爾網(wǎng)站建設(shè)公司,為噶爾等地區(qū)提供建站服務(wù)。全流程按需定制網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)
__name__ 類、函數(shù)、方法等的名字
__module__ 類定義所在的模塊
__class__ 對(duì)象或類所屬的類
__bases__ 類的基類的元組,順序?yàn)樗麄冊(cè)诨惲斜碇谐霈F(xiàn)的順序
__doc__ 類、函數(shù)的文檔字符串,如果沒有定義則為None
__mro__ 類的面容,class.mro()返回的結(jié)果 保存在__mro__中
__dict__ 類或?qū)嵗膶傩?,可寫的字?/p>
查看屬性
__dir__ 返回類或者對(duì)象的所有成員名稱列表。dir() 函數(shù)就是調(diào)用__dir__()。
使用實(shí)例調(diào)用時(shí),如果提供__dir__(),則返回其返回值,要求是可迭代對(duì)象
如果沒有提供__dir__(),則會(huì)從實(shí)例和類及祖先類中手機(jī)信息
如果dir([obj]) 參數(shù)obj包含方法 __dir__(),該方法將被調(diào)用。如果Obj 不包含 __dir__(),該方法將最大限度收集屬性信息
dir(obj) 對(duì)于不同類型的對(duì)象obj具有不同的行為:
1.如果對(duì)象是模塊對(duì)象,返回的列表包含模塊的屬性名和變量名
2.如果對(duì)象是類型或者類對(duì)象,返回的列表包含類的屬性名,及它的基類的屬性名
3.如果obj不寫 即dir(),返回列表包含內(nèi)容不同
- 在模塊中,返回模塊的屬性和變量名
- 在函數(shù)中,返回本地作用域的變量名
- 在方法中,返回本地作用域的變量名
dir()測(cè)試如下:
classPerson:
defshow(self):
a =100
t=int(a)
print(dir())
deftest(a=50,b=100):
print(dir())
Person().show()
test()
-----------------------------------------------
['a', 'self', 't']
['a', 'b']
魔術(shù)方法***
分類:
1.創(chuàng)建、初始化與銷毀
__new__ 、__init__ 與__del__
2.hash
3.bool
4.可視化
5.運(yùn)算符重載
6.容器和大小
7.可調(diào)用對(duì)象
8.上下文管理
9.反射
10.描述器
11.其它雜項(xiàng)
實(shí)例化
__new__方法很少使用,即使創(chuàng)了該方法,也會(huì)使用 return super().__new__(cls)基類obj 的 __new__方法來創(chuàng)建實(shí)例并返回
classA:
def__new__(cls,*args,**kwargs):
print(cls)
print(*args)
print(**kwargs)
returnsuper().__new__(cls) # 返回cls的實(shí)例
# return 1
# return None
def__init__(self,name):
self.name = name
a = A("tom")
print(a)
--------------------------------------------
tom
<__main__.A object at 0x00000281924C46A0>
hash
hash(x) x都一樣,求得hash應(yīng)該不變的,冪等性:一般來說,x不一樣,hash應(yīng)該不一樣.
不同的hash算法都有hash沖突的問題,即不同的x求得同樣的hash值
hash值相同就會(huì)去重嗎??
不是的
list 類為為什么不可hash ??
源碼中有一句 __hash__ = None, 也就是調(diào)用 __hash__() 相當(dāng)于 None(),一定報(bào)錯(cuò)
所有類都繼承object,而在這個(gè)類是具有 __hash__() 方法的,如果一個(gè)類不能被hash,就把__hash__設(shè)置為 = None
classA:
def__init__(self,name,age=18):
self.name = name
def__hash__(self):
return1
# def __eq__(self, other):
# return self.name == other.name
def__repr__(self):
returnself.name
print(hash(A("tom")))
print((A('tom'),A('tom')))
print([A('tom'),A('tom')])
print('-------------------------')
s = {A('tom'),A('tom')} # set
print(s)
print({tuple('t'),tuple('t')})
print({('tom',),('tom',)})
print({"tom","tom"})
---------------------------------------------------------------
1
(tom, tom)
[tom, tom]
-------------------------
{tom, tom}# set 沒有去重
{('t',)}
{('tom',)}
{'tom'}
__hash__方法只是返回一個(gè)hash值作為set 的key,但是去重,還需要__eq__ 來判斷兩個(gè)對(duì)象是否相等。
hash值相等,只是hash沖突,不能說明兩個(gè)對(duì)象是相等的。
因此,一般來說提供__hash__方法是為了作set或者dict的key,所以去重,要同時(shí)提供__eq__方法
不可hash對(duì)象 isinstance(p1, collection.Hashable) 一定為False(import collections)
去重需要提供 __eq__方法
classA:
def__init__(self,name,age=18):
self.name = name
def__hash__(self):
return1
def__eq__(self,other):# 提供了__eq__方法
returnself.name == other.name
def__repr__(self):
returnself.name
print(hash(A("tom")))
print((A('tom'),A('tom')))
print([A('tom'),A('tom')])
print('-------------------------')
s = {A('tom'),A('tom')}
print(s)
print({tuple('t'),tuple('t')})
print({('tom',),('tom',)})
print({"tom","tom"})
------------------------------------------------
1
(tom, tom)
[tom, tom]
-------------------------
{tom}#去重了
{('t',)}
{('tom',)}
{'tom'}
bool
可視化
注意:類型判斷要使用type或isinstance, 不能通過判斷print輸出是否帶引號(hào)來判斷輸出值的類型。
classA:
def__init__(self,name,age=18):
self.name = name
self.age = age
def__repr__(self):
return"repr:{},{}".format(self.name,self.age)
def__str__(self):
return"str:{},{}".format(self.name,self.age)
def__bytes__(self):
return"{} is {}".format(self.name,self.age).encode()
print(A('tom'))
print([A('tom')])
print([str(A('tom'))])
print(bytes(A('tom')))
print('str:a,1')
s ='1'
print(s)
s1 ='a'
print(s1)
print([s1],(s,))
print({s,"a"})
-----------------------------------------------------------------
str:tom,18
[repr:tom,18]
['str:tom,18']
b'tom is 18'
str:a,1
1
a
['a'] ('1',)
{'1', 'a'}
運(yùn)算符重載
operator模塊提供以下的特殊方法,可以將類的實(shí)例使用下面的操作符來操作
實(shí)現(xiàn)A類的2 個(gè)實(shí)例相減
classA:
def__init__(self,name,age=18):
self.name = name
self.age = age
def__sub__(self,other):
returnself.age - other.age
def__isub__(self,other):
# self.age -= other.age
# return self
# return self.__clas__(self.name, self - other)
returnA(self.name,self- other)
tom = A('tom')
jerry = A('jerry',16)
print(tom - jerry)
print(jerry - tom,jerry.__sub__(tom))
print(id(tom))
tom -= jerry
print(tom.age,id(tom))
-------------------------------------------------------
2
-2 -2
1864834369800
2 1864834369800
__isub__方法定義,一般會(huì)in-place來修改自身
如果沒有定義 __isub__方法,則會(huì)調(diào)用__sub__
運(yùn)算符重載應(yīng)用場(chǎng)景
往往是用面向?qū)ο髮?shí)現(xiàn)的類,需要做大量的運(yùn)算,而運(yùn)算符時(shí)這種運(yùn)算在數(shù)學(xué)上最常見的表達(dá)方式,例如 對(duì) - 進(jìn)行了運(yùn)算符重載,實(shí)現(xiàn)了類 的二元操作,重新定義為 tom - jerry
@functools.total_ordering裝飾器
__lt__, __le__,__eq__,__gt__,__ge__是比較大小必須實(shí)現(xiàn)的方法,但是全部寫完太麻煩了,,使用@functools.total_ordering裝飾器就可以大大簡(jiǎn)化代碼
但是要求__eq__必須實(shí)現(xiàn),其他方法__lt__,__le__,__gt__,__ge__ 實(shí)現(xiàn)其中一個(gè)
__eq__ 等于可以推斷不等于
__gt__ 大于可以推斷 小于
__ge__ 大于等于可以推斷 小于 等于
也就是用3 個(gè)方法,就可以吧所有比較解決了,所以total_ordering可以不使用
classPoint:
def__init__(self,x,y):
self.x = x
self.y = y
def__hash__(self):
returnhash((self.x,self.y))
def__eq__(self,other):
returnselfisotheror(self.x == other.xandself.y == other.y)
def__add__(self,other):
returnPoint(self.x + other.x,self.y + other.y)
def__iadd__(self,other):
self.x,self.y =self.x + other.x,self.y + other.y
returnself
def__eq__(self,other): #判斷 == , !=
returnself.x == other.x
def__gt__(self,other): # 判斷> , <
returnself.x > other.x
def__ge__(self,other): # 判斷>= , <=
returnself.x >= other.x
a = Point(3,2)
b = Point(1,3)
c = Point(3,1)
print(a + b)
print(a > b)
print(a > c)
print(a < b)
print(a < c)
print(a >= c)
print(a <= c)
-----------------------------------------------------------
<__main__.Point object at 0x000001F51ACA49E8>
True
False
False
False
True
True
容器相關(guān)方法
為什么空字典,空字符串,空元祖,空列表,空集合可以等效為False
因?yàn)?__bool__未定義時(shí),回調(diào)用 __len__ 結(jié)果為0 等下 False
classA(dict):
def__missing__(self,key):
print('Missingn key:',key)
return0
a = A()
print(a['k'])
------------------------------
Missingn key: k
0
可調(diào)用對(duì)象
Python 中一切皆對(duì)象,函數(shù)也不例外
函數(shù)即對(duì)象,對(duì)象foo加上(), 就是調(diào)用此函數(shù)對(duì)象的__call__()方法
deffoo():
print(foo.__module__,foo.__name__)
foo()
# 等價(jià)于
foo.__call__()
可調(diào)用對(duì)象: 定義一個(gè)類,并實(shí)例化的到其實(shí)例,將實(shí)例像函數(shù)一樣調(diào)用
classPoint:
def__init__(self,x,y):
self.x = x
self.y = y
def__call__(self,*args,**kwargs):
return"
p = Point(4,5)
print(p)
print(p())
--------------------------------------------------------
<__main__.Point object at 0x000001F7E8E30A20>
classAdder:
def__call__(self,*args):
ret =0
forxinargs:
ret += x
self.ret = ret
returnret
adder = Adder()
print(adder(4,5,6))
print(adder.ret) # 當(dāng)adder(4,5,6)不存在時(shí),__call__方法不會(huì)調(diào)用,Adder無adder.ert屬性,會(huì)拋異常
-------------------------------------------------------
15
15