在python中內置類寫類屬性,即只要你新建了類,系統就會自動創建這些屬性。下面就來講解一下這些自帶的屬性。
>>> class Peopre(object):
... pass
...
>>> dir(Peopre)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
下面是常用的幾個屬性
常用專有屬性 | 說明 | 觸發方式 |
---|---|---|
__init__ |
構造初始化函數 | 創建實例后,賦值時使用,在__new__ 后 |
__new__ |
生成實例所需屬性 | 創建實例時 |
__class__ |
實例所在的類 | 實例.__class__ |
__str__ |
實例字符串表示,可讀性 | print(類實例),如沒實現,使用repr結果 |
__repr__ |
實例字符串表示,准確性 | 類實例 回車 或者 print(repr(類實例)) |
__del__ |
析構 | del刪除實例 |
__dict__ |
實例自定義屬性 | vars(實例.__dict__) |
__doc__ |
類文檔,子類不繼承 | help(類或實例) |
__getattribute__ |
屬性訪問攔截器 | 訪問實例屬性時 |
__delattr__(s,name) |
刪除name屬性 | 調用時 |
__gt__(self,other) |
判斷self對象是否大於other對 | 調用時 |
__setattr__(s,name,value) |
設置name屬性 | 調用時 |
__gt__(self,other) |
判斷self對象是否大於other對象 | 調用時 |
__lt__(slef,other) |
判斷self對象是否小於other對象 | 調用時 |
__ge__(slef,other) |
判斷self對象是否大於或者等於other對象 | 調用時 |
__le__(slef,other) |
判斷self對象是否小於或者等於other對象 | 調用時 |
__eq__(slef,other) |
判斷self對象是否等於other對象 | 調用時 |
__call__(self,\*args) |
把實例對象作為函數調用 | 調用時 |
下面將講解幾個常用的:
__init__():
__ init__方法在類的一個對象被建立時,馬上運行。這個方法可以用來對你的對象做一些你希望的初始化。注意,這個名稱的開始和結尾都是雙下划線。
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print ('Hello, my name is', self.name)
說明:__ init__ 方法定義為取一個參數name(以及普通的參數self)。在這個__ init__ 里,我們只是創建一個新的域,也稱為name。注意它們是兩個不同的變量,盡管它們有相同的名字。點號使我們能夠區分它們。最重要的是,我們沒有專門調用__ init__ 方法,只是在創建一個類的新實例的時候,把參數包括在圓括號內跟在類名后面,從而傳遞給__ init__ 方法。這是這種方法的重要之處。現在,我們能夠在我們的方法中使用self.name域。這在sayHi方法中得到了驗證。
__new__ ()
__ new__ ()在__ init__()之前被調用,用於生成實例對象.利用這個方法和類屬性的特性可以實現設計模式中的單例模式.單例模式是指創建唯一對象嗎,單例模式設計的類只能實例化一個對象.
class Singleton(object):
__instance = None # 定義實例
def __init__(self):
pass
def __new__(cls, *args, **kwd): # 在__init__之前調用
if Singleton.__instance is None: # 生成唯一實例
Singleton.__instance = object.__new__(cls, *args, **kwd)
return Singleton.__instance
__str__ ()
__ str__ ()用於表示對象代表的含義,返回一個字符串.實現了__ str__ ()方法后,可以直接使用print語句輸出對象,也可以通過函數str()觸發__ str__ ()的執行.這樣就把對象和字符串關聯起來,便於某些程序的實現,可以用這個字符串來表示某個類
class Cat:
"""定義了一個Cat類"""
#初始化對象
def __init__(self, new_name, new_age):
self.name = new_name
self.age = new_age
def __str__(self):
return "%s的年齡是:%d"%(self.name, self.age)
__del__()
__ del__稱作析構方法
析構方法,當對象在內存中被釋放時,自動觸發執行。
注:此方法一般無須定義,因為在Python中,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。在程序執行結束之后,執行此方法
class Foo:
def __del__(self):
print('run __del__')
__getattribute__
:
class Itcast(object):
def __init__(self,subject1):
self.subject1 = subject1
self.subject2 = 'cpp'
#屬性訪問時攔截器,打log
def __getattribute__(self,obj):
if obj == 'subject1':
print('log subject1')
return 'redirect python'
else: #測試時注釋掉這2行,將找不到subject2
return object.__getattribute__(self,obj)
def show(self):
print('this is Itcast')
s = Itcast("python")
print(s.subject1)
print(s.subject2)
運行結果:
log subject1
redirect python
cpp
__getattribute__
的坑
class Person(object):
def __getattribute__(self,obj):
print("---test---")
if obj.startswith("a"):
return "hahha"
else:
return self.test
def test(self):
print("heihei")
t.Person()
t.a #返回hahha
t.b #會讓程序死掉
#原因是:當t.b執行時,會調用Person類中定義的__getattribute__方法,但是在這個方法的執行過程中
#if條件不滿足,所以 程序執行else里面的代碼,即return self.test 問題就在這,因為return 需要把
#self.test的值返回,那么首先要獲取self.test的值,因為self此時就是t這個對象,所以self.test就是
#t.test 此時要獲取t這個對象的test屬性,那么就會跳轉到__getattribute__方法去執行,即此時產
#生了遞歸調用,由於這個遞歸過程中 沒有判斷什么時候推出,所以這個程序會永無休止的運行下去,又因為
#每次調用函數,就需要保存一些數據,那么隨着調用的次數越來越多,最終內存吃光,所以程序 崩潰
#
# 注意:以后不要在__getattribute__方法中調用self.xxxx