python的最最最最最基本語法(3)


模塊:在Python中,一個.py文件就稱之為一個模塊(Module)。

為了避免模塊名沖突,Python又引入了按目錄來組織模塊的方法,稱為包(Package)。例如兩個名不hello.py的模塊分別在china的包和school里的包里,然后呢,現在它們的名字分別為:china.hello與school.hello, 這樣就不沖突了吧。

每一個包目錄下面都會有一個__init__.py的文件,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄,而不是一個包。

 

自己寫一個模塊:(主要學習它的格式),創建一個hello.py的文件,內容如下:

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 
  4 'this is a hello module, i am coming '
  5 __author__='yinheyi'
  6 
  7 import sys
  8 
  9 def test():
 10         args = sys.argv
 11         if len(args) == 1:
 12                 print 'hello,world'
 13                 print '你好,世界!'
 14         elif len(args) == 2:
 15                 print 'hello,%s' % args[1]
 16         else:
 17                 print '你的參數個數不對啊,我的哥!'
 18 if __name__== '__main__':
 19         test()

第2行注釋表示.py文件本身使用標准UTF-8編碼;

第4行是一個字符串,表示模塊的文檔注釋,任何模塊代碼的第一個字符串都被視為模塊的文檔注釋;

第5行使用__author__變量把作者寫進去,這樣當你公開源代碼后別人就可以瞻仰你的大名;

注意:

if __name__=='__main__': test()

當我們在命令行運行hello模塊文件時,Python解釋器把一個特殊變量__name__置為__main__,而如果在其他地方導入該hello模塊時,則不會置為__main__, 所以我們可以直接運行這個模塊哦,用於運行測試。

 

 

 

給模塊起一個別名:

import 模塊名 as 別名

 

 

模塊內的變量與函數的作用域:

在一個模塊中,我們可能會定義很多函數和變量,但有的函數和變量我們希望給別人使用,有的函數和變量我們希望僅僅在模塊內部使用。在Python中,是通過_前綴來實現的。

正常的函數和變量名是公開的(public),可以被直接引用,比如:abcx123PI等;

類似__xxx__這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,比如上面的__author____name__就是特殊變量,hello模塊定義的文檔注釋也可以用特殊變量__doc__訪問,我們自己的變量一般不要用這種變量名;

類中,__xxx這樣的函數或變量就是非公開的(private),即有__開頭的名字;

 

模塊的搜索路經:默認情況下,Python解釋器會搜索當前目錄、所有已安裝的內置模塊和第三方模塊,搜索路徑存放在sys模塊的path變量中。

如果我們要添加搜索目錄,有兩種方法,

一是直接修改sys.path,這種方法在退出python后,會失效的。

>>> import sys
>>> sys.path.append('你自己的路經')

二是設置環境變量PYTHONPATH.可以在.bashrc里添加的,如,export PYTHONPATH = ‘目錄‘:$PYTHONPATH

 

 

使用__future__模塊:比如當我們是python2.7時,而我們想使用python3.4的python的功能時,怎么辦呢?我們可以從

__future__模塊里,導入我們想要用的功能。如除法:

#這是在python2.7中的
>>> 5/3
1
#導入新的;
>>> from __future__ import division
>>> 5/3
1.6666666666666667

 

面向對象的編程:它就是把一個對象作為基本單元,這個對象里有數據,也有對數據的操作方法啦。你看看C語言中,是不是以函數 為單元呢??這就是差別。例如一個水杯,它的元素就是水,它可以的操作有加水,倒水等。

面向對象編程的過程很簡單,首先創建一個類(其實,我認為就是一個數據類型啦,如int),然后再創建這個類的對象就可以啦。就好像你定義了一個汽車,然后,根據你的定義造出汽車的實例就可以啦。

類的定義,舉個例子:

#這是從 最根類繼承的,舊的方式定義Python類允許不從object類繼承,但這種編程方式已經嚴重不推薦使用。任何時 候,如果沒有合適的類可以繼承,就繼承自object類。 
7 class Car(object):   
  8 #定義一個含有的屬性啦;
  9         color_ = ''
 10         weight_ = 0
 11         __wheel_ = 4  #可以通過__開頭開定義私有的屬性;
 12 #定義它的方法;
 13         def __init__(self, color, weight, wheel):
 14                 self.color_ = color
 15                 self.weight_ = weight
 16                 self.__wheel_ = wheel
 17         def get_color(self):
 18                 return self.color_
 19         def get_weight(self):
 20                 return self.weight_
 21         def get_wheel(self):
 22                 return self.__wheel_
 23 
 24 baoma = Car('red',80,4)
 25 print baoma.get_color()
 26 print baoma.get_weight()
 27 print baoma.get_wheel()

