python笔记之面向对象
python是面向对象语言,因此它具有面向对象封装、继承、多态等特点。
面向对象思想:以模块化思想解决工程上的问题。
常用名称:
OO:面向对象
OOA:分析
OOD:设计
OOP:编程
OOI:实现
面向对象三大特征:
1.封装:对对象的访问成员进行限制
封装三个级别:
公开:public :对成员没有任何操作,所有地方都可以访问
受保护的:protected ,将对象成员进行一定级别的封装,在类中和子类中可以进行访问,但是外部不可以(以_开头,一个下划线开头)
私有的:private ,私有成员是最高的封装,只能在当前类或对象中访问 (以__开头,两个下划线开头),python类私有不是真私有,是一种name manglilng改名技术,可以使用对 象.__classname__.atrributename访问
public、protected、private 不是关键字
判别对象的位置:
对象内部
对象外部
子类中
2.继承:子类可以使用父类定义的内容或者行为。python中子类可以有多个父类,新式类(继承object):继承是广度优先BFS;经典类:继承是深度优先DFS
封装作用:减少代码,增加代码复用性,同时可以直接定义类与类直接关系
继承与被继承概念:
被继承类叫父类、也叫基类、也叫超类
继承类叫子类、也叫派生类
继承与被继承一定存在一个is-a关系
继承特征:
子类继承父类,可以使用父类中所有的内容
子类继承父类后,并没有将父类中所有的成员复制到子类中,而是通过引用关系访问调用
子类可以定义自己方法和属性,且优先使用自己成员
子类想扩充父类中方法,可以定义新方法的同时引用父类方法,使用 父类名.父类成员(如:Person().work(self)) ,也可以使用 super().父类成员(如:super().work())格式调用
3.多态:同一个对象在不同情况下有不同的状态。
python中多态是一种思想,不是一种语法 (java中多态是一种语法,多态就是方法名一样,参数不一样),python中不支持这种写法
多态:一种调用方式,不同的执行结果
多态:同一事物的多种形态
简单了解下面向对象术语
类:具有相同属性和方法的对象的集合(抽象,描述一个集合,侧重于共性),对象是实例化后的类(具享,描述是一个个体)。
方法:类中定义的函数,使用def定义,同时参数里面默认要带上self
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
python中定义类格式如下:
class ClassName():
def 方法名(self):
pass
类名一般建议使用驼峰命名方式,即:每个单词首字母大写。
#property 案例 # 定义一个Person类,具有name,age属性 # 对于任意输入的名字,希望使用大写保存 # 年龄统一用整数保存 # x = property(fget, fset ,fdel, doc) class Person(): def fget(self): #函数名称可以任意 return self._name def fset(self, name): self._name = name.upper() def fdel(self): self._name = "NONAME" name = property(fget, fset, fdel, "对name进行操作啦") if __name__ == '__main__': p = Person() p.name = "dddee" print(p.name)
1 class Person(object): 2 name1 = 'admin' #name1类变量 3 __age = '18' #私有变量,以__开头,私有属性在类外部无法直接进行访问 4 def __init__(self,age,sex): #age sex为实例变量 5 self.name = self.name1 6 self.age = age 7 self.sex = sex 8 9 def info(self): 10 print('你的名字是{0},年龄{1}岁,性别是{2}'.format(self.name,self.age,self.sex)) 11 12 if __name__ == '__main__': 13 p = Person('20','男') 14 p.info()
python继承,允许同时继承多个父类,在调用方法时,先寻找子类如果没有则寻找父类从左到右,再从下到上找
1 class Person(): 2 def __init__(self,name): 3 self.name = name 4 5 def show(self): 6 print('你的名字是{0}'.format(self.name)) 7 8 def aa(self): 9 print('我是父类Person') 10 11 class PA(): 12 def __init__(self,name): 13 self.name = name 14 15 def show(self): 16 print('PA:你的名字是{0}'.format(self.name)) 17 18 def aa(self): 19 print('我是父类PA') 20 21 def bb(self): 22 print('我是类PA中的bb方法') 23 24 class PsersonA(Person): 25 def __init__(self,name,age): 26 Person.__init__(self,name) 27 self.age = age 28 # 29 # def show(self): 30 # print('你的名字是{0},年龄{1}岁'.format(self.name, self.age)) 31 32 class PsersonB(PA): 33 def __init__(self,name,sex): 34 super(PsersonB,self).__init__(name) 35 self.sex = sex 36 37 def show(self): 38 print('你的名字是{0},性别是{1}'.format(self.name, self.sex)) 39 40 def info(self): 41 print('我是类PsersonB') 42 43 class C(PsersonA,PsersonB): 44 def __init__(self,name,age,sex): 45 PsersonA.__init__(self,name,age) 46 PsersonB.__init__(self, name, sex) 47 48 def info(self): 49 print('我是子类C') 50 print(issubclass(PersonA,C)) #判断C是否是PersonA子类 51 52 if __name__ == '__main__': 53 p = C('ADMIN','20','男') 54 p.info() #子类与父类存在相同方法,优先使用子类 55 p.show() #子类方法不存在,则从父类中寻找,顺序 从左到右,从下到上,就先寻找第一个父类,如果没有继续找第一个父类的父类,如果还没有找第二个父类 56 p.aa() #方法aa,C类中没有,找第一个父类 PsersonA 中也没有,找 PsersonA 的父类 Person 有方法aa 57 p.bb()
类的魔术方法:
class BB(): def __init__(self, name): self.name = name def __str__(self): return self.name def __gt__(self, obj): print("哈哈,{0}会比{1}大吗?".format(self,obj)) return self.name>obj.name
1 class P(): 2 '''类描述信息嘀嗒''' 3 def __init__(self): 4 print('我是构造函数,在生成对象时时执行') 5 6 def __del__(self): 7 print('我是虚构函数,最后执行') 8 9 def info(self): 10 print('个人信息') 11 12 def __call__(self, *args, **kwargs): 13 print('对象后面(),触发调用') 14 self.info() 15 16 def __str__(self): 17 return '改变对象字符串显示' 18 19 if __name__ == '__main__': 20 obj = P() 21 print(obj()) 22 print(obj.__doc__) 23 print(obj) 24
鸭子类型
class A(): name = 'yaona' age = 18 def __init__(self): self.name = "aaa" self.age = 17 def say(self): print(self.name) print(self.age) class B(): name = "bbbb" age = 19 dd = 33 a = A() a.say() #对象调用方法,自动将实例对象a当成第一个参数传入 A.say(a) #此时当做self传入 结果为 name = 'aaa' age = 17 A.say(A) #此时A当做self传入 结果为 name = 'yaona' age = 18 #此时传入B类实例,因为B具有name和age属性,所有不会报错 A.say(B) #该代码利用 鸭子类型,具有相同属性
import abc #声明一个类,并且指定当前类的元类 class CC(metaclass=abc.ABCMeta): #定义一个抽象的方法 @abc.abstractmethod def sayhello(self): pass #定义一个类抽象方法 @abc.abstractclassmethod def drink(cls): pass #定义一个静态抽象方法 @abc.abstractstaticmethod def paly(): pass def sleep(): print('Sleep ....')
在类中方法有普通方法、静态方法、特性方法、类方法等
1 class P(object): 2 def info(self): 3 print('我是普通方法') 4 5 @property #加property装饰器,为特性方法,在调用函数时无需加() 6 def info1(self): 7 print('我是特性方法') 8 9 @staticmethod #加staticmethod装饰器,为静态方法,可由类名直接调用 10 def info2(): 11 print('我是静态方法') 12 13 @classmethod #加classmethod装饰器,为静态方法,属于类,可由类直接调用 14 def info3(cls): 15 print('我是类方法') 16 17 18 if __name__ == '__main__': 19 obj = P() 20 obj.info() 21 obj.info1 22 P.info2() 23 P.info3() 24