每天5分钟玩转Python(23) - 对象属性
前面介绍了面向对象编程的三个基本特性:封装、继承和多态。这一章开始讲解一些高级特性,可以让我们如虎添翼, 编写更高阶的程序。包括对象属性、多继承、定制类和元类。
使用__slots__
当我们创建了一个类的实例后,可以给这个实例绑定任何属性和方法,这是动态语言的灵活性。
比如我们定义了一个Phone类:
1 | class Phone(object): |
我们创建一个实例,然后给它绑定新的属性和方法:
1 | p = Phone() |
这里要注意,给实例绑定的方法和属性只对这个实例有用,对其他实例不起作用。
有些时候我们想限制实例绑定的属性该咋办捏?比如我只允许Phone的实例拥有brand和color属性。
Python允许我们定义class的时候定义一个特殊的__slots__
变量,来限制该class实例能添加的属性:
1 | class Phone(object): |
运行后报错AttributeError: 'Phone' object has no attribute 'name'
。
__slots__
定义的属性仅对当前类实例起作用,对子类不起作用。
除非在子类中也定义__slots__
,这样,子类实例允许定义的属性就是自身的__slots__
加上父类的__slots__
。
使用@property
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是没办法进行参数检查。 比如在设置手机颜色的时候,只能设置红、蓝、白三种颜色。可以通过增加方法来检查:
1 | class Phone(object): |
但是调用方法的方式显得比较繁琐。不如直接写属性方式简单直接。对于追求完美的pythoner来讲得两者兼顾才爽。
还记得之前讲的装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。
Python内置的@property
装饰器就是负责把一个方法变成属性调用的:
1 | class Phone(object): |
@property
的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property
就可以了,
此时@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter方法变成属性赋值,
于是,我们就拥有一个可控的属性操作。还有一点要注意是两个方法的名称就是属性名,要统一。
@property
广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,
这样,程序运行时就减少了出错的可能性。