輸出為:

red
80
4

總結:

類的私有屬性:
  __private_attrs  兩個下划線開頭,聲明該屬性為私有,不能在類地外部被使用或直接訪問。在類內部的方法中使用時 self.__private_attrs
類的方法
  __private_method 兩個下划線開頭,聲明該方法為私有方法,不能在類地外部調用。在類的內部調用slef.__private_methods

有些時候,你會看到以一個下划線開頭的實例變量名,比如_name,這樣的實例變量外部是可以訪問的,但是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,“雖然我可以被訪問,但是,請把我視為私有變量,不要隨意訪問”。

雙下划線開頭的實例變量是不是一定不能從外部訪問呢?其實也不是。不能直接訪問__name是因為Python解釋器對外把__name變量改成了_Student__name,所以,仍然可以通過_Student__name來訪問__name變量,但是不同版本的Python解釋器可能會把__name改成不同的變量名。

 

在類地內部,使用def關鍵字可以為類定義一個方法,與一般函數定義不同,類方法必須包含參數self,且為第一個參數私有的類方法
類的專有方法:
__init__  構造函數,在生成對象時調用
__del__   析構函數,釋放對象時使用
__repr__ 打印,轉換
__setitem__按照索引賦值
__getitem__按照索引獲取值
__len__獲得長度
__cmp__比較運算
__call__函數調用
__add__加運算
__sub__減運算
__mul__乘運算
__div__除運算
__mod__求余運算
__pow__稱方

 

類的繼承與多態:我們定義一個class的時候,可以從某個現有的class繼承,新的class稱為子類(Subclass),而被繼承的class稱為基類、父類或超類

定義一個基類:

class Animal(object):
    def run(self):
        print 'Animal is running...'

定義它的子類:

class Tiger(Animal):
    pass
class Dog(Animal):
    def run(self):
        print 'Dog is running...'

class Cat(Animal):
    def run(self):
        print 'Cat is running...'

運行:

tiger = Tiger()
tiger.run()
dog = Dog()
dog.run()
cat = Cat()
cat.run()

 

輸出:

Animal is running...

Dog is running...
Cat is running...
 
 
多態:要理解多態,你要知道上面的dog與cat的實例同時屬於Animal 與Dog 和Cat類型哦;
當我們定義一個函數時,如果傳入的數據類型為Animal的話,我們可以把Animal的實例或着繼承Anaimal的類的類型傳入這個函數中。
看一個例子:定義一個函數:
  
  
  
          
def run_twice(animal): animal.run() animal.run()
然后呢,當我們傳入Animal的實例時,run_twice()就打印出:
>>> run_twice(Animal()) Animal is running... Animal is running...

 

當我們傳入Dog的實例時,run_twice()就打印出:

>>> run_twice(Dog()) Dog is running... Dog is running...

 

當我們傳入Cat的實例時,run_twice()就打印出:

>>> run_twice(Cat()) Cat is running... Cat is running...

 

可以看出:

對於Animal的子類,不必對run_twice()做任何修改,實際上,任何依賴Animal作為參數的函數或者方法都可以不加修改地正常運行,原因就在於多態。

多態的好處就是,當我們需要傳入Dog、Cat、時,我們只需要接收Animal類型就可以了,因為Dog、Cat都是Animal類型,然后,按照Animal類型進行操作即可。由於Animal類型有run()方法,因此,傳入的任意類型,只要是Animal類或者子類,就會自動調用實際類型的run()方法,這就是多態的意思:

對於一個變量,我們只需要知道它是Animal類型,無需確切地知道它的子類型,就可以放心地調用run()方法,而具體調用的run()方法是作用在Animal、Dog、Cat對象上,由運行時該對象的確切類型決定,這就是多態真正的威力:調用方只管調用,不管細節,而當我們新增一種Animal的子類時,只要確保run()方法編寫正確,不用管原來的代碼是如何調用的。

這就是著名的“開閉”原則:

對擴展開放:允許新增Animal子類;

對修改封閉:不需要修改依賴Animal類型的run_twice()等函數。

 
 
