本文主要針對python的package、面向對象編程等進行詳述。
1.Python模塊
在Python中,一個.py文件就稱之爲一個模塊(Module),不同的文件目錄稱爲包(Package),每一個包目錄下面都會有一個__init__.py的文件,這個文件是必須存在的,否則,Python就把這個目錄當成普通目錄,而不是一個包。
與java相同,python也有public/private等屬性和方法,在一個模塊中(Module),是通過"_"前綴來實現的,正常的函數和變量名是公開的(public),可以被直接引用,比如:abc,x123,PI等;類似“__xxx__”這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,比如上面的“__author__”,“__name__”就是特殊變量,hello模塊定義的文檔註釋也可以用特殊變量“__doc__”訪問,我們自己的變量一般不要用這種變量名;類似_xxx和__xxx這樣的函數或變量就是非公開的(private),不應該被直接引用,比如_abc,__abc等;
Python module的規範格式
#!/usr/bin/env python3
# 第一行註釋可以讓這個hello.py文件直接在Unix/Linux/Mac上運行
# -*- coding: utf-8 -*-
# 第2行註釋表示.py文件本身使用標準UTF-8編碼
' a test module '
# 一個字符串,表示模塊的文檔註釋,任何模塊代碼的第一個字符串都被視爲模塊的文檔註釋;
__author__ = 'Michael Liao' # 變量把作者寫進去,這樣當你公開源代碼後別人就可以瞻仰你的大名
import sys
def test():
args = sys.argv #類似於java main函數中的main(String[] args)中的args
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
test()
# 當我們在命令行運行hello模塊文件時,Python解釋器把一個特殊變量__name__置爲__main__,而如果在其他地方導入該hello模塊時,if判斷將失敗,因此,這種if測試可以讓一個模塊通過命令行運行時執行一些額外的代碼,最常見的就是運行測試。
2.面向對象編程
class Student(object):
def __init__(self, name, score): # 注意到__init__方法的第一個參數永遠是self,表示創建的實例本身
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
bart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)
bart.print_score()
lisa.print_score()
輸出結果:
Bart Simpson: 59
Lisa Simpson: 87
3.繼承和多態
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running...')
def eat(self):
print('Eating meat...')
class Cat(Animal):
def run(self):
print('Cat is running...')
print("繼承")
dog = Dog()
dog.run()
cat = Cat()
cat.run()
print("多態")
def run_animal(animal):
animal.run()
run_animal(Animal())
run_animal(Dog())
run_animal(Cat())
輸出結果:
繼承
Dog is running...
Cat is running...
多態
Animal is running...
Dog is running...
Cat is running...
對於靜態語言(例如Java)來說,如果需要傳入Animal類型,則傳入的對象必須是Animal類型或者它的子類,否則,將無法調用run()方法。對於Python這樣的動態語言來說,則不一定需要傳入Animal類型。我們只需要保證傳入的對象有一個run()方法就可以了。
class Timer(object):
def run(self):
print('time run...')
run_animal(Timer())
輸出結果:
time run...
4.獲取對象信息
1.type(),判斷對象類型,type("abc"),type(123)a = Animal()
isinstance(a, Animal)
print("#獲取對象的方法")
print(dir(dog))
#獲取對象的方法
['__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__', 'eat', 'run']
5.Python的類屬性(類似於java類的static屬性)
class Student(object):
name = 'Student'
6.類的屬性和方法的綁定
from types import MethodType
class Student(object):
pass
s = Student()
s.name = 'Michael' # 動態給實例綁定一個屬性
print(s.name)
def set_age(self, age): # 定義一個函數作爲實例方法
self.age = age
s.set_age = MethodType(set_age, s) # 給實例綁定一個方法
s.set_age(25) # 調用實例方法
print(s.age) # 測試結果
# 給一個實例綁定的方法,對另一個實例是不起作用的
# 爲了給所有實例都綁定方法,可以給class綁定方法
def set_score(self, score):
self.score = score
Student.set_score = set_score
s.set_score(100)
print(s.score)
7.__slots__限制類的屬性
class Student(object):
__slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱
s = Student() # 創建新的實例
s.name = 'Michael' # 綁定屬性'name'
s.age = 25 # 綁定屬性'age'
s.score = 99 # 綁定屬性'score'
輸出結果:
Traceback (most recent call last):
line 7, in <module>
s.score = 99 # 綁定屬性'score'
AttributeError: 'Student' object has no attribute 'score'