面向對象編程中最重要的一個概念也就是類和對象排截。所以下面來介紹一下類的相關內容
類和對象
類是抽象的模板,比如我們抽象一個學生類,很容易想到學生固有的一些屬性凭涂,比如名字祝辣,年齡等等,創(chuàng)建一個學生類:
class Student(object):
pass
這里的object是表明Student類是從哪個類繼承來的,在python中object是所有類的父類(繼承的概念下文會提及)
創(chuàng)建實例對象tom:
tom = Student()
//我們可以自由地給類綁定屬性:
tom.name = 'XiaoMing'
tom.age = 23
那么既然類具有模板的作用切油,所以我們可以把一些屬性強行綁定給類
class NewStudent(object):
def init(self,name,age):
self.name = name
self.age = age
這里需要注意一點__init__方法的第一個參數(shù)永遠是self蝙斜,表示創(chuàng)建的實例本身,因此澎胡,在__init__方法內部可以把各種屬性綁定到self孕荠。有了__init__方法,在創(chuàng)建實例的時候就不能傳入空的參數(shù)了滤馍,必須傳入與__init__方法匹配的參數(shù)岛琼,但是self不需要傳,python解釋器會自己把實例變量傳進去巢株。
我們可以給類添加打印學生信息的方法槐瑞,把邏輯放在類內部,外部只需要調用即可:
class NewStudent(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def printInfo(self):
print('name:%s,age:%s'%(self.__name,self.__age))
john = NewStudent('JOHN',32)
//類外部調用:
john.printInfo()
訪問限制
在上面的代碼中阁苞,我們雖然把屬性方法寫在了類的內部困檩,實際上渔肩,我們從外面還是能夠對他進行修改的八孝,python中在屬性的名字前面加雙下劃線就使屬性變成了私有,外部不能訪問也不可更改牺荠。
class NewStudent(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
如果我們有想要獲取想要更改怎么辦呢骚灸?可以通過get set方法:
class NewStudent(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def printInfo(self):
print('name:%s,age:%s'%(self.__name,self.__age))
def get_name(self):
return self.__name
def get_age(self):
return self.__age
def set_name(self,name):
self.__name = name
def set_age(self,age):
self.__age = age
john.set_name('HAHA')
john.set_age(10)
print(john.get_name())
print(john.get_age())
至于為什么這么折騰呢糟趾?寫成私有變量的好處就是我允許外部訪問或修改,但是我內部是有判斷的甚牲。
繼承和多態(tài)
在OOP程序設計中义郑,我們定義一個類的時候,可以從現(xiàn)有的類繼承丈钙;新的類就稱為子類非驮,而被繼承的類就是父類,基類或超類雏赦。
class Animal(object):
def run(self):
print('Animal is running...')
def eat(self):
print('Animal is eating...')
class Dog(Animal):
pass
class Cat(Animal):
pass
上面的三個類劫笙,Animal就是Dog和Cat的父類,那么繼承有什么好處呢星岗?
dog = Dog()
cat = Cat()
dog.run()
cat.run()
//Animal is running...
//Animal is running...
從上面的代碼可以看出填大,子類繼承了父類的全部方法(功能);
當然子類也可以擁有自己的方法:
class Animal(object):
def run(self):
print('Animal is running...')
def eat(self):
print('Animal is eating...')
class Dog(Animal):
def run(self):
print('Dog is running...')
def bark(self):
print('Dog is barking...')
class Cat(Animal):
def run(self):
print('Cat is running...')
def jump(self):
print('Cat is jumping...')
dog = Dog()
cat = Cat()
dog.run()
dog.eat()
dog.bark()
cat.run()
cat.eat()
cat.jump()
繼承還有一個好處就是,子類可以對父類的方法進行重寫俏橘,當子類和父類都有同樣的方法時栋盹,子類會覆蓋父類的方法,這就是繼承的另一個好處:多態(tài)。
多態(tài)其實講了一個現(xiàn)實生活很常見的現(xiàn)象例获,那就是狗是動物汉额,貓也是動物,但是動物不是狗榨汤,動物也不是貓蠕搜;繼承導致了Dog和Cat類有了兩種類型,這是一個很重要的功能
比如我們定義一個方法:
def run_twice(animal):
animal.run()
animal.run()
run_twice(Animal())
當我們傳入Animal實例就會執(zhí)行兩次run方法
run_twice(Dog())
run_twice(Cat())
當我們傳入子類對象的時候,子類對象也會執(zhí)行兩次類方法
獲取對象信息
當我們拿到一個對象的引用收壕,如何知道這個對象是什么類型有什么方法妓灌?
使用type()
print(type(123) == int)
print(type('123') == str)
判斷基本類型可以直接寫int,str蜜宪,但是如果要判斷對象是不是函數(shù)呢虫埂?
import types
def function():
pass
print(type(function) == types.FunctionType)
print(type(lambda x: x*x) == types.LambdaType)
print(type((x for x in range(10)))==types.GeneratorType)
print(type(abs)==types.BuiltinFunctionType)
使用isinstance()
a = Animal()
d = Dog()
c = Cat()
print(isinstance(a,Animal))
print(isinstance(d,Animal))
print(isinstance(d,Dog))
使用dir()
dir()返回一個包含字符串的list
dir('123')
//可以獲取str對象的所有屬性和方法
類似XXX的屬性和方法在python中都是有特殊用途的,比如len方法返回長度圃验。在Python中掉伏,如果你調用len()函數(shù)試圖獲取一個對象的長度,實際上澳窑,在len()函數(shù)內部斧散,它自動去調用該對象的len()方法,所以摊聋,下面的代碼是等價的:
len('123')
'123'.__len__()
//運行結果:
//3
淡然僅僅把屬性和方法列出來是不夠的鸡捐,還有配合getattr()、setattr()以及hasattr()麻裁,我們就可以直接操作一個對象的狀態(tài)箍镜。
最后
面向對象其實有很多知識點可以寫,我只是做一個摘要而已煎源,希望自己能堅持下去吧~