【python基础】学习笔记五 面向对象高级编程

python中的面向对象有许多高级特性能够帮助我们实现许多功能。

一、__slots__变量

python作为动态语言,是允许我们动态添加类和实例的属性的,但是很多时候我们想要限制实例的属性,这时候就要用到__slots__ 变量。

①使用方法:
class Student(object):
    __slots__ = ('name', 'age')

我们用一个 tuple 来定义允许绑定的元素,这样我们就不能随便给实例添加属性了。

②注意点:

我们再使用 __slots__ 的时候一定要注意其定义的属性只对该类的实例起作用,继承的子类是不起作用的。

但是如果我们在继承的子类中也使用了 __slots__ 变量,那么子类的实例允许定义的属性不仅仅包括自身的 __slots__ ,还包括父类的。

二、@property

@property是一个装饰器,,用来装饰一个类。

①使用方法

一般的,我们访问和修改类的变量需要定义getdata() 和setdata() 两个属性,那么我们利用@property,也可以实现这两个属性,并且还不需要调用属性,而是直接可以输出和修改数据。

比如下面这个例子:

利用@property给一个Screen对象加上widthheight属性,以及一个只读属性resolution

import sys
sys.setrecursionlimit(1000000)

class Screen(object):

    @property
    def width(self):
        return self._width
    
    @width.setter
    def width(self,width):
        self._width = width
    
    @property
    def height(self):
        return self._height
    
    @height.setter
    def height(self, height):
        self._height  = height
    
    @property
    def resolution(self):
        return self._width * self._height

s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
    print('测试通过!')
else:
    print('测试失败!')

这里我们可以看到,对实例 s 的 _width _height 赋值或修改可以直接通过等号。

不过这里要注意的是,我们调用 width 属性为 s._width 赋了值,而不是赋给 s.width,width是用来修改和访问变量 _width 的函数,而不是变量。


三、__str__

我们想要对实例的输出进行定制的就需要用到 __str__

class Student(object):

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

    def __str__(self):
        return 'Student object (name: %s)' % self.name

    __repr__ = __str__

print(Student('Michael'))


四、__getattr__

①使用方法

我们在调用类的属性或者方法的时候,如果不存在就会报错,为了避免这种错误,就需要使用到 __getattr__

__getattr__ 中我们可以定义可以被调用的属性,也可以定义不可以被调用的属性被访问时抛出的错误。

class Student(object):

    def __init__(self):
        self.name = 'Michael'

    def __getattr__(self, attr):
        if attr=='score':
            return 99
        if attr=='age':
            return lambda: 25
        raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
②注意点

需要注意的是,__getattr__ 的调用机制是:一旦没有找到属性,就会调用。因此这方便我们干其他的一些事情:比如我们可以利用 __getattr__ 直接返回动态对象,而不需要再一一去创建。


五、__call__

利用 __call__ 我们可以直接调用实例本身,这样一来,实例对象本身就可以看作一个函数,同样也可以传递参数。

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)

s = Student('Michael')
s()


展开阅读全文

没有更多推荐了,返回首页