Python面向對象編程基礎實例分析

這篇文章主要介紹了Python面向對象編程基礎,結合實例形式分析了Python面向對象編程類的定義、繼承、特殊方法及模塊相關原理與操作技巧,需要的朋友可以參考下

本文實例講述了Python面向對象編程基礎。分享給大家供大家參考,具體如下:

1、類的定義

Python中類的定義與對象的初始化如下,python中所有類的父類是object,需要繼承。

由於Python是動態語言,因此可以直接爲對象添加屬性並賦值而不必在類定義中聲明

class Person(object):  # 定義一個Person類
  pass
p = Person()  # 初始化一個Person對象
p.name="xiaoming"  # 對象屬性賦值

Python的類初始化方法爲__init__(),其第一個參數爲self代之對象自身,其後爲各個參數,初始化就是將傳入的參數賦值給對象的屬性。**kw代表任意數量的屬性,通過key=attribute的形式傳入,之後通過setattr()方法將每個屬性賦值給對象。

直接在class中定義的變量稱爲類屬性,在__init__()中定義的爲對象屬性,類屬性供所有對象共享,對象只能訪問卻無權修改。當通過對象給類屬性賦值時,會爲對象新建一個同名的對象屬性,而不是修改類屬性。無論在類的內部還是外部,都通過類名對類屬性進行訪問。

以__開頭的變量無法被外部訪問,類似於私有變量。這時就需要對象的實例方法從類的內部訪問私有變量並做出相應的操作,這樣在類的內部定義的方法叫做實例方法,實例方法的第一個參數默認爲self代表對象自己。

相應地類方法只能訪問類屬性,其定義方式是在之前添加標記@classmethod:,其第一個參數cls代表類本身

class Person(object):
  count = 0  # 類屬性
  @classmethod:
  def get_count(cls):  # 類方法
    return cls.count
  def __init__(self,name,gender,birth,**kw):
    Person.count+=1  # 訪問類屬性
    self.name = name
    self.__gender = gender
    self.birth = birth
    for k, v in kw.iteritems():  # 遍歷之後的鍵值對,設置屬性
      setattr(self, k, v)
  def get_name(self):  # 定義實例方法
    return self.__name
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
xiaoming.count==9  # 爲對象創建屬性,不會修改Person.count
print(xiaoming.job)  # 顯示Student
print(xiaoming.__gender)  # 無法訪問,拋出異常AttributeError
print(xiaoming.get_name())  # 通過實例方法訪問內部變量

2、類的繼承

Python中類的繼承方式如下。值得注意的是在子類Teacher中需要通過super(子類名,self)調用父類的初始化函數來完成對父類中參數的初始化。也可以直接通過父類名稱調用父類的方法

通過type()方法輸出變量的類型,isinstance()可以判斷變量是否是某個類型,dir()方法返回變量的所有屬性和方法列表。輸出對象t的屬性結果如下,其中帶__的爲默認屬性,其餘爲自定義的屬性

[‘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’, ‘course’, ‘gender’, ‘name’]

class Person(object):
  def __init__(self, name, gender):
    self.name = name
    self.gender = gender
class Teacher(Person):  # 繼承父類Person
  def __init__(self, name, gender, course):
    super(Teacher,self).__init__(name,gender)  # 調用父類的初始化函數
    self.course= course  # 完成子類變量的初始化
t = Teacher('Alice', 'Female', 'English')
print(isinstance(t,Person))  # 結果爲True,子類也是父類的類型
print(dir(t))  # 顯示對象的所有屬性

和其他面向對象的語言一樣,Python具有多態的特性,例如父類和不同的子類都定義了相同的方法,當不同的子類調用該方法時會調用自己定義的方法,從而實現相同的方法具有不同的操作。但python是動態語言,和靜態語言C++、Java不同的是在調用實例方法時,python不檢查類型,只要方法存在,參數正確,就可以調用。例如原本json的load方法中定義了read()方法用於實現對文件的讀取,當我們自定義一個類其中包含read()方法時,便可動態調用實例方法

import json
class Students(object):
  def read(self):
    return r'["Tim", "Bob", "Alice"]'
s = Students()
print json.load(s)

一個子類可以同時繼承兩個以上的父類,這個特性叫做多繼承,當有多個父類時,需要在初始化時指明父類

class A(object):
  def __init__(self, a):
    self.a = a
class B(object):
  def __init__(self, b):
    self.b = b
class C(A, B):
  def __init__(self, a, b, c):
    A.__init__(self, a)
    B.__init__(self, b)
    self.c = c
c = C(1, 2, 3)
print(c.a)   # 輸出1

推薦我們的Python學習扣qun:913066266 ,看看前輩們是如何學習的!從基礎的python腳本到web開發、爬蟲、django、數據挖掘等【PDF,實戰源碼】,零基礎到項目實戰的資料都有整理。送給每一位python的小夥伴!每天都有大牛定時講解Python技術,分享一些學習的方法和需要注意的小細節,點擊加入我們的 python學習者聚集地

3、類的特殊方法

