面向对象高级编程(__slots__ @property 多重继承 定制类 使用枚举类 使用元类)
2017-09-13 15:57
686 查看
数据封装、继承和多态只是面向对象程序设计中最基础的3个概念。在Python中,面向对象还有很多高级特性,允许我们写出非常强大的功能。
Python允许在定义class的时候,定义一个特殊的 _ slots _ (注意前后都有两个_)变量,来限制该class实例能添加的属性。
_ slots _定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
在子类中也定义 _ slots _ ,这样,子类实例允许定义的属性就是自身的 _ slots _ 再加上父类的_ slots _。
属性一般通过getter和serter方法封装。
@property 装饰器下的是getter方法;属性.setter下的是serter方法。只有一个@property则表示只读。
这种设计通常称之为MixIn。
MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。
由于Python允许使用多重继承,因此,MixIn就是一种常见的设计。只允许单一继承的语言(如Java)不能使用MixIn的设计。
举个栗子:第一个继承是生父,后边的都是继父。所以,父类有重复地方,首先继承生父的!
类继承关系:
_ str _ 直接显示变量。
当直接打印变量不用print的时候,直接显示变量调用的不是str(),而是repr(),两者的区别是str()返回用户看到的字符串,而repr()返回程序开发者看到的字符串,也就是说,repr()是为调试服务的。
_ iter_ 。
如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
3._ getitem_
要表现得像list那样按照下标取出元素,需要实现_ getitem_()方法。
a. _ getitem_()传入的参数可能是一个int,也可能是一个切片对象slice,所以做切片操作前要做判断。
b. 如果把对象看成dict,_ getitem_()的参数也可能是一个可以作key的object,例如str。
c.与之对应的是_ setitem_()方法,把对象视作list或dict来对集合赋值。最后,还有一个_ delitem_()方法,用于删除某个元素。
4._ getattr_(动态返回一个属性)
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。要避免这个错误,除了可以加上一个属性外,Python还有另一个机制,那就是写一个__
getattr__()方法,动态返回一个属性。
只有在没有找到属性的情况下,才调用_ getattr_,已有的属性,比如name,不会在_ getattr_中查找。
调用不存在的定义的属性会返回None,因为_ getattr_默认返回是None。要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误。
5._ call_() 可以定义参数。
能被调用的对象就是一个Callable对象,比如函数和我们定义的带有call()的类实例。通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类。
alue属性则是自动赋给成员的int常量,默认从1开始计数。
@unique装饰器可以帮助我们检查保证没有重复值。
可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
type()
type()函数可以查看一个类型或变量的类型。
type()函数可以查看一个类型或变量的类型,type()函数既可以返回一个对象的类型,又可以创建出新的类型。
要创建一个class对象,type()函数依次传入3个参数:
class的名称;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
class的方法名称与函数绑定。
通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。
metaclass(元类)
控制类的创建行为,可以把类看成是metaclass创建出来的“实例”。
基本用不到,用到再百度吧。。。
学习网站:www.liaoxuefeng.com
slots
限制实例能添加的属性。Python允许在定义class的时候,定义一个特殊的 _ slots _ (注意前后都有两个_)变量,来限制该class实例能添加的属性。
_ slots _定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
在子类中也定义 _ slots _ ,这样,子类实例允许定义的属性就是自身的 _ slots _ 再加上父类的_ slots _。
@property
@property装饰器就是负责把一个方法变成属性调用。属性一般通过getter和serter方法封装。
@property 装饰器下的是getter方法;属性.setter下的是serter方法。只有一个@property则表示只读。
多重继承
通过继承,子类可以扩展父类的功能。要加入额外的功能,通过多重继承就可以实现。这种设计通常称之为MixIn。
MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。
由于Python允许使用多重继承,因此,MixIn就是一种常见的设计。只允许单一继承的语言(如Java)不能使用MixIn的设计。
举个栗子:第一个继承是生父,后边的都是继父。所以,父类有重复地方,首先继承生父的!
类继承关系:
现在python3已经都是新式类了,就讲下新式类的继承 class D(object): pass class E(object): pass class F(object): pass class C(D, F): pass class B(E, D): pass class A(B, C): pass 比如说这么一个多重继承,那么继承顺序就是,A-B-E-C-D-F
定制类
这种形如_ xxx_的变量或者函数名,这样有特殊用途的函数,可以帮助我们定制类。_ str _ 直接显示变量。
当直接打印变量不用print的时候,直接显示变量调用的不是str(),而是repr(),两者的区别是str()返回用户看到的字符串,而repr()返回程序开发者看到的字符串,也就是说,repr()是为调试服务的。
_ iter_ 。
如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
#以斐波那契数列为例, aa27 写一个Fib类,可以作用于for循环 class fib(object): def __init__(self): self.a,self.b = 0,1 #初始化连个计数器a,b def __iter__(self): return self #本身就是迭代对象,故返回自己 def __next__(self): self.a ,self.b = self.b ,self.a +self.b #返回下一个值 if self.a >100: ##退出循环条件 raise StopIteration() return self.a for n in fib(): print(n)
3._ getitem_
要表现得像list那样按照下标取出元素,需要实现_ getitem_()方法。
a. _ getitem_()传入的参数可能是一个int,也可能是一个切片对象slice,所以做切片操作前要做判断。
b. 如果把对象看成dict,_ getitem_()的参数也可能是一个可以作key的object,例如str。
c.与之对应的是_ setitem_()方法,把对象视作list或dict来对集合赋值。最后,还有一个_ delitem_()方法,用于删除某个元素。
4._ getattr_(动态返回一个属性)
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。要避免这个错误,除了可以加上一个属性外,Python还有另一个机制,那就是写一个__
getattr__()方法,动态返回一个属性。
class Student(object): def __init__(self): self.name = 'Michael' def __getattr__(self, attr): if attr=='score': return 99
只有在没有找到属性的情况下,才调用_ getattr_,已有的属性,比如name,不会在_ getattr_中查找。
调用不存在的定义的属性会返回None,因为_ getattr_默认返回是None。要让class只响应特定的几个属性,我们就要按照约定,抛出AttributeError的错误。
5._ call_() 可以定义参数。
能被调用的对象就是一个Callable对象,比如函数和我们定义的带有call()的类实例。通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类。
枚举类
Enum可以把一组相关常量定义在一个class中,且class不可变,而且成员可以直接比较。定义常量时,使用枚举类可以使每个常量都是class的一个唯一实例。alue属性则是自动赋给成员的int常量,默认从1开始计数。
@unique装饰器可以帮助我们检查保证没有重复值。
可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
from enum import Enum, unique @unique #保证元素不重复 class weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 print(weekday.Sun) print(weekday(2))
元类
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。type()
type()函数可以查看一个类型或变量的类型。
type()函数可以查看一个类型或变量的类型,type()函数既可以返回一个对象的类型,又可以创建出新的类型。
要创建一个class对象,type()函数依次传入3个参数:
class的名称;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
class的方法名称与函数绑定。
通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。
metaclass(元类)
控制类的创建行为,可以把类看成是metaclass创建出来的“实例”。
基本用不到,用到再百度吧。。。
学习网站:www.liaoxuefeng.com
相关文章推荐
- 【Python】[面向对象高级编程] 多成继承,定制类,使用枚举
- 初学Python的学习笔记9----面向对象编程(获取对象信息、实例属性和类属性)、面向对象高级编程(使用__slots__、使用@property)
- 【Python】[面向对象高级编程] 使用__slots__,使用@property
- Python 面向对象高级编程――使用__slots__
- 【Python】__slots__ 、@property、多重继承、定制类、枚举类、元类
- 面向对象高级编程(2)-使用@property
- 【Python】学习笔记——-8.1、面向对象高级编程:1.使用__slots__
- 【Python】学习笔记——-8.2、面向对象高级编程:2.使用@property
- python——(面向对象高级编程)使用@property
- 面向对象高级编程(5)-使用元类
- Python 面向对象高级编程――使用枚举和元类
- 面向对象高级编程——使用__slots__
- 面向对象高级编程——使用@property
- 面向对象高级编程(1)-使用__slots__
- Python 面向对象高级编程――使用@property
- 【Python】学习笔记——-8.5、面向对象高级编程:5.使用枚举类
- 【Python】学习笔记——-8.6、面向对象高级编程:6.使用元类
- 面向对象高级编程—使用___slots__
- python——(面向对象高级编程)使用__slots__
- Python面向对象高级编程:@property--把方法变为属性