原创:叫我詹躲躲
来源:掘金
连接:python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)
致谢:感谢求知教育提供的视频教程python
## 封装,继承和多态
## 1.封装 1、知足把内容封装到某个地方,另外一个地方去调用封装的内容 2、使用初始化构造方法,或者使用self获取封装的内容 ## 2.继承 子类继承父类的属性和内容 复制代码
class Animal:
def eat(self): print('吃饭了') pass def drink(self): print('喝水了') pass class Dog(Animal): def wwj(self): ## 子类独有的实现 print('小狗汪汪叫') pass class Cat(Animal): def mmj(self): ## 子类独有的实现 print('小猫喵喵叫') pass d1 = Dog() d1.eat() d2 = Cat() d2.eat() ## 总结:因此对于面向对象的继承来讲,能够极大的提高效率,减小重复代码 复制代码
class Shenxian:
def fly(self): print('神仙会飞') pass class Monkey: def chitao(self): print('猴子喜欢吃桃') pass class Sunwukong(Shenxian,Monkey): pass swk = Sunwukong() swk.fly() swk.chitao() 复制代码
## 多个父类存在相同的方法,该调用哪个
class D(object): def eat(self): print('D.eat') pass class C(object): def eat(self): print('C.eat') pass class B(D): pass class A(B,C): pass a = A() a.eat print(A.__mro__) ##显示类的继承顺序 <class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class 'object'> ## 执行顺序应该是 去A里面查找,找第一个父类,A中没有的话,去B中查找,,B类中没有,C类中没有,去D类中查找; 复制代码
class Grandfather():
def eat(self): print('吃的方法') pass pass class Father(Grandfather): pass class Son(Father): pass son = Son() print(Son.__mro__) ## <class '__main__.Son'>, ## <class '__main__.Father'>, ## <class '__main__.Grandfather'>, ## <class 'object'> 复制代码
class Grandfather():
def eat(self): print('吃的方法') pass pass class Father(Grandfather): ## 覆盖了父类的方法 def eat(self): print('爸爸常常吃海鲜') pass class Son(Father): pass son = Son() print(Son.__mro__) ## 定义跟父类相同的方法,能够实现覆盖和重写父类的方法 复制代码
class Grandfather():
def __init__(self,name): self.name = name pass def eat(self): print('吃的方法') pass pass class Father(Grandfather): def __init__(self): pass ## 覆盖了父类的方法 def eat(self): print('爸爸常常吃海鲜') pass class Son(Father): pass son = Son() print(Son.__mro__) 复制代码
class Father:
def __init__(self,name): self.name = name pass ## 覆盖了父类的方法 def eat(self): print('爸爸常常吃海鲜') pass class Son(Father): def __init__(self,name): Father.__init__(self,name) ##调用父类的方法,能够具有name属性 ## 或者 ## super.__init__(name) ##也能够这样写 self.age = 90 ## 添加新的实例方法 self.sex = '男' pass pass son = Son('hello') 复制代码
class Father:
def __init__(self,name): self.name = name pass ## 覆盖了父类的方法 def eat(self): print('父类的吃方法') pass class Son(Father): def __init__(self,name): Father.__init__(self,name) ##调用父类的方法,能够具有name属性 ## 或者 ## super.__init__(name) ##也能够这样写 self.age = 90 ## 添加新的实例方法 self.sex = '男' pass pass def __str__(self): print('{}'.format(self.name)) pass def eat(self): super().eat() ##调用父类的方法 print('子类的吃方法') pass son = Son('詹躲躲') son.eat() ## 父类的吃方法 ## 子类的吃方法 复制代码
同一种行为,对于不一样子类【对象】有不一样的实现方式web
“1.继承:发生在父类和子类之间数据库
2.重写:子类重写父类的方法编程
3.1 案例演示编辑器
class Animal:
## 基本类 def say(self): print('动物类') pass pass class Duck(Animal): ## 子类 派生类 def say(self): print('鸭子类') pass pass class Dog(Animal): ## 子类 派生类 def say(self): print('小狗类') pass pass ## duck1 = Duck() ## duck1.say() ## dog = Dog() ## dog.say() def commonIvoke(obj): ## 统一调用 obj.say() ## 循环统一调用 listObj = [Duck(),Dog()] for item in listObj: commonIvoke(item) ## 在定义时的类型跟调用时不同的时候,称为多态。 复制代码
1.增长程序的灵活性ide
2.增长程序的扩展性函数
## 类属性:就是类对象拥有的属性,它被全部类对象的实例对象所共有,类对象和实例对象能够访问。
## 实例属性:实例对象所拥有的属性,只能经过实例对象访问。 class Student: ## 类属性 name = '叫我詹躲躲' def __init__(self,age): self.age = age pass pass lm = Student(18) ## 经过实例对象去访问类属性 print(lm.name) print(lm.age) ## 经过类对象去访问 print(Student.name) print(Student.age) ## 总结 ## 类属性:类对象和实例对象均可以访问 ## 实例属性:只能由实例属性访问 ## 全部的实例对象指向同一类对象 ## 实例对象去修改类属性 不能修改 ## 类对象能够修改类属性 能够修改 复制代码
## 装饰器@classmethod
class Person: country = 'china' ## 类方法 用classmethod修饰 @classmethod def get_country(cls): return cls.country ## 访问类属性 pass @classmethod def change_country(cls): cls.country = 'America' pass ## 经过类对象去引用 print(Person.get_country()) print(Person.change_country()) print(Person.get_country()) 复制代码
class Person:
country = 'china' ## 类方法 用classmethod修饰 @classmethod def get_country(cls): return cls.country ## 访问类属性 pass @classmethod def change_country(cls): cls.country = 'America' pass @staticmethod def get_data(): return Person.country pass ## 经过类对象去引用 print(Person.get_country()) print(Person.change_country()) print(Person.get_country()) print(Person.get_data()) 复制代码
通常不会经过是实例对象去访问静态方法post
因为静态方法主要存放逻辑方法,自己与类以及实例没有交互,也就是不会涉及类中方法和属性的操做网站
根据资源可以有效的利用spa
import time
class sys_time: def __init__(self,hour,min,second): self.hour = hour self.min =min self.second = second @staticmethod ## 独立的功能 def show_time(): return time.strftime('%H:%M:%S',time.localtime()) print(sys_time.show_time()) ## 15:15:44 复制代码
1.类方法的第一个参数是类对象,cls进而去引用类对象的属性和方法
2.实例方法的第一个参数是实例属性,若存在相同的实例属性或者方法,实例属性优先级最高
3.静态方法不须要额外的参数,若须要引用属性。,则能够经过类对象或者实例对象去引用便可,必须使用装饰器@staticmethod装饰
## 私有属性 以__开头,声明为属性私有,不能在类的外部被使用或者直接访问。
class Person(object): def __init__(self): self.__name = '叫我詹躲躲' ## 私有化 self.age = '21' pass def __str__(self): return '{}的年龄是{}'.format(self.__name,self.age) person = Person() ## print(person.__name) ##报错 print(person) ##能够访问 ## 叫我詹躲躲的年龄是21 ## 私有属性,不能被子类继承 复制代码
class A(object):
def __eat(self): print('吃饭') pass pass def run(self): print('跑步') pass pass b = A() b.__eat() ## 报错 b.run() ## 跑步 复制代码
属性函数
class A(object):
def __init__(self): self.__name = 18 def __eat(self): return self.__name pass pass def run(self): print('跑步') pass pass age = property(__eat, run) b = A() print(b.age) ## 报错 b.run() ## 跑步 复制代码
class A(object):
def __init__(self): self.__name = 18 def __eat(self): return self.__name pass pass def run(self): print('跑步') pass @property ##添加属性标识 def age(self): return self.__name pass @age.setter ##修改属性 def age(self,params): self.age = params pass pass p1 = A() print(p1.age) ## 18 p1.age = 16 print(p1.age) 复制代码
做用:建立并返回一个实例对象,若是__new__只调用了一次,就会获得一个对象。继承自object的新式类,才有new这一魔术方法。
1.__new__是一个实例化调用的第一个方法
2.__new__至少必须有一个参数 cls,表明要实例化的类,此参数在实例化时由python解释器提供,其余的参数是直接传递给__init__方法 3.__new__决定是否使用该__init__方法,由于__new__能够调用其余的类的构造方法或者返回实例对象做为类的实例,若是__new__没有返回实例,则__init__不会被调用 4.在__init__方法中,不能调用本身的__new__方法,return cls__new__(cls),不然会报错。 复制代码
class A(object):
def __init__(self): print('__init__执行了') pass pass def __new__(cls,*args,**kwargs): return super().__new__(cls,*args,**kwargs) pass pass a = A() print(a) __init__执行了 <__main__.A object at 0x00000291F97D5160> ## 当__new__返回的时候 __init__才会显示 复制代码
class DataBaseClass(object):
def __new__(cls,*args,**kwargs): ## cls._instance = cls.__new__(cls) ##不能使用本身的new方法 if not hasattr(cls,'_instance'): cls._instance = super().__new__(cls,*args,**kwargs) return cls._instance pass pass db1 = DataBaseClass() db2 = DataBaseClass() db3 = DataBaseClass() print(id(db1)) print(id(db2)) print(id(db3)) ## 三个指向的内存地址都同样的 ## 1852298514784 ## 1852298514784 ## 1852298514784 复制代码
try:
## 可能出现错误的代码块 except: ## 出错以后执行的代码块 else: ## 没有出错的代码块 finally: ## 无论有没有出错,都会执行 复制代码
try:
## 可能出现错误的代码块 li = [1,2,3] ## print(li[10]) print(1/0) except IndexError as msg: ## 出错以后执行的代码块 print(msg) except ZeroDivisionError as msg: ## 出错以后执行的代码块 print(msg) else: ## 没有出错的代码块 print('没有出错了') finally: ## 无论有没有出错,都会执行 print('出错了') ## 用一个try能够捕获多个不一样类型的异常 复制代码
try:
print(b) except Exception as result: print(result) else: print('出错了') finally: print('出错了') 复制代码
def A(s):
return s/int(s) pass def B(s): return A(s)/2 pass def main(): try: B(0) except Exception as result: print(result) main() 复制代码
在合适的位置进行错误捕获
division by zero
1、解释器会查找相应的异常捕获类型
2、不断传递给上层,没有找到异常处理,会退出 复制代码
class ToolongException(Exception):
def __init__(self, len): self.len = len def __str__(self): return '输入的长度是'+str(self.len)+'长度,超出长度了' def name_test(): name = input('输入名字') try: if len(name)>5: raise ToolongException(len(name)) else: print(name) except ToolongException as result: print(result) else: print('没有出错了') name_test() ##输入的长度是13长度,超出长度了 复制代码
import types class Student: def __init__(self, name, age): self.name = name self.age = age pass pass def __str__(self): return '{}今天{}岁了'.format(self.name, self.age) pass pass zhz = Student('詹躲躲', 25) zhz.wight = 60 def dymicMethod(self): print('{}体重是{}'.format(self.name,self.wight)) pass ## 动态添加属性 print(zhz.wight) ## 类添加属性 Student.pro = '计算机科学' ## 实例能够访问 print(zhz.pro) ## 动态添加实例方法 ## import types zhz.printInfo = types.MethodType(dymicMethod,zhz) zhz.printInfo() ## 詹躲躲体重是60 复制代码
import types
class Student: def __init__(self, name, age): self.name = name self.age = age pass pass def __str__(self): return '{}今天{}岁了'.format(self.name, self.age) pass pass zhz = Student('詹躲躲', 25) zhz.wight = 60 def dymicMethod(self): print('{}体重是{}'.format(self.name,self.wight)) pass ## 动态绑定类方法 @classmethod def classTest(cls): print('类方法') pass ## 动态绑定静态方法 @staticmethod def staticTest(): print('静态方法') pass 复制代码
print(zhz.wight)
复制代码
Student.pro = '计算机科学'
## 实例能够访问 print(zhz.pro) 复制代码
## import types
zhz.printInfo = types.MethodType(dymicMethod,zhz) zhz.printInfo() 复制代码
Student.testMethod = classTest Student.testMethod() 复制代码
zhz.testMethod()
复制代码
Student.statictest = staticTest Student.statictest() 复制代码
zhz.statictest()
复制代码
class Student(object):
__slots__ = ('name', 'age', 'score') def __str__(self): return "{},{}".format(self.name, self.age) xw = Student() xw.name = '叫我詹躲躲' xw.age = 25 ## print(xw.__dict__) ## {'name': '叫我詹躲躲', 'age': 25} xw.s11 = '1212' #### 报错 print(xw) 复制代码
子类未声明 slots,不会继承父类的__slots__,此时子类能够随意的属性赋值
子类声明了,范围为 子类+父类的范围
用来建立实例对象,只有继承了object的话,才有这个方法。
要求一个类有且只有一个实例,而且提供了全局的访问点。日志插入logger,网站计数器,权限验证模块,window资源管理器,系统回收站,数据库链接池
不能的
程序在执行中出现的异常。
分别根据异常的类型去处理
## try:
## 正常操做 ## except: ## ##.... ## else: ## ##.... ## finally: ## ##... 复制代码
限制属性的随意输入,节省内存空间
保护数据,封装性的体现
不能够直接修改,经过方法去实现,能够借助property
对属性进行私有化
提供获取用户信息的函数,提供设置私有属性的方法,设置年龄在0-120岁中间,若是不在这个范围,不能设置成功
class Person:
def __init__(self,name,age): self.__name = name self.__age = age pass pass def GetUserInfo(self): return "{}的年龄为{}".format(self.__name,self.__age) pass pass def __str__(self): return "{}的年龄为{}".format(self.__name,self.__age) def setAge(self,age): if age>0 and age<120: self.__age = age else: pass person = Person('詹躲躲',19) print(person.GetUserInfo()) ## 詹躲躲的年龄为19 print(person.setAge(30)) print(person.GetUserInfo()) ## 詹躲躲的年龄为30 复制代码
class DataBaseClass(object):
def __new__(cls,*args,**kwargs): ## cls._instance = cls.__new__(cls) ##不能使用本身的new方法 if not hasattr(cls,'_instance'): cls._instance = super().__new__(cls,*args,**kwargs) return cls._instance pass pass db1 = DataBaseClass() db2 = DataBaseClass() db3 = DataBaseClass() print(id(db1)) print(id(db2)) print(id(db3)) 复制代码
class Student:
def __init__(self, name, score): self.__name = name self.___score = score @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name def __str__(self): return self def __call__(self, *args, **kwargs): print(self.name) pass pass xm = Student('詹躲躲',98) xm.__call__() xm.name() 复制代码
import types
class Animal: pass def run(self): print('小猫') cat = Animal() cat.run = types.MethodType(run,cat) cat.run() Animal.color = 'red' print(cat.color) def info(): print('ok') Animal.info = info Animal.info() 复制代码