面向对象高级编程
来源:互联网 发布:网络机顶盒怎么看直播 编辑:程序博客网 时间:2024/04/29 17:00
面向对象高级编程
使用__slots__
当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性
class Student(object): pass
尝试给实例绑定一个属性:
class Student(object): passs = Student()s.name = "csx"print s.name# 输出:csx
还可以尝试给实例绑定一个方法:
# coding=utf-8class Student(object): passs = Student()s.name = "csx"print s.name# 定义一个方法作为实例方法def set_age(self, age): self.age = agefrom types import MethodType# 给实例绑定一个方法s.set_age = MethodType(set_age, s, Student)s.set_age(25)print s.age
但是,给一个实例绑定的方法,对另一个实例是不起作用的:
为了给所有实例都绑定方法,可以给class绑定方法:
Student.set_score = MethodType(set_score, None, Student)
- 使用__slots__
如果我们想要限制class的属性怎么办?比如,只允许对Student实例添加name和age属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class能添加的属性:
# coding=utf-8class student(object): __slots__ = ("name", "age")s = student()s.name = "csx"s.age = 13s.score = 90"""Traceback (most recent call last): File "G:/python/day2/slot.py", line 9, in <module> s.score = 90AttributeError: 'student' object has no attribute 'score'"""
使用@property
封装属性时,同时进行参数检查
# coding=utf-8class student(object): def get_score(self): return self._score def set_score(self,score): if not isinstance(score,int): raise ValueError('score must be an integer!') if score < 0 or score > 100: raise ValueError('score must between 0 ~ 100!') self._score = scores = student()s.set_score(70)print s.get_score()# 输出:70s.set_score("csx")print s.get_score()"""Traceback (most recent call last): File "G:/python/day2/slot.py", line 16, in <module> s.set_score("csx") File "G:/python/day2/slot.py", line 7, in set_score raise ValueError('score must be an integer!')ValueError: score must be an integer!"""
上面的调用方法又略显复杂,没有直接用属性这么直接简单。
还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:
class Student(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 0 ~ 100!') self._score = values = Student()s.score = 90print s.score# 输出:90
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
多重继承
实例
class Mammal(Animal): passclass Runnable(object): def run(self): print('Running...')class Flyable(object): def fly(self): print('Flying...') # 多重继承class Dog(Mammal, Runnable): pass
Mixin
在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为Mixin。
Mixin的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个Mixin的功能,而不是设计多层次的复杂的继承关系。
定制类
__str__
类似java中的toString,输出默认的打印信息
__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。
__iter__
如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
我们以斐波那契数列为例,写一个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 > 100000: # 退出循环的条件 raise StopIteration(); return self.a # 返回下一个值
__getitem__
像list那样按照下标取出元素,需要实现__getitem__()方法:
class Fib(object): def __getitem__(self, n): a, b = 1, 1 for x in range(n): a, b = b, a + b return a
__getattr__
解决,调用不存在属性时,调用出错的问题
class Student(object): def __init__(self): self.name = 'Michael' def __getattr__(self, attr): if attr=='score': return 99s = Student()s.score# 输出:99
当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性,
__call__
一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。能不能直接在实例本身上调用呢?类似instance()?在Python中,答案是肯定的。
任何类,只需要定义一个__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()# 输出:My name is Michael.
call()还可以定义参数。对实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象,因为这两者之间本来就没啥根本的区别。
通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。
使用元类
type()动态创建类
type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义:
def fn(self, name='world'): # 先定义函数 print('Hello, %s.' % name)Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
- 要创建一个class对象,type()函数依次传入3个参数:
- class的名称;
- 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
- class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
metaclass
除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。
metaclass,直译为元类,简单的解释就是:
当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。
但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。
连接起来就是:先定义metaclass,就可以创建类,最后创建实例。
所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。
metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。
我们先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法:
定义ListMetaclass,按照默认习惯,metaclass的类名总是以Metaclass结尾,以便清楚地表示这是一个metaclass:
# metaclass是创建类,所以必须从`type`类型派生: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 # 指示使用ListMetaclass来定制类
当我们写下__metaclass__ = ListMetaclass语句时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.new()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。
- __new__()方法接收到的参数依次是:
- 当前准备创建的类的对象;
- 类的名字;
- 类继承的父类集合;
- 类的方法集合。
- 面向对象高级编程
- 面向对象高级编程
- 面向对象高级编程
- python 面向对象高级编程
- 面向对象的高级编程
- Python面向对象高级编程
- python面向对象高级编程
- python 面向对象高级编程
- Python06_面向对象高级编程
- python-面向对象高级编程
- 8面向对象高级编程--->高级概念
- PHP面向对象编程 面向对象的高级实践
- python之面向对象高级编程
- Python学习----面向对象高级编程
- js面向对象编程-高级内容
- 面向对象和高级编程 20151212
- C++面向对象高级编程(上)-Geekband
- JavaScript面向对象编程高级1
- Java学习之文件传输基础---Java IO流
- Linux下解决no jdk found问题
- 全概率公式与贝叶斯公式
- 安装linux系统过程中值得记录的内容
- 定时器和延迟
- 面向对象高级编程
- 想不通HTTPS如何校验证书合法性来看
- Windows中的句柄
- 入驻CSDN
- redis学习之redis的主从复制
- kali linux 使用privoxy与XX-net代理终端
- 使用javascript控制密码框获取焦点时文字消失,失去焦点时文字出现
- D3.js学习04_enter,update,exit
- Java:jdbc连接数据库插入中文数据乱码问题