python 面向對象

面向對象

對象:是指現實中的物體實體化,對象有很過屬性(名字、年齡..),也有不少行爲(學習、吃飯..),實例即對象。對象同時也是經過類定義的數據結構實例,對象包括兩個數據成員(類變量和實例變量)和方法。對象能夠包含任意數量和類型的數據。html

實例化:建立一個類的實例,類的具體對象化,實例就是類的實例化,d1 = gog(),d1即爲實例python

:擁有相同屬性和方法(行爲)的對象劃爲一組,稱爲類,類是建立對象的工具
編程

方法:類中定義的函數數據結構

類變量:在類中被定義的變量,一般以self.variable的形式被定義,類變量一般不做爲實例變量使用ide

方法重寫:若是從父類繼承的方法不能知足子類的需求,能夠對其進行修改,這個過程叫方法的覆蓋,也叫方法的重寫函數

繼承:及一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也容許把一個派生類的對象做爲一個基類對象對待。工具

Python中的類提供了面向對象編程的全部基本功能:類的繼承機制容許多個基類,派生類能夠覆蓋基類中的任何方法,方法中能夠調用基類中的同名方法。學習

類定義  語法格式url

  class 類名(繼承列表):spa

    """類的文檔字符串"""

    類變量的定義

    實例方法的定義

    類方法的定義(@classmethod)

    靜態方法的定義(@staticmethod)

做用:

  建立一個類,類用於描述對象的行爲和屬性,類用於建立此類的一個或者多個對象(實例)類名實質上是變量,它綁定一個類

類的文檔字符串

類內第一個沒有賦值給任何變量的字符串爲類的文檔字符串,類的文檔字符串能夠用類的 __doc__屬性訪問

help(Dog)    查看文檔字符串

類.__doc__屬性用來綁定文檔字符串

類變量的定義

類變量就類的屬性,此屬性屬於類,不屬於此類的實例

做用:一般用來存儲該類建立的對象的共有屬性

說明:類變量能夠經過該類或該類的實例直接訪問;類變量能夠經過此類的實例對象的__class__屬性間接訪問

class Human:
    total_count = 0  # 類變量

    def __init__(self, name):
        print(name, '對象被建立')


print(Human.total_count)  # 類直接訪問類變量 0
h1 = Human('小張')
print(h1.total_count)  # 0 用此類的實例能夠訪問類變量
h1.total_count = 100  # 爲對象添加實例變量
print(h1.total_count)  # 100, 優先訪問對象的實例變量
print(Human.total_count)  # 0, 訪問類的類變量
print(h1.__class__.total_count)  # 0 經過此類的實例對象的__class__屬性來訪問類變量

初始化方法 __init__()

一、初始化方法__init__()會在構造函數建立實例後自動調用

二、初始化方法若是須要return語句返回,則只能返回None

三、通常類都會傾向於將(實例)對象建立爲有初始化狀態的

四、實例方法至少有一個形參,第一個形參表明調用這個方法的實例,通常命名爲'self',所以類可能會定義一個名爲__init__()的特殊方法(構造方法)

五、__init__有形參時,參數會經過__init__()傳遞到實例化對象上。

class complex:
    # 構造函數,在實例化時作一些類的初始化工做,__init__用來傳參的
    def __init__(self, name, age):  # 定義類的方法
        self.name = name    # 實例變量(靜態屬性)
        self.age = age

x = complex("做者",23)       # 類的實例化,變成具體對象
print(x.name,x.age)

# 做者 23

類的方法與普通的函數只有一個特殊的區別————他們必須有一個額外的第一參數名稱self,按照慣例它的名稱是self,誰調用這個類的方法,self就指向誰。self表明類的實例化,而非類

class Test:             #定義一個名爲Test的類
    def prt(self):      #定義類的方法prt
        print(self)
        print(self.__class__)   # self.__class__指向類

t = Test()  #類的實例化
t.prt()     #訪問類的方法

# <__main__.Test object at 0x000001836DFE10B8>
# <class '__main__.Test'>

self表明的是類的實例,表明當前對象的地址,而self.__class__則指向類名。

self不是python的關鍵詞,咱們把self換成其餘的表示符也是能夠的(在這裏咱們把self換成runoob)

class Test:  # 定義一個名爲Test的類
    def prt(runoob):  # 定義類的方法prt
        print(runoob)
        print(runoob.__class__)


t = Test()  # 類的實例化
t.prt()  # 訪問類的方法
# <__main__.Test object at 0x000001836DFE10B8>
# <class '__main__.Test'>

類的__slots__列表

做用:限定一個類建立的實例只能有固定屬性(實例屬性),不容許對象添加列表之外的屬性(實例變量)

