Python學習目錄java
面向對象編程——Object Oriented Programming,簡稱OOP,是一種程序設計思想。OOP把對象做爲程序的基本單元,一個對象包含了數據和操做數據的函數。python
class Student(object):
pass
stone = Student()
stone.name = "stone"
stone.age = 2
print(stone.name, stone.age)
複製代碼
上面代碼中:編程
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
def print_info(self):
print(self.name, self.age)
stone = Student("stone", 18)
stone.print_info()
複製代碼
上面代碼中:api
__init__
方法的第一個參數永遠是self
,表示建立的實例自己,所以,在__init__
方法內部,就能夠把各類屬性綁定到self
,由於self
就指向建立的實例自己。相似於java的構造函數。self
外,其餘和普通函數同樣。要調用一個方法,只須要在實例變量上直接調用,除了self
不用傳遞,其餘參數正常傳入。__
開頭,就變成了一個私有變量(private),只有內部能夠訪問,外部不能訪問。__xxx__
的,也就是以雙下劃線開頭,而且以雙下劃線結尾的,是特殊變量,特殊變量是能夠直接訪問的,不是private變量。在OOP程序設計中,當咱們定義一個class的時候,能夠從某個現有的class繼承,新的class稱爲子類(Subclass),而被繼承的class稱爲基類、父類或超類(Base class、Super class)。和java同樣。網絡
靜態語言 vs 動態語言:ssh
對於靜態語言(例如Java)來講,若是須要傳入Animal
類型,則傳入的對象必須是Animal
類型或者它的子類,不然,將沒法調用Animal
中的方法。對於Python這樣的動態語言來講,則不必定須要傳入Animal
類型。咱們只須要保證傳入的對象有Animal
中的方法就能夠了。函數式編程
>>> import types
>>> def fn():
... pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
複製代碼
以上代碼能夠看出,判斷基本數據類型能夠直接寫
int
,str
等,但若是要判斷一個對象是不是函數怎麼辦?能夠使用types
模塊中定義的常量。函數
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
Tru
複製代碼
能夠判斷一個變量是不是某些類型中的一種,好比上面的代碼就能夠判斷是不是list或者tuplepost
若是要得到一個對象的全部屬性和方法,能夠使用dir()
函數,它返回一個包含字符串的list,好比,得到一個str對象的全部屬性和方法:學習
>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']
複製代碼
相似__xxx__
的屬性和方法在Python中都是有特殊用途的,好比__len__
方法返回長度。在Python中,若是你調用len()
函數試圖獲取一個對象的長度,實際上,在len()
函數內部,它自動去調用該對象的__len__()
方法,因此,下面的代碼是等價的:
>>> len('ABC')
3
>>> 'ABC'.__len__()
3
複製代碼
咱們本身寫的類,若是也想用len(myObj)
的話,就本身寫一個__len__()
方法:
>>> class MyDog(object):
... def __len__(self):
... return 100
...
>>> dog = MyDog()
>>> len(dog)
100
複製代碼
僅僅把屬性和方法列出來是不夠的,配合getattr()
、setattr()
以及hasattr()
,咱們能夠直接操做一個對象的狀態:
>>> class MyObject(object):
... def __init__(self):
... self.x = 9
... def power(self):
... return self.x * self.x
...
>>> obj = MyObject()
複製代碼
緊接着,能夠測試該對象的屬性:
>>> hasattr(obj, 'x') # 有屬性'x'嗎?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
False
>>> setattr(obj, 'y', 19) # 設置一個屬性'y'
>>> hasattr(obj, 'y') # 有屬性'y'嗎?
True
>>> getattr(obj, 'y') # 獲取屬性'y'
19
>>> obj.y # 獲取屬性'y'
19
複製代碼
也能夠得到對象的方法:
>>> hasattr(obj, 'power') # 有屬性'power'嗎?
True
>>> getattr(obj, 'power') # 獲取屬性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 獲取屬性'power'並賦值到變量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 調用fn()與調用obj.power()是同樣的
81
複製代碼
類自己須要綁定一個屬性:
class Student(object):
name = 'Student'
複製代碼
當咱們定義了一個類屬性後,這個屬性雖然歸類全部,但類的全部實例均可以訪問到。來測試一下:
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # 建立實例s
>>> print(s.name) # 打印name屬性,由於實例並無name屬性,因此會繼續查找class的name屬性
Student
>>> print(Student.name) # 打印類的name屬性
Student
>>> s.name = 'Michael' # 給實例綁定name屬性
>>> print(s.name) # 因爲實例屬性優先級比類屬性高,所以,它會屏蔽掉類的name屬性
Michael
>>> print(Student.name) # 可是類屬性並未消失,用Student.name仍然能夠訪問
Student
>>> del s.name # 若是刪除實例的name屬性
>>> print(s.name) # 再次調用s.name,因爲實例的name屬性沒有找到,類的name屬性就顯示出來了
Student
複製代碼