獲取對象有信息:
判斷基本類型都可以用type()函數判斷的,如:
  
  
  
          
>>> type(132)
<type 'int'>
>>> type('lol')
<type 'str'>>>> type([1,2,3])
<type 'list'>
另外,Python把每種type類型都定義好了常量,放在types模塊里,使用之前,需要先導入,可以這這樣子:
>>> import types
>>> type('lol')==types.StringType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType
True
對於類的話,可以使用isinstance():
>>> isinstance(dog, Dog)
True

 

使用dir()函數獲取類的對象的屬性與方法。使用dir()函數,它返回一個包含字符串的list。

#看看字符串都有哪些屬性與方法
>>> dir('lol')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

如,如__len__方法返回長度。在Python中,如果你調用len()函數試圖獲取一個對象的長度,實際上,在len()函數內部,它自動去調用該對象的__len__()方法。

 

然后配合hasattr()getattr()setattr()我們可以直接操作一個對象的狀態。

hasattr():判斷是否存在某個屬性或方法;

getattr():得到是否存在某個屬性或方法;

setattr():設置是否存在某個屬性或方法;

 

python作為動態語言,有很多的靈活性。

我們可以動態的能已經定義的實例綁屬性與方法哦,也可以給一個類綁定方法的。

#給一個實例綁定屬性:
>>> class Car():
...     pass
... 
>>> bmw = Car()
>>> bmw.clor = 'red'

 

#給一個實例邦定一個方法
>>> def get_color(self):
...     return self.color
... 
>>> from types import MethodType
>>> bmw.color = MethodType(get_color, bmw, Car)
>>> bmw.color()
'red'

 

# 給一個類邦定方法
>>> def get_color(self):
...     return self.color
... 
>>> from types import MethodType
>>> Car.color = MethodType(get_color, None, Car)

 

當我們想限制動態綁定的屬性的名稱時,怎么辦呢?那就利用Class的__slots__變量。

為了達到限制的目的,Python允許在定義class的時候,定義一個特殊的__slots__變量,來限制該class能添加的屬性:

>>> class Student(object):
...     __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱

#這樣的話,我們的Student只能動態綁定 'name'與‘age'這兩個動態變量了。

另外,

使用@property裝飾器可以把定義的一個方法,變為通過屬性來調用的。

還有,很有一些特殊的變量或方法來定制類,如__len__、__str__、__iter__、__getitem__等等等 ,具體可以用到的時候具體查一下的。

 

python中的錯誤處理機制:

錯誤處理機制:try …except…finally

Python的錯誤其實也是class,所有的錯誤類型都繼承自BaseException。 在python程序中,一旦出現錯誤的話,它就要一級級的上報,直到某個函數能夠處理這個錯誤,如果最后沒有函數可以處理這個錯誤的話,最后就被python的解釋器捕獲,打印出錯誤信息,並退出程序了。

因為錯誤是一級一級的一報的,所以,不需要在每個可能出錯的地方去捕獲錯誤,只要在合適的層次去捕獲錯誤就可以了。

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 
  4 try:
  5         r = 10 /0
  6 except ZeroDivisionError, sh:
  7         print '出現錯誤了,except:',sh
  8 finally:
  9         print 'finally,錯誤機制結束'
 10 print 'end,程序結束'

輸出:

yinheyi@ubuntu:~/python$ ./2.py
出現錯誤了,except: integer division or modulo by zero
finally,錯誤機制結束
end,程序結束

 

我們也可以利用python中的log模塊記錄錯誤信息,然后分析錯誤原因。我們在except下面加入了一個記錄錯誤的語句:

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 import logging
  4 try:
  5         r = 10 /0
  6 except ZeroDivisionError, sh:
  7         print '出現錯誤了,except:',sh
  8         logging.exception(sh)
  9 finally:
 10         print 'finally,錯誤機制結束'
 11 print 'end,程序結束'

它的輸出為:

yinheyi@ubuntu:~/python$ ./2.py
出現錯誤了,except: integer division or modulo by zero
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
  File "./2.py", line 5, in <module>
    r = 10 /0
ZeroDivisionError: integer division or modulo by zero
finally,錯誤機制結束
end,程序結束

 

可以用raise拋出錯誤的,錯誤也可以自己定義的哦,具體,等着我用到了,我再補沖哈

另外,還有和程序的調試,測試啦等待,現在暫時用不着,不寫了就哈。(用於的時候學習代碼是效率最高的)

 

 

最后,如果你覺得以上內容對你有幫助,作為回報,那就可以打賞一下我這個窮學生吧,以資助我買幾本書。

錢也不用太多,您可以選擇:2毛,5毛、1元。

如果對你沒有幫助,那就算了。

 

-21_thumb

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM