本博客所有文章僅僅是博主做筆記之用,博客內容並不詳細(以後有空會修改完善),思維也有跳躍之處,想詳細學習博客內容可參考文章後面的參考鏈接,祝學習快樂。
本節要點:
- 類的語法
- 類變量和實例變量
- 特殊方法
- 繼承和多態
- 私有屬性和方法
- 靜態方法、類方法、屬性方法
- 反射
1.語法
class ClassName(object): #定義一個類
"""docstring for ClassName"""
def __init__(self, arg): #構造函數
super(ClassName, self).__init__()
self.arg = arg
x = ClassName("yang") #生成一個對象
2. 類變量和實例變量
>>> class ClassName(object):
"""docstring for ClassName"""
age = 100 #類變量
list_1 = [] #類變量
def __init__(self, name, age):
super(ClassName, self).__init__()
self.name = name #實例變量
self.age = age
>>>
>>> x = ClassName("yang",18)
>>> x.age #實例變量會覆蓋類變量
18
>>> y = ClassName('hello',10)
>>> y.age
10
>>> x.age = 17
>>> y.age
10
>>> ClassName.age #可以直接通過類調用類變量
100
>>> x.IQ #沒有這個屬性
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'ClassName' object has no attribute 'IQ'
>>> x.IQ = 280 #可以在類外添加新屬性(動態給實例綁定一個屬性)
>>> dir(x)
['IQ', '__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__', 'age', 'list_1', 'name']
>>> x.IQ
280
>>> hasattr(x,'IQ')
True
>>> hasattr(y,'IQ') #給x添加的實例變量不會出現在其他對象中
False
>>> ClassName.EQ = 300 #同樣可以在類外添加類變量
>>> x.EQ
300
>>> y.EQ
300
附:動態給實例綁定一個方法
from types import MethodType
class Student(object):
pass
def set_age(self,age):
self.age = age
s = Student()
s.set_age = MethodType(set_age,s) # 給實例綁定一個方法
s.set_age(18)
print(s.age)
3. 特殊方法和屬性
特殊方法前後各有兩個下劃線
構造函數 __init__()
通過類創建對象時,自動觸發執行。析構函數 __del__()
類一定有析構函數,可以自己定義,銷燬對象的時候自動執行。
>>> class Test(object):
... def __init__(self):
... print('生成了一個對象。。。')
... def __del__(self):
... print('析構函數執行了。。。')
...
>>> test = Test()
生成了一個對象。。。
>>> del test
析構函數執行了。。。
3 __doc__
類的描述信息
>>> class ClassName(object):
"""docstring for ClassName""" #__doc__就是這塊東西
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
... ... ... ... ... ...
>>> ClassName.__doc__
'docstring for ClassName'
4 __class__和__moudle__
>>> x = ClassName('yang')
>>> x.__class__ #表示當前操作的對象的類是什麼
<class '__main__.ClassName'>
>>> x.__module__ #表示當前操作的對象在哪個模塊
'__main__'
5 __call__ ()
對象後面加括號,觸發執行。使得對象可被調用。
>>> class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
def __call__(self):
print('執行了這裏.')
>>> test = ClassName('yang')
>>> test()
執行了這裏.
>>> print(callable(test))
True
6 __str__()
print(obj)的時候觸發打印這個函數的返回值
>>> class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
def __str__(self):
return '自定義打印。。' #注意,這裏是return,而不是print
>>> test = ClassName('yang')
>>> print(test)
自定義打印。。
7 __dict__
獲取類的成員(屬性和方法)或者對象的成員(只有屬性)。
class Province:
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print('func')
# 獲取類的成員,即:靜態字段、方法、
print(Province.__dict__)
# 輸出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 獲取 對象obj1 的成員
# 輸出:{'count': 10000, 'name': 'HeBei'}
obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
# 獲取 對象obj2 的成員
# 輸出:{'count': 3888, 'name': 'HeNan'}
8 __slots__(*待補充)
https://eastlakeside.gitbooks.io/interpy-zh/content/slots_magic/
http://wiki.jikexueyuan.com/project/start-learning-python/212.html
http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000
9 __len__()使得可以使用len(obj)
>>> class Student(object):
def __len__(self):
return 100
>>> a = Student()
>>> len(a)
100
4.繼承和多態
繼承
class Person(object): #object是所有類的基類
"""docstring for Person"""
def __init__(self, name,age):
self.__flag = False
self.name = name
self.age = age
class Student(Person):
"""docstring for Student"""
def __init__(self, name, age, ID):#重構的構造函數,繼承的屬性和子類新的屬性都要寫進去
super(Student, self).__init__(name,age) #新式類寫法,將繼承的屬性寫進去,這個函數相當於把父類的構造函數抄了一遍
self.ID = ID
def test(self):
print('go to school')
多繼承
一個類還可以同時繼承多個類
py2 經典類是按深度優先來繼承的,新式類是按廣度優先來繼承的
py3 經典類和新式類都是統一按廣度優先來繼承的
多態
(*僞多態)
5. 私有屬性和方法
在Python中,如果在變量名或函數名前加上‘_ _’,就會將這個變量或函數變爲私有,在類外不可訪問,對子類也不可見,子類不能繼承父類的私有屬性和方法。
但是,事實上,python不存在真正的私有,_ _xxx或者_ _xxx()
可以在類外加上_class_ _xxx來訪問。Python解釋器將私有的變量名改了一個名字來實現類外私有變量名不可見。不同解釋器的改名規則可能不一樣。
總的來說就是,Python本身沒有任何機制阻止你幹壞事,一切全靠自覺。
>>> class Person(object):
def __init__(self, name):
self.name = name
self.__age = 18
def __test(self):
print('私有方法')
>>> class Student(Person):
pass
>>> p = Person('yang')
>>> s = Student('world')
>>> print(p.name)
yang
>>> print(s.name)
world
>>> print(p.__age)
Traceback (most recent call last):
File "test.py", line 16, in <module>
print(p.__age)
AttributeError: 'Person' object has no attribute '__age'
>>> print(s.__age)
Traceback (most recent call last):
File "test.py", line 16, in <module>
print(s.__age)
AttributeError: 'Student' object has no attribute '__age'
>>> print(p._Person__age)
18
>>> print(s._Person__age)
18
>>> p.__test()
Traceback (most recent call last):
File "test.py", line 18, in <module>
p.__test()
AttributeError: 'Person' object has no attribute '__test'
>>> s.__test()
Traceback (most recent call last):
File "test.py", line 16, in <module>
s.__test()
AttributeError: 'Student' object has no attribute '__test'
>>> p._Person__test()
私有方法
>>> s._Person__test()
私有方法
6. 靜態方法、類方法、屬性方法
靜態方法
@staticmethod
普通的方法,可以在實例化後直接調用,並且在方法裏可以通過self.調用實例變量或類變量,但靜態方法是不可以訪問實例變量或類變量的(Python本質上沒有不可訪問的東西,只是不能按一般的調用類方法的方式去訪問而已),一個不能訪問實例變量和類變量的方法,其實相當於跟類本身已經沒什麼關係了,它與類唯一的關聯就是需要通過類名來調用這個方法。
靜態方法有什麼用呢?可以把一堆函數集中放在一塊,通過類名來調用,就相當於一個工具包裏面有很多的函數而已。
>>> class Dog(object):
def __init__(self,name):
self.name = name
@staticmethod #截斷跟類的關係
def test(self): #這樣寫不能以obj.test()來訪問,需要把obj當參數傳進去
print(self.name)
>>> d = Dog("taidi")
>>> d.test() #這樣會出錯
>>> d.test(d) #手動傳進來一個參數,這樣就可以了。
類方法
@classmethod
類方法通過@classmethod裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量。
class Dog(object):
n = 123
def __init__(self,name):
self.name = name
@classmethod
def test(self):
print(self.name) #訪問不了
print(self.n) #沒問題
d = Dog("taidi")
d.test() #錯誤
屬性方法
@property
屬性方法的作用就是通過@property把一個方法變成一個靜態屬性
(學習東西的時候一定要知道它的應用場景,先有需求纔會有解決相應需求的方法誕生。生活上也是如此,當你有某種需要的時候,一定會有相應的產品出現的,如果沒有,那恭喜你,你的機會來了。。)
關於@property的知識請移步這裏,這篇教程寫的非常好,從需求出發,引入@property,這樣的教程才能真正學習到一些東西。
7. 反射
getattr(object, name) #name是字符串
hasattr(obj, name)
etattr(obj, name, value)
delattr(obj, name)
class Foo(object):
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
obj = Foo()
# #### 檢查是否含有成員 ####
hasattr(obj, 'name') #返回True
hasattr(obj, 'func')
# #### 獲取成員 ####
getattr(obj, 'name') #返回的是對象的內存地址
getattr(obj, 'func')
# #### 設置成員 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
# #### 刪除成員 ####
delattr(obj, 'name')
delattr(obj, 'func')
參考鏈接:
- http://www.cnblogs.com/alex3714/articles/5188179.html
- http://www.cnblogs.com/alex3714/articles/5213184.html
- http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431864715651c99511036d884cf1b399e65ae0d27f7e000
- http://wiki.jikexueyuan.com/project/start-learning-python/212.html
- http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000