Python學習筆記(六)面向對象高級編程

參考資料:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386820058291028118ddeefc4de7860a8e48b9942e9b000

1、類及實例屬性、方法的動態綁定。

    作爲動態語言,Python允許給類或實例的屬性、方法作動態綁定。在類定義時,使用__slots__可以定義只允許在給定的屬性(方法)名稱上作動態綁定,父類中定義的__slots__不會作用到子類,除非子類定義時也指定了__slots__,如果父類和子類都指定了__slots__,則子類綁定限制範圍將是父類__slots__與子類__slots__的合集。例子代碼如下:

class Student(object):
    __slots__ = ('name', 'age')

def setName(self, name):
    self.name = name
#動態綁定方法前,必須添加該引用
from types import MethodType
#給Student類動態綁定自定義方法
Student.setName = MethodType(setName, None, Student)
a = Student()
a.setName('mary')
print a.name
#由於類定義中指定了__slots__,執行下面的代碼會出錯
a.score = 99
print a.score
#下面的代碼驗證父類的__slots__不會影響子類及其實例的動態綁定
class MyStudent(Student):
    pass
b = MyStudent()
b.setName('tom')
b.score = 99
print b.name, b.score
#下面的代碼驗證了父類與子類同時定義__slots__的效果
class MyStudent1(Student):
    __slots__ = ('test')
c = MyStudent1()
c.setName('alice')
c.score = 99
print c.name, c.score

2、屬性裝飾器@property

直接看代碼。

class MyStudent2(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 1-100")
        self._score = value
d = MyStudent2()
d.score = 80
print d.score
d.score = -1
print d.score

3、多重繼承。

與Java和C#不同,Python允許多重繼承。例子代碼如下:

class Animal(object):
    def __init__(self):
        print "I am an Animal"
class FlyMixin(object):
    def fly(self):
        print "I can fly"
class RunMixin(object):
    def run(self):
        print "I can run"
class Bird(Animal, FlyMixin, RunMixin):
    pass
a = Bird()
a.fly()
a.run()

4、一些定製方法。

在Python類定義過程中,會用到一些形如__xxx__的定製方法。下面列舉一些常用的方法,全面學習可查看官方文檔

(1)__str__:定義在輸出一個類實例(print 類實例)時要做的操作。

(2)__iter__:與自定義next()方法配合,可將類實例用作for循環。

(3)__getitem__:定義該函數,類實例可當作列表訪問,如L爲類實例變量則L[0]調用__getitem__方法。

(4)__getattr__:定義該函數,當訪問實例未顯式定義的屬性或方法時,會執行該函數。

(5)__call__:定義該函數,當以“實例名()”的形式執行代碼時,將調用該函數。

下面的代碼以一個集成了上述定製方法的斐波那契序列類演示了這些方法的應用:

class Fib(object):
    def __init__(self, max):
        self.max = max
        self.a, self.b = 0, 1
    def __str__(self):
        return 'Fib object with maxvalue(%d)' % self.max
    __repr__ = __str__
    def __iter__(self):
        return self
    def next(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > self.max:
            raise StopIteration()
        return self.a
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a
    def __getattr__(self, attr):
        if attr == 'name':
            return 'Fib List with (%d)' % self.max
        return 'No attribute with name (%s)' % attr
    def __call__(self):
        print 'My name is ', self.name
n = Fib(10)
print n
for f in n:
    print f
print n[100]
print n.name
print n.score
n()

5、動態創建類。

前面學習過的type()函數可以動態創建一個類,調用格式爲type('類名', 父類tuple, 方法名與函數綁定字典)。例子代碼如下:

def fn(self, name='world'):
    print 'Hello,', name
Hello = type('Hello', (object,), dict(hello=fn))
h = Hello()
h.hello()

6、用於自定義類創建行爲的元類(metaclass)

直接看代碼。

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)
class MyList(list):
    __metaclass__ = ListMetaclass
l = MyList()
l.add(1)
print l[0]

注:元類用於創建類,所以必須從type繼承。

參考資料中給出了一個利用元類實現的ORM框架的例子

今天就學習到這裏,下節從錯誤調試學起。

發佈了80 篇原創文章 · 獲贊 3 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章