您好,登錄后才能下訂單哦!
特殊屬性
__name__ 類、函數、方法等的名字
__module__ 類定義所在的模塊
__class__ 對象或類所屬的類
__bases__ 類的基類的元組,順序為他們在基類列表中出現的順序
__doc__ 類、函數的文檔字符串,如果沒有定義則為None
__mro__ 類的面容,class.mro()返回的結果 保存在__mro__中
__dict__ 類或實例的屬性,可寫的字典
查看屬性
__dir__ 返回類或者對象的所有成員名稱列表。dir() 函數就是調用__dir__()。
使用實例調用時,如果提供__dir__(),則返回其返回值,要求是可迭代對象
如果沒有提供__dir__(),則會從實例和類及祖先類中手機信息
如果dir([obj]) 參數obj包含方法 __dir__(),該方法將被調用。如果Obj 不包含 __dir__(),該方法將最大限度收集屬性信息
dir(obj) 對于不同類型的對象obj具有不同的行為:
1.如果對象是模塊對象,返回的列表包含模塊的屬性名和變量名
2.如果對象是類型或者類對象,返回的列表包含類的屬性名,及它的基類的屬性名
3.如果obj不寫 即dir(),返回列表包含內容不同
- 在模塊中,返回模塊的屬性和變量名
- 在函數中,返回本地作用域的變量名
- 在方法中,返回本地作用域的變量名
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']
魔術方法***
分類:
1.創建、初始化與銷毀
__new__ 、__init__ 與__del__
2.hash
3.bool
4.可視化
5.運算符重載
6.容器和大小
7.可調用對象
8.上下文管理
9.反射
10.描述器
11.其它雜項
實例化
__new__方法很少使用,即使創了該方法,也會使用 return super().__new__(cls)基類obj 的 __new__方法來創建實例并返回
class A:
def __new__(cls, *args, **kwargs):
print(cls)
print(*args)
print(**kwargs)
return super().__new__(cls) # 返回cls的實例
# 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
hash(x) x都一樣,求得hash應該不變的,冪等性:一般來說,x不一樣,hash應該不一樣.
不同的hash算法都有hash沖突的問題,即不同的x求得同樣的hash值
hash值相同就會去重嗎??
不是的
list 類為為什么不可hash ??
源碼中有一句 __hash__ = None, 也就是調用 __hash__() 相當于 None(),一定報錯
所有類都繼承object,而在這個類是具有 __hash__() 方法的,如果一個類不能被hash,就把__hash__設置為 = 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'}
__hash__方法只是返回一個hash值作為set 的key,但是去重, 還需要__eq__ 來判斷兩個對象是否相等。
hash值相等,只是hash沖突,不能說明兩個對象是相等的。
因此,一般來說提供__hash__方法是為了作set或者dict的key,所以 去重,要同時提供__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
可視化
注意:類型判斷要使用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'}
運算符重載
operator模塊提供以下的特殊方法,可以將類的實例使用下面的操作符來操作
實現A類的2 個實例相減
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__方法定義,一般會in-place來修改自身
如果沒有定義 __isub__方法,則會調用__sub__
運算符重載應用場景
往往是用面向對象實現的類,需要做大量的運算,而運算符時這種運算在數學上最常見的表達方式,例如 對 - 進行了運算符重載,實現了類 的二元操作,重新定義為 tom - jerry
@functools.total_ordering裝飾器
__lt__, __le__,__eq__,__gt__,__ge__是比較大小必須實現的方法,但是全部寫完太麻煩了,,使用@functools.total_ordering裝飾器就可以大大簡化代碼
但是要求__eq__必須實現,其他方法__lt__,__le__,__gt__,__ge__ 實現其中一個
__eq__ 等于 可以推斷 不等于
__gt__ 大于 可以推斷 小于
__ge__ 大于等于 可以推斷 小于 等于
也就是用3 個方法,就可以吧所有比較解決了,所以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
容器相關方法
為什么空字典,空字符串,空元祖,空列表,空集合可以等效為False
因為 __bool__未定義時,回調用 __len__ 結果為0 等下 False
class A(dict):
def __missing__(self, key):
print('Missingn key:', key)
return 0
a = A()
print(a['k'])
------------------------------
Missingn key: k
0
可調用對象
Python 中一切皆對象,函數也不例外
函數即對象,對象foo加上(), 就是調用此函數對象的__call__()方法
def foo():
print(foo.__module__, foo.__name__)
foo()
# 等價于
foo.__call__()
可調用對象: 定義一個類,并實例化的到其實例,將實例像函數一樣調用
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) # 當adder(4,5,6)不存在時,__call__方法不會調用,Adder無adder.ert屬性,會拋異常
-------------------------------------------------------
<Point 4:5>
15
15
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。