python中的面向对象有许多高级特性能够帮助我们实现许多功能。
一、__slots__变量
python作为动态语言,是允许我们动态添加类和实例的属性的,但是很多时候我们想要限制实例的属性,这时候就要用到__slots__ 变量。
①使用方法:
class Student(object):
__slots__ = ('name', 'age')
我们用一个 tuple 来定义允许绑定的元素,这样我们就不能随便给实例添加属性了。
②注意点:
我们再使用 __slots__ 的时候一定要注意其定义的属性只对该类的实例起作用,继承的子类是不起作用的。
但是如果我们在继承的子类中也使用了 __slots__ 变量,那么子类的实例允许定义的属性不仅仅包括自身的 __slots__ ,还包括父类的。
二、@property
@property是一个装饰器,,用来装饰一个类。
①使用方法
一般的,我们访问和修改类的变量需要定义getdata() 和setdata() 两个属性,那么我们利用@property,也可以实现这两个属性,并且还不需要调用属性,而是直接可以输出和修改数据。
比如下面这个例子:
利用@property
给一个Screen
对象加上width
和height
属性,以及一个只读属性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()