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框架的例子

今天就学习到这里,下节从错误调试学起。

猜你喜欢

转载自blog.csdn.net/alvin_2005/article/details/80331628