面向對象,類的屬性和 類的方法
面向對象
- 類和對象
- Python類定義
- 類屬性
- 類方法
面向過程和面向對象
面向過程 和 面向對象 編程
- 面向過程 編程:函數式編程,C程序,shell等
- 面向對象 編程:C++ ,Java,Python
類和對象
類和對象:是面向對象中的兩個重要概念
1.類: 是對事物的抽象,比如:人類,球類
2.對象:是類的一個實例,比如:足球,籃球
實例說明:
球類可以對球的特征和行為進行抽象,然后可以實例化一個真實的球實體出來
靜態屬性,動態方法
為什么面向對象
面向對象的主要思想是:
- 封裝
- 繼承
- 多態
這種思想方便解決較為復雜的項目,且維護起來較為容易
類的定義
類定義:
類把需要的變量和函數組合成一起,這樣包含稱為"封裝"
class A(object):
類的結構:
class 類名:
成員變量 - 屬性
成員函數 - 方法
class MyClass(object): def fun(self): print "i am function"
類的方法中至少有一個參數 self
#!/usr/bin/python class People(object): # 定義類(class),object可以有,也可以沒有 color = 'yellow' #定義了一個靜態屬性,成員變量 def think(self): #定義了一個動態方法,這個方法里一定要有self,還可以帶多個屬性,成員函數 self.color = "black" #如果需要調用類里的屬性,就要用到self.color來調用該靜態屬性 print "I am a %s" % self.color #調用動態方法時的輸出 print "i am a thinker" ren = People() #將類賦值給'ren'這個變量,就是一個對象,即為將類實例化 print ren # 單純打印這個'ren'變量是一個對象(object),所以將類實例化后的便是對象(object) print ren.color #輸出,'ren'對象的靜態屬性, ren.think() #使用這個類里面的.think()方法
輸出結果:
[root@hc python]# python class.py <__main__.People object at 0x7f646d144690> #打印這個方法的信息 yellow #靜態屬性的輸出結果 I am a black #這里輸出的是 ren.think() i am a thinker
對象的創建
創建對象的過程稱之為實例化;
當一個對象被創建后,包含三個方面的特性
- 對象句柄
- 屬性
- 方法
句柄用於 區分不同的對象
對象的屬性和方法與類中的成員變量和成員函數對應
obj = MyClass()
# 創建類的一個實例(對象)通過對象來調用方法和屬性
類的屬性
類的屬性按使用范圍分為公有屬性和私有屬性,類的屬性范圍取決於屬性的名稱
公有屬性:
在類中和類外都能調用的屬性
私有屬性:
不能再類外以及被類以外的函數調用
定義方式:
以"__"雙下划線開始的成員變量就是私有屬性
可以通過instance._classname__attribute
方式訪問
內置屬性:由系統在定義類的時候默認添加的,由前后雙下划線構成,__dict__ , __module__
#!/usr/bin/python #coding:utf8 class People(object): color = 'yellow' __age = 30 #前面加兩個__ 為私有屬性,只能內部使用 def think(self): self.color = "black" print "I am a %s" % self.color print "i am a thinker" print self.__age #調用私有屬性 ren = People() #將類實體化 ren.color = 'aaa' #對象內的color屬性重新賦值 print ren.color #輸出這個對象被新賦值的屬性 print People.color() #調用類里的屬性,是原來的值,是因為類實體化之前之后是不同的個體 print '-' *50 ren.think() #調用對象里的方法 print '-' *50 print ren.__dict__ #通過對象調用公有的屬性,保存到字典里輸出 print People.__dict__ #通過類調用內置屬性,公私有屬性全部保存到字典輸出 print '-' *50 print ren._People__age #以這種方法查看對象里的私有屬性,測試用
輸出結果:
[root@hc python]# python class1.py # ren = People() # ren.color = 'aaa' # print ren.color # print People.color() aaa yellow -------------------------------------------------- # ren.think() I am a black i am a thinker 30 #這是私有屬性 -------------------------------------------------- # print ren.__dict__ {'color': 'black'} # print People.__dict__ {'__module__': '__main__', 'color': 'yellow', '__doc__': None, '__dict__': <attribute '__dict__' of 'People' objects>, '_People__age': 30, '__weakref__': <attribute '__weakref__' of 'People' objects>, 'think': <function think at 0x7fe443e265f0>} -------------------------------------------------- # print ren._People__age 30
類的方法
- 方法的定義和函數一樣,但是需要self 作為第一個參數
- 類方法:
公有方法
私有方法
類方法
靜態方法
公有方法:在類中和類外都能調用的方法
私有方法:不能被類的外部調用,在方法前面加上"__"雙下划線就是私有方法
self 參數
用於區分函數和類的方法(必須有一個self),self參數表示執行對象本身
方法和函數的區別是:在括號內有沒有self,有self就是方法,沒有就是函數
self
代表類的本事
通過類調用!
類的方法 (能被類直接調用的叫做類方法)
類方法:
被classmethod()
函數處理過的函數,能被類所調用,也能被對象所調用(是繼承的關系)
classmethod
修飾符對應的函數不需要實例化,不需要 self 參數,但第一個參數需要是表示自身類的 cls 參數,可以來調用類的屬性,類的方法,實例化對象等。
靜態方法:
相當於"全局函數",可以被類直接調 用,可以被所有實例化對象共享,通過staticmethod()
定義,
靜態方法沒有self參數。
裝飾器:
@classmethod # 指定一個類的方法為類方法,通過這個函數classmethod,(單獨寫需要一個變量來接受值) #動態方法占用資源比較少,用到了才會加載,但是訪問速度比較慢 @staticmethod #只針對它下面的函數生效,它是將函數轉為類的靜態方法,靜態方法比較占用資源,但是訪問速度快 #靜態方法無需實例化,但也可以也可以實例化后調用
使用例子
#!/usr/bin/python #coding:utf8 class People(object): color = 'yellow' __age = 30 def think(self): self.color = "black" print "I am a %s" % self.color print "i am a thinker" print self.__age def __aaa(self): # 私有方法,只能內部調用 print "使用私有方法 " def axx(self): #需要使用到一個類的方法內部調用才可以訪問到內部的私有方法 self.__aaa() @classmethod #類方法 def test(x): #修飾符對應的函數不需要實例化,不需要self參數,但第一個參數需要是表示自身類的x參數,可以來調用類的屬性,類的方法,實例化對象等。 print x.color print "動態方法" @staticmethod #靜態方法無需實例化,但也可以也可以實例化后調用 def test1(): print "靜態方法" print "通過實體化后的類訪問" abc = People() abc.test() abc.test1() print "---------------------" print "通過類訪問的" People.test() People.test1() print "---------------------" abc.axx()
類的內置方法 和 繼承
python 內部類
所謂內部類,就是再類的內部定義的類,主要目的是為了更好的抽象實現世界
例子:
汽車是個類,汽車的底盤,輪胎也可以抽象為類,將其定義到汽車類中,則形成內部類,更好的描述汽車類,因為底盤,輪胎是汽車的一部分
內部類的實例化方法
方法1:直接使用外部類調用內部類object_name = outclass_name.inclass_name()
方法2:先對外部類進行實例化,然后再實例化內部類
out_name = outclass_name()
in_name = out_name.inclass_name()
in_name,method()
方法3:公有屬性,直接可以通過類直接調用
魔術方法
類的內置方法或者叫做魔術方法
__str__(self)
將輸出對象更友好的輸出
構造函數與析構函數
構造函數:
用於初始化類的內部狀態,Python提供的構造函數是__init__()
;__init__()
方法是可選的,如果不提供,Python會給出一個默認的__init__
方法
析構函數:
用於釋放對象占用的資源,Python提供的析構函數是 __del__()
;__del__()
也是可選的。如果不提供,則Python 會在后台提供默認析構函數
垃圾回收機制
1.Python 采用垃圾回收機制來清理不再使用的對象;Python提供gc模塊釋放不再使用的對象。
2.Python采用"引用計數"的算法方式來處理回收
即:當某個對象在其作用域內不再被其他對象引用的時候,Python就自動清除對象;
3.gc模塊的collect()
可以一次性收集所有待處理的對象 print gc.collect()
如果是0則為回收
類的繼承
- 繼承是面向對象的重要特性之一;
- 繼承關系:繼承是相對兩個雷而言的父子關系,子類繼承了父類的所有公有屬性和方法
- 繼承實現了代碼重用
使用繼承
繼承可以重用已經存在的數據和行為,減少代碼的重復編寫,Python在類名后使用一對括號來表示繼承關系,括號中的類即為父類。
class Myclass(ParentClass)
class Myclass繼承了ParentClass類
如果父類定義了__init__
方法,子類必須顯示調用父類的__init__
方法:ParentClass.__init__(self,[args...])
如果子類需要擴展父類的行為,可以添加__init__
方法的參數
簡單的繼承:
#!/usr/bin/python #-*- coding:utf-8 -*- class People(object): #New Style 傳統方式不加() color = 'yellow' def __init__(self, c): #父類的構造函數,如果self后跟了一個變量,則在繼承的子類時需要重寫這個構造函數然后引入這個值 print "Init..." self.dwell = 'Earth' #這是它的初始化變量 def think(self): print "I am a %s" % self.color print "I am a thinker " class Chinese(People): #Chinese繼承了People父類 def __init__(self): #則在繼承的子類時需要重寫這個構造函數然后引入這個值 #People.__init__(self,'red') #第一種方法可以使用傳統的方式 ,super 是第二種方法,不支持傳統格式的類 super(Chinese, self).__init__('red') #使用super函數來繼承父類,父類必須是NewStyle,不然會報錯 pass cn = Chinese() #實例化調用這個類 print cn.color #輸出里面定義的變量 cn.think() #還能通過繼承的類,訪問它內部的函數 print cn.dwell #也是會執行內部初始化的變量
super 函數 來繼承父類
class Chinese(People):
Chinese繼承了People父類
`def __init__(self): `
則在繼承的子類時需要重寫這個構造函數然后引入這個值super(Chinese, self).__init__('red')
#使用super函數來繼承父類,pass
Help on class super in module __builtin__: class super(object) | super(type, obj) -> bound super object; requires isinstance(obj, type) | super(type) -> unbound super object | super(type, type2) -> bound super object; requires issubclass(type2, type) | Typical use to call a cooperative superclass method: | class C(B): | def meth(self, arg): | super(C, self).meth(arg)
People.__init__(self,'red')
第一種方法可以使用傳統的方式 ,super 是第二種方法,不支持傳統格式的類
super(Chinese, self).__init__('red')
使用super函數來繼承父類,父類必須是NewStyle,不然會報錯
繼承2
多重繼承
Python 支持多重繼承,即一個類可以繼承多個父類
語法class class_name(Parent_c1,Parent_c2,...)
注意:
當父類中出現多個自定義的__init__
方法時,
多重繼承只執行第一個類的__init__
方法
其他不執行
類屬性,方法 總結
類的屬性-總結
-
類屬性,也是共有屬性
-
類的私有屬性
-
對象的共有屬性
-
對象的私有屬性
-
內置函數
-
函數的局部變量
-
全局變量
#!/usr/bin/python #coding:utf8 var5 = '全局變量' class MyClass(object): var1 = '類屬性,類的公有屬性 var1' __var2 = '類的私有屬性 __var2' def func1(self): self.var3 = '對象的公有屬性 var3' self.__var4 = '對象的私有屬性 __var4' var5 = '函數的局部變量 var5' print self.__var4 print var5 def func2(self): print self.var1 print self.__var2 print self.var3 #需要先調用方法,才能被調用 print self.__var4 print var5 #全局變量! return '這是函數的返回值,沒有return就會出現None' mc = MyClass() mc.func1() print '---------' print mc.func2() print '---------' --------------------------------------------- mc = MyClass() #實例化類 print mc.var1 #私有屬性都不能訪問 mc.func1() #先調用方法 才能調用內部的公有屬性 print mc.func1() mc1 = MyClass() print mc1.var3 #沒調用內部的方法,所以不能調用 ---------------------------------------------- #通過類 ,對象的屬性只能通過對象訪問, print MyClass.var1 #訪問類的公有屬性 可以 print MyClass.var2 #訪問類的私有屬性 不可以 mc = MyClass() mc.fun1 mc.fun2 print '-' * 50 print mc.__dict__ #返回一個字典,里面包含的是'類的內置屬性' print '-' * 50 print MyClass.__dict__ #通過類來調用'內置屬性',返回一個字典,里面包含的類來調用'內置屬性'
類方法總結
-
公有方法
-
私有方法
-
類方法
-
靜態方法
-
內置方法
#!/usr/bin/python #coding:utf8 class MyClass(object): name = 'Test' def __init__(self): #如果加了內部的構造函數,即當前的類別實例化會, self.func1() #會自動加載,並初始化里面的內容 self.__func2() self.classFun() #類方法,靜態方法 這兩種都可以通過對象來調用 self.staticFun() def func1(self): print self.name, print "我是公有方法" # self.__func2() def __func2(self): print self.name, print "我是私有方法" @classmethod #修飾器,這樣就將類里的方法,轉為類方法然后外部調用 def classFun(self): print self.name, print "我是類方法" @staticmethod #修飾器 def staticFun(): #靜態方法不能有 self 方法 print MyClass.name, #因為是靜態的,需要類名來調用 print "我是靜態方法" mc = MyClass() #實例化 mc.func1() mc.__fun2() #直接調用不行。必須在內部調用,在func1里面調用才可以 ------------------------------------------------------------------------------------ MyClass.classFun() #類方法,需要加修飾器才可以再外部調用 MyClass.staticFun() #靜態方法,需要加修飾器才可以再外部調用 #類方法,靜態方法 這兩種都可以通過對象來調用
rc腳本(類的定義與腳本的結構)
#!/usr/bin/python import sys import os from subprocess import Popen, PIPE #調用系統bash 啟動,stdout的標准輸出通過這個PIPE管道符傳入一個臨時文件里 class Process(object): '''memcached rc script''' #注釋 def __init__(self, name, program, args, workdir): #類實例化的時候,初始化傳遞的參數 self.name = name self.program = program #初始化屬性 self.args = args self.workdir = workdir def _init(self): #這里是一個下划線,是一個普通的方法 '''/var/tmp/memcached''' if not os.path.exists(self.workdir): # 判斷目標不存在,則創建,進入該目錄 os.mkdir(self.workdir) # mkdir 創建目錄 os.chdir(self.workdir) # chdir 進入該目錄 def _pidFile(self): '''/var/tmp/memcached/memcached.pid''' return os.path.join(self.workdir, "%s.pid" % self.name) #將目錄連接到一起,然后返回這個結果 def _writhPid(self): if selp.pid: #判斷這個pid 是否有值,有值則寫入文件 with open(self._pidFile(),'w') as fd: fd.write(str(self.pid)) def start(self): #類里的方法 self._init() #這個方法判斷這個目錄在不在,不在就創建。 cmd = self.program + ' ' + self.args #啟動腳本的路徑 + ' ' + 啟動選項參數 p = Popen(cmd, stdout=PIPE, shell=True) # 這條是執行命令,stdout=PIPE:是將標准輸出傳給管道,傳給一個臨時文件里 self.pid = p.pid #用了Popen里的一個pid方法輸出PID self._wirthPid() #調用方法寫PID 這個值 print "%s start Sucessful" % self.name def _getPid(self): p = Popen(['pidof',self.name],stdout=PEPI) pid = p.stdout.read().strip() # strip() 去除收尾的空格,換行等。可以執行去掉的字符,需要在括號內寫 return pid def stop(self): self._getPid() if pid: #判斷這個不為空則執行 os.kill(int(pid),15) #調用系統命令 kill 進程,用kill -15 相當正常退出,kill()里面需要兩個參數,一個是PID和等級 if os.path.exists(self._pidFile()): os.remove(self._pifFile()) print " %s is stop" % self.name def restart(self): self.stop() self.start() def status(self): pid = self._getPid() if pid: print "%s is runing" % self.name elif pid: print "%s in stopped" % self.name def help(self): print "Usage: %s {start|stop|status|restart}" % __file__ # __file__ 打印這個內置屬性,則是該文件名 def main(): #一個主體函數 name = 'memcached' #程序名 prog = '/usr/bin/memcached' #程序的啟動腳本的路徑 args = '-u nobody -p 11211 -c 1024 -m 64' #啟動時帶的參數 wd = '/var/tmp/memcached' #程序所在的路徑 pm = Process(name = name, #上面的參數 傳入類的屬性里去 program = prog, args = args, workdir = wd) try: #處理輸入的異常 cmd = sys.argv[1] #取輸入腳本的第一個值 比如,start,stop等等。。 except IndexError, e: #except 異常的捕捉 print "Option error" sys.exit() if cmd == 'start': #判斷輸入的類型 pm.start() # 實例化后的類 進行調用內部的方法 elif cmd == 'stop': pm.stop() elif cmd == 'restart': pm.restart() elif cmd == 'status': pm.status() else: pm.help() if __name__ == '__main__': #調用使用 main() 函數,print(__name__) 打印的輸出就等於__main__ main() #這里等同於啟動python程序的意思
Linux kill 命令
9和15 的區別,最好還是用15,這樣相當於正常退出
SIGNKILL(9) 的效果是立即殺死進程. 該信號不能被阻塞, 處理和忽略。
SIGNTERM(15) 的效果是正常退出進程,退出前可以被阻塞或回調處理。並且它是Linux缺省的程序中斷信號。
linux 命令
echo $$ #當前PID的bash 進程
tty #顯示當前終端號
pidof #取一個進程的PID
關於 get pid 的問題
from subprocess import Popen, PIPE #先加載模塊
p = Popen(['pidof','memcached'], stdout=PIPE) #將Popen 實例化 給p
p.pid #p調用pid方法 ,這個PID 是 pidof命令的進程的PID
28675
pid = p.stdout.read() #這個PID才是我memcached的進程PID
pid
'28001\n'
pid.strip() #用strip() 字符串方法 去掉 特殊字符
'28001'