python類與物件
python類與物件
python通過類來建立物件,物件是類的例項。
1.類的定義
類通過class + 類名的方式定義
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
類名的首字母一般用大寫,類中的函式稱為方法。
2.Class物件
類的物件支援兩種操作:屬性引用和例項化
(1)屬性引用
如上述程式碼通過Myclass.i或Myclass.f即可返回一個整數和一個函式,並且可以通過複製Myclass.i來改變他的值。
print(MyClass.i) MyClass.i = 10 print(MyClass.i) print(type(MyClass.f) #12345 #10 #<class 'function'>)
(2)例項化
x = Myclass()
這裡的x便是類的例項。
3.__init__方法
這是一個特殊的方法,當例項化類時會自動呼叫該方法。
許多類喜歡建立帶有特定初始狀態的自定義例項。 為此類定義可能包含這個方法,就像這樣:
class Jump:
def __init__(self,name):
self.name = name
def jump(self):
print(f'{self.name} is jumping now!')
a = Jump("小a")
a.jump()
#小a is jumping now!
當建立一個例項時這個方法自動使self.name賦值為"小a"。
如果沒有這個方法,那上面的例子就應當這麼寫:
class Jump:
def name(self,name):
self.name=name
def jump(self):
print(f'{self.name} is jumping now!')
a = Jump()
a.name("小a")
a.jump()
#小a is jumping now!
我們還要再呼叫一次name的方法。
4.例項物件
例項物件能理解的唯一操作是屬性引用,有兩種有效的屬性名稱:資料引用和方法
(1)資料引用
例項可以引用類中的資料
class MyClass: i = 12345 def f(self): return 'hello world' a = MyClass() print(a.i) #12345
但是運用例項改變所引用的資料時,類原本的資料不會改變
a.i = 10
print(MyClass.i)
#12345
(2)方法
例項可以引用類中的方法
通常方法物件在繫結後直接被呼叫,但是也直接呼叫也不是必須的,我們可以將其保留起來。
class MyClass:
i = 12345
def f(self):
return 'hello world'
xf = x.f
while True:
print(xf())
將會一直輸出,直到結束。
我們會發現這裡上面呼叫 x.f()
時並沒有帶引數,雖然 f()
的函式定義指定了一個引數。實際上,方法的特殊之處就在於例項物件會作為函式的第一個引數被傳入。
5.self
就像上面所說,類的方法與普通的函式只有一個特別的區別 —— 它們必須有一個額外的第一個引數名稱(對應於該例項,即該物件本身),按照慣例它的名稱是 self
。在呼叫方法時,我們無需明確提供與引數 self
相對應的引數。
簡單來說self就是在未建立例項時,代替例項本身。
同時 self 在定義方法的時候必須有,呼叫方法的時候要忽略。因為呼叫方法時例項已經產生,應當使用建立的例項而非self。
6.共有和私有
python中定義私有變數只要在變數前加兩個下劃線"__".
class Sheep:
a = 10
__b = 11
def sb(self):
print(self.a)
print(self.__b)
x = Sheep()
x.sb()
print(x.a)
print(x.__b)
#10
#11
#10
#AttributeError: 'Sheep' object has no attribute '__b'
當我們呼叫方法時能夠輸出私有變數,而想在方法外引用就會報錯,我們輸出x.__b就會報錯,表示例項沒有這個變數。
私有方法同上,想呼叫私有方法,只能在公有方法中引用。
7.繼承
(1)繼承的定義
被繼承的類稱為父類,繼承的類稱為子類
子類會自動繼承父類的方法和屬性。
class Person(object): # 定義一個父類
a = 1
def talk(self): # 父類中的方法
print("person is talking....")
class Chinese(Person): # 定義一個子類,繼承Person
def walk(self): # 在子類中定義其自身的方法
print('is walking...')
c = Chinese()
c.talk() # 呼叫繼承的Person類的方法
c.walk() # 呼叫本身的方法
print(c.a)
# 輸出
person is talking....
is walking...
1
(2)對子類方法的重構
如果子類中定義與父類同名的方法或屬性,則會自動覆蓋父類的該方法或屬性
class Person(object): # 定義一個父類
def __init__(self):
print("is a person")
def talk(self): # 父類中的方法
print("person is talking....")
class Chinese(Person):
def __init__(self):
print("is a Chinese person")
def walk(self):
print('is walking...')
c = Chinese()
c.talk()
c.walk()
#is a Chinese person
#person is talking....
#is walking...
要想在父類的一個方法的基礎上增加新功能,可以在同名方法下再次引用父類方法:
def __init__(self):
Person.__init__(self)
print("is a Chinese person")
#is a person
#is a Chinese person
#person is talking....
#is walking...
或者使用super()函式:
def __init__(self):
super().__init__()
print("is a Chinese person")
#is a person
#is a Chinese person
#person is talking....
#is walking...
(3)新增方法和屬性
子類可以新增其他新方法和屬性
新增屬性:
class Person:
def __init__(self,name):
self.name = name
def information(self):
print(f"my name is {self.name}")
class Chinese(Person):
def __init__(self,name,language):
super().__init__(name)
self.language = language
def information(self):
print(f"my name is {self.name} and I speak {self.language}")
a = Chinese("小明","Chinese")
a.information()
#my name is 小明 and I speak Chinese
新增方法只要在子類中直接加入就可以了。
(4)判斷是否為子類
運用issubclass()函式,有兩個待填形參,前一個填子類,後一個填父類,類是自身的子類。
class A:
pass
class B(A):
pass
print(issubclass(B, A)) # True
print(issubclass(B, B)) # True
print(issubclass(A, B)) # False
print(issubclass(B, object)) # True
python中還支援多重繼承,但是容易引起混亂所以一般不使用。
8.組合
類之間除繼承外,還可以相互引用,進行組合,使在一個類中使用其他類。
class Turtle:
def __init__(self, x):
self.num = x
class Fish:
def __init__(self, x):
self.num = x
class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x)
self.fish = Fish(y)
def print_num(self):
print("水池裡面有烏龜%s只,小魚%s條" % (self.turtle.num, self.fish.num))
p = Pool(2, 3)
p.print_num()
# 水池裡面有烏龜2只,小魚3條