Python的特殊方法是指定義在類中,以__開頭和結尾,由某些函數或操作符隱式觸發調用的方法。例如當我們使用print§打印一個Person對象p時,就會調用Person的__str__()方法將p轉化爲字符串共print輸出,輸出結果爲:<main.Person object at 0x000001787CC7C0D0>

當我們重新自定義這些特殊方法後,當觸發調用時就會按我們定義的函數執行。例如重新定義__str__(),當print()時就會顯示My name is Bob

class Person(object):
  def __init__(self, name, gender):
    self.name = name
    self.gender = gender
  def __str__(self):  # 重新定義類特殊方法
    return "My name is " + self.name
p = Person('Bob', 'male')
print(p)  # 輸出結果爲:My name is Bob

cmp()方法用於實現類的比較,在排序時會自動調用。例如在Student類中重新定義該方法,按分數高低對學生進行排序,其有兩個參數,第一個自己self,第二個是比較的對象s,如果self應該在s之前,則返回-1

class Student(object):
  def __init__(self, name, score):
    self.name = name
    self.score = score
  def __cmp__(self, s):  # 重寫__cmp__方法
    if self.score>s.score:
      return -1  # self在s之前
    elif self.score<s.score:
      return 1
    else:
      return 0
L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
Ls = sorted(L)  # 使用sorted對Student類進行排序

len()方法用於返回長度,當len()調用類時會觸發

addsubmul、__div__分別對應類的加減乘除運算,當類遇到運算符±*/時會調用該方法,例如實現一個分數類Rational的加法:1/2+1/4,通分相加得6/8,最後求最大公約數後約分得到3/4

int、__float__方法在int()、float()調用類時觸發,可以重新該方法返回一個int或float結果

def gcd(a, b):  # 求最大公約數
  if b == 0:
    return a
  return gcd(b, a % b)
class Rational(object):
  def __init__(self, p, q):
    self.p = p
    self.q = q
  def __add__(self, r):  # 重寫加法運算
    return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
  def __str__(self):
    g = gcd(self.p, self.q)  # 將分數約分後輸出
    return '%s/%s' % (self.p / g, self.q / g)
  def __float__(self):  # 將分數轉化爲float小數返回
    return float(self.p)/float(self.q)
r1 = Rational(1, 2)
r2 = Rational(1, 4)
print(r1 + r2)  # 兩個類相加
print(float(r1))  # 輸出小數形式

類屬性的裝飾器@property用於將類方法轉化爲屬性,這樣就可以像訪問屬性一樣調用方法。例如Student類的__score屬性對外是不可見的,通過定義返回方法score使得對象s可以通過s.score得到分數值。

@property.setter方法用於對屬性設置方法進行裝飾,使得可以像給屬性賦值一樣調用類方法。例如當使用s.score=99時會調用設置方法score(self,score),將值傳遞給__score,並且可以對傳入值的合法性進行檢驗。

slots()用於定義類中可以使用的屬性,父類定義過的子類中無需重複定義。當添加新的屬性並賦值時,運行會拋出異常AttributeError

call()將一個類實例變成一個可調用對象,例如一個Student對象s,像函數調用一樣使用對象:s(‘Alice’)

class Student(object):
  __slots__ = ('name','__score')  # 本類只允許使用name、score兩個屬性
  def __init__(self, name, score):
    self.name = name
    self.__score = score
  @property        # 定義屬性返回方法
  def score(self):
    return self.__score
  @score.setter      # 定義屬性設置方法
  def score(self, score):
    if score < 0 or score > 100:
      raise ValueError('invalid score')
    self.__score = score
  def __call__(self, friend):
    print('My friend is %s...' % friend)
s = Student('Bob', 59)
s.score = 60  # 調用屬性設置方法
print(s.score)  # 調用屬性返回方法
s.grade='A'  # 拋出異常,無法添加其他屬性
s('Alice')  # 輸出My friend is Alice...

getattribute(self,attr)、setattr(self,attr)、delattr(self,attr)分別用於獲取、設置、刪除屬性時觸發的方法,在使用時應注意避免遞歸調用引起的無限循環,例如在get方法中再調用get類似的方法導致無限循環。

4、模塊管理

爲了方便分類管理python中的類和方法,需要將代碼放在不同的文件中,每個文件構成了一個獨立的模塊,不同模塊之間相同的變量名不會引起命名衝突。但是如果在文件a.py中希望使用文件b.py中的函數func1,則可以通過import在a中導入模塊b,並通過b.func1()調用該方法。或者通過from直接引入模塊中的函數。在引入時爲了防止命名衝突,可以通過as爲引入的函數起個別名

# 文件a.py中
import b
print(b.func1())
# 直接引入函數
from b import func1
print(func1())
# 使用別名
from b import func1 as f1
print(f1())

有時將相同類別的模塊放在一個文件夾內,就形成了一個包,python要求一個包文件夾內必須有一個__init__.py文件纔會識別爲一個包,即使它是一個空文件。這時如果一個p1包內的a.py想訪問p2包內的b.py中的函數func2,則操作如下

# p1/a.py文件內
import p2.b
print (p2.b.func2())
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章