說明:__slots__列表綁定一個字符串列表,含有__slots__列表的類所建立的實例對象沒有__dict__屬性,即此實例不用字典來存儲對象的屬性(實例變量)

__slots__ = [" ", " "]

class Human:
    # 如下列表限制此類的對象只能有'name' 和'age' 屬性
    __slots__ = ['name', 'age']

    def __init__(self, name, age):
        self.name, self.age = name, age


h1 = Human("Tarena", 15)
print(h1.age)  # 15
# h1.Age = 18  # 出錯,h1對象沒有Age屬性,也不容許有Age屬性
print(h1.age)  # 15

類方法 @classmethod

類方法是用於描述類的行爲的方法,類方法屬於類,不屬於類的實例

說明:類方法須要使用@classmethod裝飾器定義,

  def關鍵詞來定義一個方法,類方法至少有一個形參,第一個參數用於綁定類,約定寫爲" cls ",類和該類的實例均可以調用類的方法

class people:  # 定義一個類
    # 定義類的屬性
    name = ''
    age = 0
    # 定義私有屬性,私有屬性在類外部沒法直接進行訪問
    _weight = 0

    # 定義構造的方法
    def __init__(self, n, a, w):
        # 定義類的初始化屬性
        self.name = n
        self.age = a
        self._weight = w

    # 定義類的方法
    @classmethod
    def speak(cls):
        print("%s說:我%d歲" % (self.name, self.age))


# 實例化類  把一個類變成具體對象叫作類的實例化
p = people("做者", 18, 30)
p.speak()       # 做者說:我18歲

靜態方法  @staticmethod

靜態方法是定義在類內部的函數,此函數的做用域是類的內部

說明:靜態方法須要使用 @staticmethod裝飾器定義,

  靜態方法與普通函數定義相同,不須要傳入self實例參數和cls參數,靜態方法只能憑藉該類或類建立的實例調用,靜態方法不能訪問類變量和實例變量(屬性)

class A:
    @staticmethod
    def myadd(a, b):
        return a + b


print(A.myadd(100, 200))  # 300
a = A()  # 建立實例
print(a.myadd(300, 400))  # 700

實例方法、類方法、靜態方法、函數小結

  不想訪問類內和實例內的變量,用靜態方法

  只想訪問類內變量,不想訪問實例變量,用類方法

  即要訪問內變量,也想訪問實例變量用實例方法

  函數與靜態方法相同,只是靜態方式的做用域定義在類內

class Classname:
    @staticmethod
    def fun():
        print('靜態方法')

    @classmethod
    def a(cls):
        print('類方法')

    # 普通方法
    def b(self):
        print('普通方法')


Classname.fun()     # 靜態方法
Classname.a()       # 類方法

C = Classname()     
C.fun()             # 類方法
C.a()               # 類方法
C.b()               # 普通方法

類的實例化

類實例化後,可使用其屬性,實際上,建立一個類以後,能夠經過類名訪問其屬性

d1 = dog() # 調用構造函數建立實例化對象

類對象  

類對象支持兩種操做:屬性引用和實例化。

類對象建立後,類命名空間中的全部命名都是有效屬性名,類定義以下所示:

class Myclass:  # 定義一個本身的類
    """一個簡單的類實例"""
    i = 12345  # 類變量

    def f(self):  # 定義類的方法
        return "你好呀"


# 類的實例化,用x來綁定以便後面使用,否則用完以後就釋放了
x = Myclass()  # 把一個類變成具體對象的過程叫作實例化(初始化)
# 訪問類的屬性和方法
print("Myclass類的屬性i:", x.i)     # 12345
print("Myclass類的方法f:", x.f())   # 你好呀!

 python支持 在類的外面 建立類的屬性

class Dog:
    def eat(self, food):
        # print("小狗正在吃:", food)
        print(self.color, '', self.kinds, '正在吃', food)


dog1 = Dog()    # 類的實例化
dog1.kinds = '京巴'  # 爲dog1對象添加kinds屬性,綁定爲'京巴'
dog1.color = '白色'  # dog1添加屬性 爲'白色'
dog1.color = '黃色'  # 改變dog1的color屬性

# 訪問dog1 的屬性
print(dog1.color, "", dog1.kinds)  # 黃色 的 京巴

dog2 = Dog()
dog2.kinds = '哈士奇'
dog2.color = '黑白相間'
print(dog2.color, '', dog2.kinds)  # 黑白相間 的 哈士奇

dog1.eat('骨頭')  # 黃色 的 京巴 正在吃 骨頭
dog2.eat('窩頭')  # 黑白相間 的 哈士奇 正在吃 窩頭

# 定義私有屬性,私有屬性在類外部沒法直接進行訪問 __weight = 0,在變量前面加雙下劃線

刪除屬性del語句

  del 變量名  刪除變量

  del 列表[整數表達式]  刪除列表中的元素

  del 字典[鍵]        刪除字典中的鍵

  del 對象.屬性       刪除對象的屬性

析構方法:

  class 類名:

    def __del__(self):

      ......

說明:析構方法在對象被銷燬時作任何事情,由於銷燬的時間難以肯定

預置實例屬性:

  __dict__屬性

  __dict__屬性綁定一個存儲此實例自身變量的字典

class Dog:
    pass


dog1 = Dog()
print(dog1.__dict__)  # {}
dog1.kinds = '京巴'
print(dog1.__dict__)  # {'kinds': '京巴'}

__class__屬性:

  此屬性用於綁定建立此實例的類

 做用:能夠藉助於此屬性來訪問建立此實例的類

class Dog:
    pass


dog1 = Dog()
print(dog1.__class__)  # <class '__main__.Dog'>
dog2 = dog1.__class__()
print(dog2.__class__)  # <class '__main__.Dog'>

用於類的函數:

  isinstance(obj, class_or_tuple) 返回這個對象obj是不是某個類的對象或某些類中的一個類的對象,若是是則返回True,不然返回False,type(obj) 返回對象的類型

繼承/派生

繼承是指從已有的類中派生出新的類,新類具備原類的行爲,並能擴展新的行爲

派生類就是從一個已有類中衍生成新類,在新類上能夠添加新的屬性和行爲

做用:1.用繼承派生機制,能夠將一些共有功能加在基類中,實現代碼的共享

      二、在不改變基類的代碼的基礎上改變原有的功能

名詞:基類(base class)/超類(super class)/父類(father class)

     派生類(derived class) / 子類(child class)

單繼承

單繼承:

  語法:

    class 類名(基累名):

      語句塊

  說明:單繼承是指由一個基類衍生出的新的類

class Derived_Class_Name(Base_Class_Name1):
    <statement-1>
    .
    .
    <statement-N>

單繼承實例

class Human:  # 人類的共性
    def say(self, what):
        print("say:", what)

    def walk(self, distance):  # 走路
        print("走了", distance, '千米')


class Student(Human):
    def study(self, subject):
        print("正在學習:", subject)


class Teacher(Student):
    '''說話,行走,教學'''
    def teach(self, subject):
        print("正在教:", subject)

h1 = Human()
h1.say('天氣晴了')
h1.walk(5)
print('---------------')
s1 = Student()
s1.walk(4)
s1.say('感受有點累')
s1.study('Python')
print('===============')
t1 = Teacher()
t1.walk(6)
t1.say('吃點啥好呢')
t1.teach('面向對象')
t1.study('轉魔方')

繼承說明:python3 任何類都直接或間接的繼承自object類,object 類是一切類的超類

類的__base__屬性:__base__屬性用來記錄此類的基類

覆蓋

覆蓋是指在有繼承關係的類中,子類中實現了與基類同名的方法,在子類的實例調用該方法時,實際調用的是子類中的覆蓋版本

class A:
    def works(self):
        print("A.works被調用")

class B(A):
    """B類繼承A類"""
    def works(self):
        print("B.works被調用")

a = A()
a.works()  # A.works被調用

b = B()
b.works()  # B方法被調用

用類名顯式調用

子類對象顯式調用基類(被覆蓋)方法的方式:基類名.方法名(實例, 實際調用傳參)

class A:
    def works(self):
        print("A.works被調用")

class B(A):
    ''' B類繼承自A類'''
    def works(self):
        print("B.works被調用")

b = B()
b.works()  # B.works被調用
A.works(b)  # 用類名顯式調用, A.works被調用

super函數

super(cls, obj)返回綁定超類的實例(要求obj必須是cls類型的實例),通常obj就是selfcls通常就是當前類的類名

super()  返回父類的實例,

常見用法:super(__class__, 實例方法的第一個參數),必須在方法內調用,通常super(class_name, self).父類方法  # 中間參數能夠省略,以下例

做用:藉助super() 返回的實例間接調用其父類的覆蓋方法

super().父類方法()

class A:
    def works(self):
        print("A.works被調用")


class B(A):
    """B類繼承自A類"""
    def works(self):
        print("B.works被調用")

    def super_work(self):
        self.works()  # B.works被調用
        super(B, self).works()  # A.works被調用
        super().works()  # A.works被調用


b = B()
b.works()  # B.works被調用
super(B, b).works()  # A.works被調用
b.super_work()  # ...
# B.works被調用
# A.works被調用
# A.works被調用

super().works()  # 出錯,只能在方法內調用

顯式調用基類的初始化方法

當子類中實現了 __init__方法,基類的構造方法並不會被調用,def __init__(self, ...)

