首頁  >  文章  >  後端開發  >  python中的物件導向和類別的基本語法

python中的物件導向和類別的基本語法

高洛峰
高洛峰原創
2017-03-03 13:48:35969瀏覽

當我發現要寫python的物件導向的時候,我是躊躇滿面,坐立不安呀。我一直在想:這個坑該怎麼爬?因為python中關於物件導向的內容很多,如果要講透,最好是用物件導向的想法重新學一遍前面的內容。這個坑是如此之大,猶豫再三,還是只撿一下重要的內容來講吧,不足的內容只能靠大家自己去補充了。

慣例宣告一下,我使用的版本是 python2.7,版本之間可能會有差異。

好,在開講之前,我們先思考一個問題,看程式碼:

python中的物件導向和類別的基本語法

為什麼我只創建是為a 賦值,就可以使用一些我沒寫過的方法?

可能會有小夥伴說:因為 a 此時是個字串物件呀,當然能夠使用字串的方法,至於這些方法,那是python事先寫好的。

好吧,那換個問題,為什麼 python 知道它是個字串物件?

在深入講這個問題之前,先記住一句話:python中一切皆對象,物件都是由類別建立的。

那麼類別是什麼東西呢?我在這舉個例子。

有一天,我在街上走著,突然看見前面有個仇人。此時我想揍他一頓,但是力是相互作用的呀,打他我的拳頭也會痛。誒,此時我發現路邊有個石頭,大小形狀正合適,在不考慮警察叔叔怎麼想的前提下,這是一個好的選擇。然後我抄起石頭,對著仇人進行了一些好孩子不能模仿的行為,然後深藏功與名,收工回家。

在這個過程中,我們為什麼會知道那塊東西是石頭?

因為它的具有石頭的外觀特徵呀!

為什麼我們會知道石頭可以砸人?

因為石頭硬呀!

為什麼我們知道石頭是硬的?

因為......嗯.....小時候我爸告訴我的。

此時可以得到一個結論:我們知道一個東西是什麼,具有什麼功能,是因為我們的腦海中已經有個這個東西的概念。而這個概念可能是從長輩那裡知道的,也可能是自己各種實驗後自己總結的。類似於我們對『黑洞'這個東西的認識,還是科學家的各種研究總結而來。

如何將用石頭打人這個例子用程式碼來實現的話:

class Stone(object):  # 我创建一个叫Stone的类

  def attack(self):
    print '把头伸过来,我给你加个buff'

a = Stone()  # 我用类创建了一个对象,也称为类的实例化
a.attack()   # 我使用这个对象的方法

python中的物件導向和類別的基本語法

很好,這樣我們就完成了我們的需要了。

如果我們再建立其他物件:



python中的物件導向和類別的基本語法

很顯然python並沒有為我們準備attack 方法,所以就用不了。

所謂的類別只是一個抽象的定義,而實例則是具體的物件。它們之間的差異就想我腦海中的石頭和我手中的石頭一樣,只有後者才真實存在。當然,這裡不要跟我講什麼唯心論什麼的。

看到這裡,關於類別和物件之間的關係應該清楚了一些。有些同學可能會問:python中的類別都是我們事先寫好的,有沒有方法讓python自動產生類,然後在特定的時候使用這些類別呢?恭喜你,同學,你可能摸到了人工智慧的門檻了,如果能夠實現的話,那和我們人類的學習能力不是差不多嗎?好吧,這只是我的一個設想,真正的人工智慧要怎麼實現,我也不知道,還沒有這麼高的水平去研究先,不過作為一名程式設計師,能夠編寫人工智慧,可能是終身的追求了吧。

在講完類別和實例化是怎麼一回事之後,我們來看看類別的基本語法。

首先,和定義函數的 def 一樣, class 是定義類別的關鍵字。

紧接着的是类名,这个可以自定义,同样的,不能和python的内置关键字冲突。另外,建议避开python的内建类型,例如 str、int之类的名字。规范的命名应该遵从“驼峰命名法”,例如: MyClass 这里的命名,每个单词的首字母大写。

然后是一个括号,里面的参数是用于继承的,一般继承于 object,表示一个新式类。另外,你可能见过没有括号的写法,这是经典类的写法。

示例:

class NewClass(object):
  pass

class OldClass:
  pass

New = NewClass()  # 创建一个新式类的实例
Old = OldClass()  # 创建一个经典类的实例

这就是类的基本语法,当然这样还是不够的,但是在更深入之前,我想先讲一个新旧式类的差别。

在这里,我们先打印一下两个变量的类型:

print type(New)
print type(Old)

python中的物件導向和類別的基本語法

可以看下两者的输出是不同的。

