文章目录
一、面向对象编程
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。把大块函数通过切割成小函数来降低系统的复杂度
面向对象的程序设计把计算机程序视为一组对象的集合,计算机执行的就是一系列消息在各个对象之间传递
面向对象的数据思想是抽象出Class,根据Class创建Instance(实例)
一个Class既包含数据,又包含操作数据的方法
1、类和实例
-
定义类:
class Student(object):
(object)
表示该类从哪个类继承,如果没有合适的继承类,就使用object
类(所有类都会继承的类) -
创建实例:
类名+()
实现:bart = Studen()
通过一个特殊的
__init__
方法,在创建实例的时候就把一些必须的属性加上去def __init__(self,name,score):
__init__
的第一个参数必须是self,表示创建实例的本身,传入参数self
时不需要传 -
数据封装
在类的内部定义访问数据的函数
方法就是与实例绑定的函数,方法可以直接访问数据的实例
2、访问限制
-
设为私有来限制访问
class Student(object): def __init__(self): self.__name =name self.__age = age
-
_name
外部可以直接访问,但按约定,不直接进行访问 -
__name
不能被访问的原因是python解释器对外把__name
变量改为了_Student__name
(不同版本的python改成不同的变量名)
Python本身没有任何机制不阻止你干坏事,一切靠自觉
3、继承和多态
class Dog(Animal):
子类获得父类的全部功能
当子类与父类同时存在相同的方法,子类会覆盖父类的方法
开闭原则:
- 对扩展开发:允许增加新的子类
- 对修改封闭
4、获取对象信息
(1)type()
:查看对象类型,返回对应的class类型
-
基本类型都可以用
type()
判断例:
type(123)
、type('str')
-
判断基本数据类型可以直接写
int
、char
``type(123) == int`
-
-
一个变量指向函数或者类,也可以用
type()
判断例:
type(abs)
、type(a)
-
判断一个对象是否是函数(可以使用type模块中定义的常量)
import types def fn(): pass print(type(fn) == types.FunctionsType) print(type(abs) == types.BuiltFunctionType)
-
(2)isinstance()
:判断一个对象是否是该类型本身或者位于该类型的父继承链上
-
判断继承
如果继承关系为:
object->Animal->Dog
a = Animal() d = Dog() isinstance(d,Dog) isinstance(d,Animal)
-
与
type()
一样判断基本类型isinstance('a',str)
-
判断一个变量是否是某些类型中的一种
isinstance([1,2,3],(list,tuple))
优先使用instance
(3)dir()
:获取对象的所有属性和方法,返回一个包含字符串的list
-
直接操作对象的状态,获得对象的方法
-
获取属性:
getattr()
:getattr(obj,'x')
可以传入default参数,如果参数不存在,返回默认值
getattr(obi,'x',404)
#不存在返回404 -
设置属性:
setattr()
:setattr(obj,'y',19)
-
查看属性:
hasattr()
:hasattr(obj,'y')
-
二、实例属性和类属性
-
实例属性:
实例属性属于各个实例所有,互不干扰
-
类属性:
类本身绑定属性,在class中直接定义属性,类属性属于类所有,所有实例共享一个属性
不要对实例属性和类属性使用相同的名字,实例属性会将类属性屏蔽掉
三、面向对象高级编程
1、使用__slots__
方法
-
给实例绑定方法
def set_age(self,age): #定义一个函数作为实例方法 self.age = age from types import Methodtype s.set_age = MethodType(set_age,s) #给实例绑定一个方法
-
给class绑定方法
def set_score(self,score): self.score = score Student.set_score = set_score
-
**
__slots__
:**限制该实例的能添加的属性class Student(object): __slots__ = ('name','age') #用tuple定义允许绑定的属性名称
__slots__
定义的属性仅对当前类的实例起作用,对继承的子类不起作用想在子类中运用,就需在子类中也定义
__slots__
,子类允许定义的属性就是自身的__slots__
加上父类的__slots__
2、使用@property
-
定义读写属性:定义
getter
和setter
方法class Student(object): @property #getter方法 def birth(self): return self._birth @birth.setter #setter方法 def birth(self,value): self._birth = value
-
定义只读属性:只定义
setter
方法class Student(object): @property def age(self): return 2015-self._birth
3、多重继承
-
MixIn
多重继承:一个子类同时继承多个父类(
class Bat(Mammal,Flyable)
)MixIn
:(mix+in:混入)给一个类增加多个功能(继承多个父类)优先通过多重继承来组合多个
Mixln
的功能
4、定制类
-
__str__
:返回字符串定义
__str__
方法:def __str__(self): return 'Student object (name:%s)' % self.name
直接显示变量调用的不是
__str__()
,而是__repr__()
__str__()
返回用户看到的字符串Student object (name:micle)
__repr__()
返回开发者看到的字符串<__main__.Student object at 0x109afb310>
- 解决办法:
__repr__ = __str__
-
__iter__
:循环类iter:循环
类想被
for...in
循环,就必须实现一个__iter__()
方法,改方法返回一个迭代对象class Fib(object): def __init__(self): self.a,self.b = 0,1 def __iter__(self): return self #实例本身是迭代对象,故返回自己
-
__getitem__
:类按下标访问元素item:
按照下标取出元素:
__getitem__()
class Fib(object): def __getitem__(self,n): a,b=1,1 for x in range(n): a,b = b,a+b return a
对Fib切片会报错,原因是
__getitem__()
传入的可能是一个int,也可能是一个切片对象slice所以需要对传入的参数做判断
if isinstance(n,slice)
-
__getattr__
:避免调用类的方法或属性不存在报错attr:属性
def __getattr__(self,attr) if attr == 'age': return 99 #返回score的值 #return lambda: 25 #也可以返回函数
只有在没有找到属性的情况下,才调用
__getattr__
__getattr__()
默认返回时None
要让class只响应特定的几个属性,就需要抛出
AttributeError
(把一个类的所有属性和方法调用全部动态化处理了) -
__call__
:对实例进行调用class Student(object): def __init__(self,name): self.name = name def __call__(self): print('.....')
__call__()
还可以定义参数:def __call__(self,age)
判断一个对象能否被调用:
能被调用的对象就是一个
Callable
对象:callable(Student())
5、使用枚举类Enum()
-
使用
Enum()
from enum import Enum
for name,member in Month__members__.item(): print(name,'=>',',',member.value)
value
属性则是自动赋值给成员的int
常量,默认从1开始from enum import Enum,unique @nuique class Weekday(Enum)
@unique
装饰器可以保证没有重复值 -
访问枚举类型
- 可以用成员名引用枚举常量(
Weekday.Tue
) - 也可以直接根据value的值获得枚举常量(
Weekday(1)
)
- 可以用成员名引用枚举常量(
6、使用元类metaclass
-
type()
-
查看一个类型或变量的类型
Hello
是一个class,它的类型就是`type``h = Hello()
,h
是一个实例,它的类型就是classHello
-
动态创建新的类型
Hello = type('Hello',(object,),dict(hello=fn))
#创建Hello class要创建一个class对象,
type()
函数依次传入3个参数:- 1、class的名称 #
Hello
- 2、继承的父类集合,继承多重继承,注意tuple的单元素写法 3 #
(object,)
- 3、class的方法与函数绑定 #
decit(hello=fn)
- 1、class的名称 #
-
-
metaclass
:控制类的创建行为-
1、先定义
metaclass
class ListMetaclass(type):
metaclass的类名以Metaclass结尾
metaclass是类的模板,所以必须从type类型派生
-
2、再创建
class
class MyList(list,metaclass=ListMetaclass:
定义类时,需要传入关键字metaclass
-
3、最后创建实例
-