一. 内置方法和析構函數
__str__() 在調用print 列印對象時自動調用 是給使用者用的 是一個描述對象的方法
__repr__() 是給機器用的在python 解釋器裡面直接敲對象在回車後調用次方法
對于一個object來說,__str__和__repr__都是傳回對object的描述,隻是,前一個的描述簡短而友好,後一個的描述,更細節複雜一些,
對于有些資料類型,__repr__傳回的是一個string,
優點: 當一個對象屬性值很多 并且需要都需要列印 重寫了
__str__方法後簡化了代碼
1. __repr__() 方法
class Apple:
# 實作構造器
def __init__(self, color, weight):
self.color = color;
self.weight = weight;
# 重寫__repr__方法,用于實作Apple對象的“自我描述”
def __repr__(self):
return "Apple[color=" + self.color +\
", weight=" + str(self.weight) + "]"
a = Apple("紅色" , 5.68)
# 列印Apple對象
print(a) # Apple[color=紅色, weight=5.68]
print(a.__dict__) # {'color': '紅色', 'weight': 5.68}
2. __str__()方法
# 建立一個簡單的類
class person(object):
def __init__(self,name,age,height,weight):
# 定義屬性
self.name=name
self.age=age
self.height=height
self.weight=weight
def __str__(self):
return "%s-%d-%d-%d" % (self.name,self.age,self.height,self.weigh)
per2=person("張三豐",200,165,65)
# print(per2.name,per2.age,per2.height,per2.weight) #張三豐 200 165 65kg
print(per2) #張三豐 200 165 65kg
3. __len__ ()方法
# __len__ 和 len配合使用
class Students(object):
def __init__(self, *args):
self.names = args
def __len__(self):
return len(self.names)
aa=Students("111",222)
print(aa) # <__main__.Students object at 0x000002E1EBB5D5F8>
print(len(aa)) # color': '紅色', 'weight': 5.68}
4.__del__()
# 析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。析構函數往往用來做"清理善後" 的工作
# (例如在建立對象時用new開辟了一片記憶體空間,delete會自動調用析構函數後釋放記憶體)。
# 析構函數 :__del__()釋放對象自動調用
class person(object):
def run(self):
print("run")
def __init__(self, name, age, height, weight):
self.name = name
self.age = age
self.height = height
self.weight = weight
def __del__(self):
print("這裡是析構函數11111111")
per = person("張三", 25, 300, 100)
# 釋放對象 就相當于删除了 就不能通路了 這是手動釋放
del per
# 在函數裡定義的對象會在函數結束時自動釋放(删除) 可以減少記憶體浪費空間
def fun():
per2 = person("李四", 1000, 2000, 30000)
print(per2.name)
fun()
# 這裡是析構函數11111111
# 李四
# 這裡是析構函數11111111
class Person(object):
def __init__(self,name):
self.name = name
def __del__(self):
print("執行個體對象:%s"%self.name,id(self))
print("python解釋器開始回收%s對象了" % self.name)
print("類對象",id(Person)) # 類對象 2052877825944
zhangsan= Person("張三")
print("執行個體對象張三:",id(zhangsan)) # 執行個體對象張三: 2052909816408
print("------------")
lisi= Person("李四")
print("執行個體對象李四:",id(lisi)) # 執行個體對象李四: 2052909815232
# 類對象 2052877825944
# 執行個體對象張三: 2052909816408
# ------------
# 執行個體對象李四: 2052909815232
# 執行個體對象:張三 2052909816408
# python解釋器開始回收張三對象了
# 執行個體對象:李四 2052909815232
# python解釋器開始回收李四對象了
import time
class Animal(object):
# 初始化方法
# 建立完對象後會自動被調用
def __init__(self, name):
print('__init__方法被調用')
self.__name = name
# 析構方法
# 當對象被删除時,會自動被調用
def __del__(self):
print("__del__方法被調用")
print("%s對象馬上被幹掉了..."%self.__name)
# 建立對象
dog = Animal("哈皮狗")
# 删除對象
del dog
cat = Animal("波斯貓")
print(id(cat))
cat2 = cat
print(id(cat2))
cat3 = cat
print(id(cat3))
print("---馬上 删除cat對象")
del cat
print("---馬上 删除cat2對象")
del cat2
print("---馬上 删除cat3對象")
del cat3
print("程式2秒鐘後結束")
time.sleep(2)
# _init__方法被調用
# __del__方法被調用
# 哈皮狗對象馬上被幹掉了...
# __init__方法被調用
# 2710758308552
# 2710758308552
# 2710758308552
# ---馬上 删除cat對象
# ---馬上 删除cat2對象
# ---馬上 删除cat3對象
# __del__方法被調用
# 波斯貓對象馬上被幹掉了...
# 程式2秒鐘後結束
5. __call__()
# __call__
# 上面我們看到,後面加上括号可以直接調用,我們稱之後可調用對象。
# 類也是一個可調用對象,其調用傳回執行個體,故類對象的類即元類(最著名的是type)也要實作__call__方法。
# object類沒有__call__方法,是以大部分直接繼承object類的類所産生的對象不能被調用。(type類雖然也繼承了object類,但是其實作了該方法)
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __call__(self, friend):
print ('My name is %s...' % self.name)
print ('My friend is %s...' % friend)
def aa(self,cc):
print("111111111111111111111111111111111",cc,self.name)
p = Person('Bob', 'male')
print(p)
p("張三")
# 單看 p('Tim') 你無法确定 p 是一個函數還是一個類執行個體,是以,在Python中,函數也是對象,對象和函數的差別并不顯著。
p.aa("卧槽")
# <__main__.Person object at 0x0000020E64D43A90>
# My name is Bob...
# My friend is 張三...
# 111111111111111111111111111111111 卧槽 Bob
# 差別 沒有是call 隻能 對象.方法 a.bb()
class B:
def __init__(self,name):
self.name=name
def bb(self,lover):
print("111111111111111111111",lover)
a=B("張三")
a.bb("卧槽!!1")
# 差別 沒有是call 可以 使用對象直接調用方法 a()
class B:
def __init__(self,name):
self.name=name
def __call__(self,lover):
print("111111111111111111111",lover)
a=B("張三")
a("卧槽!!1")
6.__new__
# __new__方法隻負責建立
# __init__方法隻負責初始化
# _new__必須要有傳回值,傳回執行個體化出來的執行個體,這點在自己實作__new__時要特别注意,
# 可以return父類(通過super(目前類名, cls))__new__出來的執行個體,或者直接是object的__new__出來的執行個體
_new__至少要有一個參數cls,代表要執行個體化的類,此參數在執行個體化時由Python解釋器自動提供
__new__必須要有傳回值,傳回執行個體化出來的執行個體,這點在自己實作__new__時要特别注意,可以return父類__new__出來的執行個體,或者直接是object的__new__出來的執行個體
__init__有一個參數self,就是這個__new__傳回的執行個體,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要傳回值
class Dog(object):
def __init__(self,name,age):
self.name=name
self.age=age
print("----init方法-----")
def __new__(cls,nice,boy):#cls此時是Dog指向的那個類對象
print("----new方法-----")
return object.__new__(cls)
dd=Dog("張三","啦啦啦啦啦")
class ClassA(object):
def __new__(cls, *args, **kwargs):
object = super(ClassA, cls).__new__(cls)
print("in New")
return object
def __init__(self, *args, **kwargs):
print("in init")
bb=ClassA()
# in New
# in init
# 可以看出先調用__new__()
# 再調用 __init__()
print("**************************************")
class ClassA(object):
def __new__(cls, *args, **kwargs):
object = super(ClassA, cls).__new__(cls)
print("in New")
# return object
def __init__(self, *args, **kwargs):
print("in init")
cc=ClassA()
# in New
# __new__():真正的構造函數,負責傳回執行個體;
# __init__():初始化函數,負責在得到執行個體後進一步初始化一些執行個體變量。
# 如果__new__()是類函數,一定會執行;__init__()是執行個體函數,如果__new__()未傳回執行個體,那麼__init__()将沒有機會執行。
# __new__
class A:
__aa=False
def __init__(self,name,age):
self.name=name
self.age=age
def __new__(cls, *args, **kwargs):
if cls.__aa:
return cls.__aa
cls.__aa=object.__new__(A)
return cls.__aa
f=A("張三",66666)
f.cloth="小棉襖"
g=A("哈哈哈",25)
print(f)
print(g)
print(f.name)
print(g.name)
print(g.cloth)
# __new__ 的作用
# 1、__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的執行個體化過程的途徑。
# 假如我們需要一個永遠都是正數的整數類型,通過內建int,我們可能會寫出這樣的代碼。
# 3、__new__必須要有傳回值,傳回執行個體化出來的執行個體,這點在自己實作__new__時要特别注意,可以return父類(通過super(目前類名, cls))
# __new__出來的執行個體,或者直接是object的__new__出來的執行個體
# 4、__init__有一個參數self,就是這個__new__傳回的執行個體,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要傳回值
7. __hash__
# __hash__
# 傳回對象的哈希值,用整數表示。哈希值在字典查找時,可用于快速比較鍵的值。
class F(object):
def __init__(self,name,sex):
self.name=name
self.sex=sex
def __hash__(self):
return hash(self.name+ self.sex)
a=F("張三","男")
b=F("張三","1111")
print(hash(a))
print(hash(b))
# 337530981586063875
# 6407353799004837497
8. __eq__
# 如果不實作__eq__方法,那麼自定義類型會調用預設的__eq__方法, 通過預設方法進行比較的相等條件相當嚴格,隻有自己和自己比才會傳回True,表現如下
# __eq__
class Item:
def __init__(self, name):
self. name= name
def __eq__(self, other):
if self. name== other. name:
return True
else:
return False
first = Item('hello')
second = Item('hello')
print(first == second) # True
class A(object):
def __init__(self, name):
self.name = name
def __eq__(self, obj):
return self.name == obj.name
a = A("Leon")
b = A("Leon")
print(a==b) True
class student(object):
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def __eq__(self, *args, **kwargs):
return object.__eq__(self, *args, **kwargs)
# python中的對象是否相等有兩個層面,一個層面是是否是同一個對象,及在記憶體中是否共用一個記憶體區域,用is判斷,另一個是對象的值是否相等,用==判斷。
like = student("like", 25, "male")
xue = student("xue", 23, "female")
dong = student("like", 25, "male")
print(like is xue) # False
print(like is dong) # False
print(like == dong) # False
class student(object):
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __eq__(self,other):
return self.name == other.name
like = student("like",25,"male")
dong = student("like",23,"female")
print(like == dong) #True
轉載于:https://www.cnblogs.com/Sup-to/p/10873114.html