在早于python2.2的版本时,只有经典类这一种写法,当时,类和类型没有合并。

类是类对象,实例是实例对象,这两个对象之间没有任何关系。

这句话是什么意思?看代码:

print type(OldClass)
print type(Old)

python中的物件導向和類別的基本語法

我们可以看见其输出很含糊,经典类属于类对象,无论是哪个类,都统一为“类”类型,实例属于实例类型,却不知道其是由哪个类创建的,所以的实例都统一为“实例”类型。也就是说当时的类型用 classobj 和 instance 代表了所以的类和实例,无论你是哪个类,又或是哪个类创建的实例。

这样的信息实在太少,而类和类型之间非常混乱。为了解决这种情况,在 python2.2 中引入了新式类,并进行了类和类型的同统一。

print type(NewClass)
print type(New)

python中的物件導向和類別的基本語法

类的类型是 type?type 返回的对象还能像类一样创新新对象?

总结的来说:在新式类中,所以的类对象都是 type 的实例。而不同的类对象有能创建出其对应的实例。

class NewClass(object):
  def __init__(self, val):
    self.val = val

New = NewClass(123)  
b = type(New)(321) # 对实例来说type返回的是类对象,我又可以用类对象来和创建新的实例
print b.val

python中的物件導向和類別的基本語法

构造器方法

一般可以理解类中的函数就是方法,而方法分为:实例方法,只有实例化后才能调用的,其第一个参数一般为 self,代表实例本身;类方法,其第一个参数为 cls,代表类本身;还有静态方法,就是个普通函数,没有要求参数。

1. __init__(self [,arg1,....]):

当类被调用进行实例化的时候,python会自动调用类里面的构造函数(如果有的话),在构造函数中,可以进行各种初始化的操作,最常见的就是上面的进行实例的属性的创建。

python 在示例化的时候,会检查其实行了 __init__ 方法了没有,如果没有则不对实例进行任何操作,然后返回对象。如果实行了这个方法,则自动调用这个方法,并自动将 self 传进行,也就是说我们在实例化进行传参的时候,将不用理会 self,直接传给后面的参数。

讲到属性,就必须要提一下什么是属性。属性这个对象其实更像一个变量,大多数对象都可以有属性(不包括python的内置类型),例如函数。

def Test():
  pass

Test.a = 123
print Test.a

python中的物件導向和類別的基本語法

因为函数也是一个对象。

属性在类中,就是一个变量,例如:

class NewClass(object):
  a = 123

print NewClass.a

python中的物件導向和類別的基本語法

当然,因为 python 的特性,我们可以在运作中为某个对象添加属性,而不用一开始就在类中写定。

注意,这个方法应该返回 None,也就是说我们一般不用 return 任何对象,让它默认返回就行了。

2. __new__(cls [,arg1,....]):

这也是一个构造器方法,它是一个类方法,一般在对 python 的不可变数据类型进行继承扩展的时候用的比较多。

某处拿来的代码示例:

class RoundFloat(float):
  def __new__(cls, val):
    return super(RoundFloat, cls).__new__(cls, round(val, 2))

a = RoundFloat(3.14159)
print a

python中的物件導向和類別的基本語法

解构器方法

__del__(self [,arg1,....])

这个方法将会在对象所以的引用被清除后才执行,例如:

class Test(object):

  def __del__(self):
    print '我被干掉了,兄弟们为我报仇!'

a = Test() # 创建了一个对象
b = a  # b又引用了a
c = b  # c又引用了b,现在 a 所指向的对象有3次引用,相当有三条命
del a  # 干掉一条命
del b  # 又干掉
del c  # 听说你有3条命?全部干掉!

python中的物件導向和類別的基本語法

注意,这里只输出了一次,也就是说到了最后才删除完毕。这里要注意一下几点:

1.调用 del 并不意味着完成删除某个对象,只是减少引用。

2.如果你有一个循环引用或其它的原因,让一个实例的引用逗留不去,该对象的__del__()可能永远不会被执行。

3.__del__()未捕获的异常会被忽略掉(因为一些在__del__()用到的变量或许已经被删除了)。 不要在__del__()中干与实例没任何关系的事情。

4.一般情况下并不用实现这个方法,因为这样有一定的风险。

5.如果你定义了__del__,并且实例是某个循环的一部分,垃圾回收器将不会终止这个循环— —你需要自已显式调用 del。

6.如果继承了父类,且父类中也有解构器,要记得调用。否则可能会有某些在父类中的清理方法没有调用到,出现以下无法预料的错误。

以上这篇浅谈python中的物件導向和類別的基本語法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持PHP中文网。

更多python中的物件導向和類別的基本語法相关文章请关注PHP中文网!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn