Python學習筆記-面向對象篇 原

定義

#創建類
class Student1:
    pass

#創建類,繼承自object類
class Student1(object):
    pass

#帶構造方法的類以及對象方法調用
class Student2(object):

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

    def print_score(self):
        print('%s: %s' % (self.name, self.score))

##實例化和調用

#實例化類
>>> bart = Student1()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student1
<class '__main__.Student'>

>>> bart = Student2('Bart Simpson', 59)
>>> bart.print_score()
Bart Simpson: 59

#綁定屬性
>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'

訪問限制

  1. 雙下劃線__: 私有變量(解釋器把雙下劃線改成了單下劃線,依舊可以通過單下劃線訪問)
  2. 單下劃線_: 可以被外部訪問,但約定俗稱不要訪問
  3. 雙下劃線包圍__XXX__: 特殊變量,可以訪問

繼承

#父類、基類或者超類
class Animal(object):
    def run(self):
        print('Animal is running...')

#子類
class Dog(Animal):
    pass

class Cat(Animal):
    pass

多態

在繼承關係中,如果一個實例的數據類型是某個子類,那它的數據類型也可以被看做是父類。但是,反過來就不行。

對象類型

  1. type(): 判斷對象類型
  2. isinstance():對象是否是某種類型
  3. dir():對象的所有屬性和方法
  4. hasattr(obj, 'x'):有屬性'x'嗎?
  5. setattr(obj, 'y', 19):設置一個屬性'y'
  6. getattr(obj, 'y'):獲取屬性'y',屬性不存在,拋出AttributeError

實例屬性和類屬性

class Student(object):
    #類屬性
    name = 'Student'

    #實例屬性
    def __init__(self, name):
        self.name = name

動態綁定方法

#給對象綁定方法
>>> def set_age(self, age): # 定義一個函數作爲實例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 給實例綁定一個方法
>>> s.set_age(25) # 調用實例方法
>>> s.age # 測試結果
25

#給類綁定方法
>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = MethodType(set_score, Student)

__slots__限制只能添加指定屬性

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定義允許綁定的屬性名稱

>>> s = Student() # 創建新的實例
>>> s.name = 'Michael' # 綁定屬性'name'
>>> s.age = 25 # 綁定屬性'age'
>>> s.score = 99 # 綁定屬性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

@property簡化setter和getter

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

#當調用屬性賦值時,自動調用對應的setter方法
>>> s = Student()
>>> s.score = 60 # OK,實際轉化爲s.set_score(60)
>>> s.score # OK,實際轉化爲s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
  ...
ValueError: score must between 0 ~ 100!

多重繼承

class Dog(Mammal, Runnable):
    pass

#需要“混入”額外的功能,使用叫做 MixIn 的設計
class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):
    pass

定製類

  1. __str__:類似於Java中的toString()方法
  2. __repr__():調試時使用的字符串
  3. __iter__:返回迭代對象,用於for ... in循環
  4. __getitem__:使用下標方式獲取元素
  5. __getattr__:沒有找到屬性的情況下調用此方法
  6. __call__:把對象看成函數而直接調用所執行的方法

枚舉類

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

#遍歷
for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)

#派生
from enum import Enum, unique

@unique
class Weekday(Enum):
    Sun = 0 # Sun的value被設定爲0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6

#@unique用於檢查重複

type()

查看類型

>>> from hello import Hello
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class 'hello.Hello'>

創建類型

#1.class名,2.父類集合,3.class的方法名稱與函數綁定
>>> def fn(self, name='world'): # 先定義函數
...     print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 創建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<class 'type'>
>>> print(type(h))
<class '__main__.Hello'>

metaclass

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章