在Python中,一個.py文件就稱之爲一個模塊(Module)。 java
使用模塊有什麼好處? python
最大的好處是大大提升了代碼的可維護性。其次,編寫代碼沒必要從零開始。當一個模塊編寫完畢,就能夠被其餘地方引用。咱們在編寫程序的時候,也常常引用其餘模塊,包括Python內置的模塊和來自第三方的模塊。 ssh
模塊別名: 函數
try: import cStringIO as StringIO except ImportError: # 導入失敗會捕獲到ImportError import StringIO
面向對象的訪問限制: spa
在Class內部,能夠有屬性和方法,而外部代碼能夠經過直接調用實例變量的方法來操做數據,這樣,就隱藏了內部的複雜邏輯。 設計
若是要讓內部屬性不被外部訪問,能夠把屬性的名稱前加上兩個下劃線__,在Python中,實例的變量名若是以__開頭,就變成了一個私有變量(private),只有內部能夠訪問,外部不能訪問
調試
class Student(object): def __init__(self, name): self.__name = name def getName(self): return '實例變量:'+self.__name stu1 = Student('syc') print stu1.getName() # 實例變量:syc print stu1.__name # AttributeError: type object 'Student' has no attribute '__name'
有些時候,你會看到以一個下劃線開頭的實例變量名,好比_name,這樣的實例變量外部是能夠訪問的,可是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,「雖然我能夠被訪問,可是,請把我視爲私有變量,不要隨意訪問」。 code
繼承: orm
在OOP程序設計中,當咱們定義一個class的時候,能夠從某個現有的class繼承,新的class稱爲子類(Subclass),而被繼承的class稱爲基類、父類或超類(Base class、Super class)。 對象
class Animal(object): def run(self): print 'animail is running' def eat(self): print 'animail is eating' class Horse(Animal): def run(self): print 'horse is running' Animal.eat(self) # 子類中調用父類的方法 hs = Horse() hs.run() print type(hs) 結果: horse is running animail is eating <class '__main__.Horse'>
若是要得到一個對象的全部屬性和方法,可使用dir()函數:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'eat', 'run']
class Horse(object): name = 'horse' def run(self): print 'horse is running' Animal.eat(self) # 子類中調用父類的方法 hs = Horse() print hasattr(hs, 'name') # 判斷hs對象是否含有name屬性,一樣也能夠進行方法的判斷 setattr(hs, 'age', '18') # 增長的是實例變量,不能爲對象設置新的方法 print getattr(hs, 'age') # 獲得hs的age值,同時能夠獲得方法的變量
使用__slots__
正常狀況下,當咱們定義了一個class,建立了一個class的實例後,咱們能夠給該實例綁定任何屬性和方法,這就是動態語言的靈活性
class Student(object): name = 'syc' def drink(self): print 'student is drunking' stu = Student() stu.age = 18 #給實例增長屬性 print stu.age Student.age =19 # 給類添加屬性 print Student.age def eat(self): print 'student is eating' from types import MethodType stu.eat = MethodType(eat, stu, Student) # 給Student的實例stu添加方法 stu.eat() stu2 = Student() # print stu2.eat() # AttributeError: 'Student' object has no attribute 'eat' Student.eat = MethodType(eat, None, Student) # 給類Student添加方法 stu2.eat()
class Student(object): __slots__ = ('name', 'age', 'eat') name = 'syc' def drink(self): print 'student is drunking' stu = Student() stu.address = 'fuzhou' 結果:AttributeError: 'Student' object has no attribute 'address'
方法也是一樣的;
使用__slots__要注意,__slots__定義的屬性僅對當前類起做用,對繼承的子類是不起做用的
class Student(object): __slots__ = ('name', 'age', 'eat') name = 'syc' def drink(self): print 'student is drunking' class SubStudent(Student): pass substu = SubStudent() substu.address = 'fuzhou' print substu.address # fuzhou
使用@property
@property普遍應用在類的定義中,可讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,這樣,程序運行時就減小了出錯的可能性。
class Student(object): @property def aname(self): # 第一處 return self.__name @aname.setter # 第二處 def name(self, name): # 第三處 # if name == 'syc': # raise TypeError('name不能爲syc') self.__name = name stu = Student() stu.name = 'syc' # 第四處 print stu.name # 第五處
新增的屬性爲name,不是__name
多重繼承:
Mixin:在設計類的繼承關係時,一般,主線都是單一繼承下來的,若是須要「混入」額外的功能,經過多重繼承就能夠實現,這種設計一般稱之爲Mixin;python中的多重繼承相似於java中的類組合;
在多重繼承中,最大的問題就是當繼承的父類中有同名的方法,這時的優先級問題:
class Grandfa(object): def hair(self): print 'no hair' class Father(Grandfa): pass class Mom(object): def hair(self): print 'hair' class Tom(Father,Mom): pass tom = Tom() tom.hair() # no hair 深度優先
定製類:
經過特殊變量,能夠爲咱們定製類,如:__slots__,__len__,__str__等
__str__:
class Student(object): pass # def __str__(self): # return 'a student instance' stu = Student() print stu # <__main__.Student object at 0x02634B90> class Student(object): # pass def __str__(self): return 'a student instance' stu = Student() print stu # a student instance
__iter__:
判斷對象是否能夠進行迭代:
class Student(object): pass from collections import Iterable print isinstance(stu,Iterable) # False
若是須要使對象可以迭代,能夠在類中定義__iter__方法:
class Student(object): def __iter__(self): return self def next(self): self.a, self.b = self.b, self.a + self.b if self.b >100: raise StopIteration() return self.b stu = Student() from collections import Iterable print isinstance(stu,Iterable) # True stu.a, stu.b = 1,2 print [x for x in stu] # [3, 5, 8, 13, 21, 34, 55, 89]
Python的for循環就會不斷調用該迭代對象的next()方法拿到循環的下一個值,直到遇到StopIteration錯誤時退出循環。
__getitem__
雖然能做用於for循環
class Student(object): def __getitem__(self, n): for x in range(n): self.a, self.b = self.b, self.a + self.b return self.b stu = Student() from collections import Iterable print isinstance(stu,Iterable) # False stu.a, stu.b = 1,2 print stu[1] # [3, 5, 8, 13, 21, 34, 55, 89]
__getattr__
經過__getattr__動態的定義類的屬性和方法;
class Student(object): def __init__(self, name): self.name = name def __getattr__(self, item): if item == 'score': # 自動添加屬性 return 99 if item =='getSocre': # 自動添加方法 return lambda :self.score * self.score stu = Student('syc') print stu.socre # None ==>當類定義了__getattr__時,即便沒有定義socre,也不會報錯:AttributeError: 'Student' object has no attribute 'socre' print stu.score # 99 print stu.getSocre() # 9801
class Student(object): def __init__(self, path=''): self.__path = path def __getattr__(self, item): if item == "users": return lambda user: Student("%s/users/:%s" % (self.__path, user)) else: return Student("%s/%s" % (self.__path, item)) def __str__(self): return self.__path print Student().users('syc').repos # /users/:syc/repos
或者:
class Student(object): def __init__(self, path=''): self.__path = path def __getattr__(self, item): return Student("%s/%s" % (self.__path, item)) def __str__(self): return self.__path def __call__(self, name): return Student("%s/:%s" % (self.__path, name)) print Student().users('syc').repos # /users/:syc/repos
一個對象實例能夠有本身的屬性和方法,
當咱們調用實例方法時,咱們用instance.method()來調用。能不能直接在實例自己上調用呢?相似instance()?在Python中,答案是確定的。
任何類,只須要定義一個__call__()方法,就能夠直接對實例進行調用。請看示例:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) s = Student('syc') s() # My name is syc.
那麼,怎麼判斷一個變量是對象仍是函數呢?其實,更多的時候,咱們須要判斷一個對象是否能被調用,能被調用的對象就是一個Callable對象,好比函數和咱們上面定義的帶有__call()__的類實例:
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) s = Student('syc') print callable(s) # True print callable([1, 2, 3]) # False print callable('ABC') # False print callable(None) # False
使用元類:
建立類有兩種方法:自定義:class XXX,type(ClassName, parentClass, dict{fun,property})
def fn(self, name): print 'Hello %s'% name Hello = type('Hello', (object,), dict(hello=fn)) Hello().hello('world') # Hello world
要建立一個class對象,type()函數依次傳入3個參數: