溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python——魔術(shù)方法

發(fā)布時(shí)間:2020-07-07 02:07:09 來源:網(wǎng)絡(luò) 閱讀:522 作者:AiSmile 欄目:編程語言

特殊屬性

Python——魔術(shù)方法

__name__    類、函數(shù)、方法等的名字

__module__  類定義所在的模塊

__class__   對象或類所屬的類

__bases__   類的基類的元組,順序?yàn)樗麄冊诨惲斜碇谐霈F(xiàn)的順序

__doc__     類、函數(shù)的文檔字符串,如果沒有定義則為None

__mro__     類的面容,class.mro()返回的結(jié)果 保存在__mro__中

__dict__    類或?qū)嵗膶傩裕蓪懙淖值?/span>

查看屬性

Python——魔術(shù)方法

__dir__     返回類或者對象的所有成員名稱列表。dir() 函數(shù)就是調(diào)用__dir__()。

使用實(shí)例調(diào)用時(shí),如果提供__dir__(),則返回其返回值,要求是可迭代對象

           如果沒有提供__dir__(),則會(huì)從實(shí)例和類及祖先類中手機(jī)信息

如果dir([obj])  參數(shù)obj包含方法 __dir__(),該方法將被調(diào)用。如果Obj 不包含 __dir__(),該方法將最大限度收集屬性信息

dir(obj) 對于不同類型的對象obj具有不同的行為:

1.如果對象是模塊對象,返回的列表包含模塊的屬性名和變量名

2.如果對象是類型或者類對象,返回的列表包含類的屬性名,及它的基類的屬性名

3.如果obj不寫  即dir(),返回列表包含內(nèi)容不同

- 在模塊中,返回模塊的屬性和變量名

- 在函數(shù)中,返回本地作用域的變量名

- 在方法中,返回本地作用域的變量名

dir()測試如下:

class Person:

   def show(self):

       a = 100

       t = int(a)

       print(dir())

def test(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)用對象

8.上下文管理

9.反射

10.描述器

11.其它雜項(xiàng)

實(shí)例化

Python——魔術(shù)方法

__new__方法很少使用,即使創(chuàng)了該方法,也會(huì)使用 return super().__new__(cls)基類obj 的 __new__方法來創(chuàng)建實(shí)例并返回

class A:

   def __new__(cls, *args, **kwargs):

       print(cls)

       print(*args)

       print(**kwargs)

       return super().__new__(cls) # 返回cls的實(shí)例

       # return 1

       # return None

   def __init__(self, name):

       self.name = name

a = A("tom")

print(a)

--------------------------------------------

<class '__main__.A'>

tom

<__main__.A object at 0x00000281924C46A0>


hash

Python——魔術(shù)方法

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

class A:

   def __init__(self, name, age=18):

       self.name = name

   def __hash__(self):

       return 1

   # def __eq__(self, other):

   #     return self.name == other.name

   def __repr__(self):

       return self.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'}

Python——魔術(shù)方法

__hash__方法只是返回一個(gè)hash值作為set 的key,但是去重, 還需要__eq__ 來判斷兩個(gè)對象是否相等。

hash值相等,只是hash沖突,不能說明兩個(gè)對象是相等的。

因此,一般來說提供__hash__方法是為了作set或者dict的key,所以 去重,要同時(shí)提供__eq__方法

不可hash對象 isinstance(p1, collection.Hashable) 一定為False(import collections)

去重需要提供 __eq__方法

class A:

   def __init__(self, name, age=18):

       self.name = name

   def __hash__(self):

       return 1

   def __eq__(self, other): # 提供了__eq__方法

       return self.name == other.name

   def __repr__(self):

       return self.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

Python——魔術(shù)方法

可視化

Python——魔術(shù)方法

注意:類型判斷要使用type或isinstance, 不能通過判斷print輸出是否帶引號來判斷輸出值的類型。

class A:

   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í)例使用下面的操作符來操作

Python——魔術(shù)方法

實(shí)現(xiàn)A類的2 個(gè)實(shí)例相減

class A:

   def __init__(self, name, age=18):

       self.name = name

       self.age = age

   def __sub__(self, other):

       return self.age - other.age

   def __isub__(self, other):

       # self.age -= other.age

       # return self

       # return self.__clas__(self.name, self - other)

       return A(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)用場景

往往是用面向?qū)ο髮?shí)現(xiàn)的類,需要做大量的運(yùn)算,而運(yùn)算符時(shí)這種運(yùn)算在數(shù)學(xué)上最常見的表達(dá)方式,例如 對 - 進(jìn)行了運(yùn)算符重載,實(shí)現(xiàn)了類 的二元操作,重新定義為 tom - jerry

@functools.total_ordering裝飾器

__lt__, __le__,__eq__,__gt__,__ge__是比較大小必須實(shí)現(xiàn)的方法,但是全部寫完太麻煩了,,使用@functools.total_ordering裝飾器就可以大大簡化代碼

但是要求__eq__必須實(shí)現(xiàn),其他方法__lt__,__le__,__gt__,__ge__ 實(shí)現(xiàn)其中一個(gè)

__eq__ 等于 可以推斷 不等于

__gt__ 大于 可以推斷 小于

__ge__ 大于等于 可以推斷 小于 等于

也就是用3 個(gè)方法,就可以吧所有比較解決了,所以total_ordering可以不使用

class Point:

   def __init__(self, x, y):

       self.x = x

       self.y = y

   def __hash__(self):

       return hash((self.x, self.y))

   def __eq__(self, other):

       return self is other or (self.x == other.x and self.y == other.y)

   def __add__(self, other):

       return Point(self.x + other.x, self.y + other.y)

   def __iadd__(self, other):

       self.x, self.y = self.x + other.x, self.y + other.y

       return self

   def __eq__(self, other): #判斷 == , !=

       return self.x == other.x

   def __gt__(self, other): # 判斷> , <

       return self.x > other.x

   def __ge__(self, other): # 判斷>= , <=

       return self.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)方法

Python——魔術(shù)方法

為什么空字典,空字符串,空元祖,空列表,空集合可以等效為False

因?yàn)?__bool__未定義時(shí),回調(diào)用 __len__ 結(jié)果為0 等下 False

class A(dict):

   def __missing__(self, key):

       print('Missingn key:', key)

       return 0

a = A()

print(a['k'])

------------------------------

Missingn key: k

0

可調(diào)用對象

Python 中一切皆對象,函數(shù)也不例外

函數(shù)即對象,對象foo加上(), 就是調(diào)用此函數(shù)對象的__call__()方法

def foo():

   print(foo.__module__, foo.__name__)

foo()

# 等價(jià)于

foo.__call__()

Python——魔術(shù)方法

可調(diào)用對象: 定義一個(gè)類,并實(shí)例化的到其實(shí)例,將實(shí)例像函數(shù)一樣調(diào)用

class Point:

   def __init__(self, x, y):

       self.x = x

       self.y = y

   def __call__(self, *args, **kwargs):

       return "<Point {}:{}>".format(self.x, self.y)

p = Point(4, 5)

print(p)

print(p())

--------------------------------------------------------

<__main__.Point object at 0x000001F7E8E30A20>

<Point 4:5>

class Adder:

   def __call__(self, *args):

       ret = 0

       for x in args:

           ret += x

       self.ret = ret

       return ret

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ì)拋異常

-------------------------------------------------------

<Point 4:5>

15

15


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI