面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。把大块函数通过切割成小函数来降低系统的复杂度
面向对象的程序设计把计算机程序视为一组对象的集合,计算机执行的就是一系列消息在各个对象之间传递
面向对象的数据思想是抽象出Class,根据Class创建Instance(实例)
一个Class既包含数据,又包含操作数据的方法
定义类:
class Student(object):
(object)表示该类从哪个类继承,如果没有合适的继承类,就使用object类(所有类都会继承的类)
创建实例:
类名+()实现:bart = Studen()
通过一个特殊的__init__方法,在创建实例的时候就把一些必须的属性加上去
def __init__(self,name,score):
__init__的第一个参数必须是self,表示创建实例的本身,传入参数self时不需要传
数据封装
在类的内部定义访问数据的函数
方法就是与实例绑定的函数,方法可以直接访问数据的实例
设为私有来限制访问
class Student(object): def __init__(self): self.__name =name self.__age = age_name外部可以直接访问,但按约定,不直接进行访问
__name不能被访问的原因是python解释器对外把__name变量改为了_Student__name(不同版本的python改成不同的变量名)
Python本身没有任何机制不阻止你干坏事,一切靠自觉
class Dog(Animal):
子类获得父类的全部功能
当子类与父类同时存在相同的方法,子类会覆盖父类的方法
开闭原则:
对扩展开发:允许增加新的子类对修改封闭(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中直接定义属性,类属性属于类所有,所有实例共享一个属性
不要对实例属性和类属性使用相同的名字,实例属性会将类属性屏蔽掉
给实例绑定方法
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__
定义读写属性:定义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._birthMixIn
多重继承:一个子类同时继承多个父类(class Bat(Mammal,Flyable))
MixIn:(mix+in:混入)给一个类增加多个功能(继承多个父类)
优先通过多重继承来组合多个Mixln的功能
__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())
Python的官方文档
使用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))type()
查看一个类型或变量的类型
Hello是一个class,它的类型就是`type``
h = Hello(),h是一个实例,它的类型就是classHello
动态创建新的类型
Hello = type('Hello',(object,),dict(hello=fn)) #创建Hello class
要创建一个class对象,type()函数依次传入3个参数:
1、class的名称 #Hello2、继承的父类集合,继承多重继承,注意tuple的单元素写法 3 #(object,)3、class的方法与函数绑定 #decit(hello=fn)metaclass:控制类的创建行为
1、先定义metaclass
class ListMetaclass(type):
metaclass的类名以Metaclass结尾
metaclass是类的模板,所以必须从type类型派生
2、再创建class
class MyList(list,metaclass=ListMetaclass:
定义类时,需要传入关键字metaclass
3、最后创建实例