super().__init__(n,a)    # 參數不填的話,默認調用父類的全部初始化參數

class Human:
    def __init__(self, n, a):
        self.name, self.age = n, a
        print("Human的__init__方法被調用")

    def infos(self):
        print("姓名:", self.name)
        print("年齡:", self.age)


class Student(Human):
    def __init__(self, n, a, s=0):
        super().__init__(n, a)  # 顯式調用父類的初始化方法
        self.score = s  # 添加成績屬性
        print("Student類的__init__方法被調用")

    def infos(self):
        super().infos()  # 調用父類的方法
        print("成績:", self.score)


s1 = Student('小張', 20, 100)
s1.infos()

多繼承

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    <statement-N>

須要注意圓括號中父類的順序,如果父類中有相同的方法名,而在子類使用時未指定,python從左至右搜索 即方法在子類中未找到時,從左到右查找父類中是否包含方法。

class people:
    name = ''
    age = 0
    __weight = 0

    def __init__(self, n, a, w):
        self.name = n
        self.age = a
        self.__weight = w

    def speak(self):
        print("%s 說: 我 %d 歲。" % (self.name, self.age))

class speaker():
    topic = ''
    name = ''

    def __init__(self, n, t):
        self.name = n
        self.topic = t

    def speak(self):
        print("我叫 %s,我是一個演說家,我演講的主題是 %s" % (self.name, self.topic))


# 多繼承
class sample(speaker, people):
    a = ''

    def __init__(self, n, a, w, t):
        # 調用父類的構函數
        people.__init__(self, n, a, w)
        speaker.__init__(self, n, t)


test = sample('凌逆戰', "大學生", 23, 'python')
test.speak()  # 方法名重複了,默認調用的是括號中排前地父類的方法
# 我叫 凌賢鵬,我是一個演說家,我演講的主題是 python

方法重寫

若是父類方法的功能不能知足需求,能夠在子類重寫父類的方法

class parent:  # 定義父類
    def my_method(self):
        print("調用父類的方法")


class child(parent):  # 定義子類
    def my_method(self):
        print("調用子類方法")


c = child()  # 子類實例

# 子類調用重寫方法
c.my_method()       # 調用子類方法

# 用子類對象調用父類已被覆蓋的方法
super(child, c).my_method()  
# 調用父類的方法

super()函數是用於調用父類(超類)的方法

Python 子類繼承父類構造函數說明

類屬性與方法

類的私有屬性

__private_attrs:兩個寫劃線開頭,聲明該屬性爲私有類,不能在類地外部被使用或直接訪問,在類內部的方法使用時self.private_attrs

類的方法

在類地內部,使用def關鍵字來定義一個方法,與通常函數定義不一樣,類方法必須包含self,且爲第一個參數,self表明的是類的實例。

self的名字並非規定死的,也能夠是其餘的,但最好按照規定用self

類的私用方法

__private_method:兩個下劃線開頭,聲明該方法爲私有方法,只能在類的內部調用 ,不能在類地外部調用。self.__private_methods

類的私有屬性

class JustCounter:
    __secretCount = 0  # 私有變量
    publicCount = 0  # 公開變量

    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print(self.__secretCount)


counter = JustCounter()
counter.count()     # 1
counter.count()     # 2
print(counter.publicCount)  # 2
print(counter.__secretCount)  
# 報錯,實例不能訪問私有變量
# Traceback (most recent call last):
#   File "test.py", line 16, in <module>
#     print (counter.__secretCount)  # 報錯,實例不能訪問私有變量
# AttributeError: 'JustCounter' object has no attribute '__secretCount'

類的私有方法

class Site:
    def __init__(self, name, url):
        self.name = name  # public
        self.__url = url  # private

    def who(self):
        print('name: ', self.name)
        print('url : ', self.__url)

    def __foo(self):  # 私有方法
        print('這是私有方法')

    def foo(self):  # 公共方法
        print('這是公共方法')
        self.__foo()


x = Site('菜鳥教程', 'www.runoob.com')
x.who()  # 正常輸出
x.foo()  # 正常輸出
x.__foo()  # 報錯

類的專有方法

  • __init__:構造函數,在生成對象時調用
  • __del__ : 析構函數,釋放對象時使用
  • __repr__ : 打印,轉換
  • __setitem__ : 按照索引賦值
  • __getitem__: 按照索引獲取值
  • __len__: 得到長度
  • __cmp__: 比較運算
  • __call__: 函數調用
  • __add__: 加運算
  • __sub__: 減運算
  • __mul__: 乘運算
  • __div__: 除運算
  • __mod__: 求餘運算
  • __pow__: 乘方

運算符重載

class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)

    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)


v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)      # Vector(7,8)
相關文章
相關標籤/搜索