类的三大特性(继承, 封装, 多态)
Posted zjaiccn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类的三大特性(继承, 封装, 多态)相关的知识,希望对你有一定的参考价值。
类的三大特性之继承
class Animals: a_type = "哺乳动物" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print("%s is eating ...."%self.name) class Person(Animals): a_type = "高级动物" def talk(self): print("person %s is talking..."%self.name) def eat(self): print("person %s is eat zaofan"%self.name) class Pig(Animals): def chase_rabbit(self): print("pig %s chase rabbit..."%self.name) p = Person("Alex",22,"Man") p.talk() p.eat() print(p.a_type) pig = Pig("jack",2,"pig") pig.chase_rabbit() print(pig.a_type)
重写父类方法 - 单继承
# -*- coding:utf-8 -*- class Animals: a_type = "哺乳动物" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print("%s is eating ...."%self.name) class Person(Animals): a_type = "高级动物" def __init__(self,name,age,sex,hobbie): #Animals.__init__(self,name,age,sex) #super(Person,self).__init__(name,age,sex) super().__init__(name,age,sex) self.hobbie = hobbie def talk(self): print("person %s is talking..."%self.name) def eat(self): super().eat() #super继承执行父类的方法 print("person %s is eat zaofan"%self.name) class Pig(Animals): def chase_rabbit(self): print("pig %s chase rabbit..."%self.name) p = Person("Alex",22,"Man","read book") p.talk() p.eat() print(p.a_type,p.hobbie)
类的多继承
按顺序从左到右继承
继承顺序分为两种:这是简单的理解,深度理解完全不是这样的
深度优先:先找M -MB - S -SB
广度优先: 一层一层的找 先M -S - MB -SB
实际上在python3上类的多继承的情况下,使用的是C3算法,既不能说是广度也不能说是深度
Python 中,类有两种写法: 在python 3上默认就是新式类
Class A: #经典类
Class B(object): #新式类
C3算法十分复杂,所以有兴趣去了解
如果想要简单快速的查看一个类的继承方式可以使用:
Print(类名.mro())
# -*- coding:utf-8 -*- class ShenXianBase: def fight(self): print("元祖在打架") class ShenXian(ShenXianBase): def fly(self): print("shenxian is fly") def fight(self): print("神仙在打架") class MonkeyBase: def fight(self): print("猿猴在打击") class Monkey(MonkeyBase): def eat_peach(self): print("monkey like eat taozi ") def fight(self): print("猴子在打击") class Monkeyking(ShenXian,Monkey): def play_goden_stick(self): print("sun wu kong play jinjubang") sxz = Monkeyking() sxz.eat_peach() sxz.fly() sxz.play_goden_stick() sxz.fight() print(Monkeyking.mro())
类的三大特性之--封装 :私有变量都是加两个下划线__
self.__name 将变量变成私有的
方法也可以变成私有的
def __sayhi():
# -*- coding:utf-8 -*- class Person(object): def __init__(self,name,age): self.__name = name self.__age = age def __get_name(self): print("name is %s"%self.__name) p = Person("Alex",22) print(p._Person__name) #强行访问私有变量 p._Person__name = "jack" #强行修改私有变量 p._Person__get_name() #强行访问私有方法
类的三大特性之- 多态
有时一个对象会有多种表现形式,比如网站页面有button按钮,可以有正方形的圆的,方的,但是他们有一个共同的调用方法onClick()
# -*- coding:utf-8 -*- #多态 class Dog(object): def sound(self): print("wang wang wang ...") class Pig(object): def sound(self): print("heng heng heng ...") def animals_sound(obj1): obj1.sound() d = Dog() p = Pig() animals_sound(d) animals_sound(p)
# -*- coding:utf-8 -*- #多态2 class Documents(object): def __init__(self,name): self.name = name def show(self): raise NotImplementedError("Subclass must implement abs") class Pdf(Documents): def show(self): return "show pdf contents" class Word(Documents): def show(self): return "show Word contents" pdf = Pdf("xixixi.pdf") word = Word("yyy.word") obj = [pdf,word] for o in obj: print(o.show()) # 这个show方法就是接口上边的pdf,word就是形态
类方法,静态方法:
类方法:
类方法通过@classmethod装饰器来装饰一下即只能访问类的变量,不能访问实例变量
# -*- coding:utf-8 -*- class Dog(object): name = ‘gouzi‘ def __init__(self,name): self.name = name @classmethod def eat(self): print("dog %s is eating ...."%self.name) d = Dog("mjj") d.eat()
为什么不能访问实例变量,因为传进来的值不是实例本身,而是类本身,加上classmethod方法就会变成这样,去掉classmethod,传进来的就是实例本身了.
作用:
# -*- coding:utf-8 -*- class Stu(object): __stu_num = 0 def __init__(self,name): self.name = name self.add_stu(self) @classmethod def add_stu(cls,obj): if obj.name: cls.__stu_num += 1 print("生成一个新学生",cls.__stu_num)
s = Stu(‘j‘) s2 = Stu(‘k‘) s3 = Stu(‘o‘)
s4 = Stu(‘5‘)
静态方法:
@staticmethod 既不能访问实例变量,又不能访问类变量
静态方法割断了他和类或实例的任何关系
属性方法property
把一个方法变成一个静态的属性
class Stu(object): def __init__(self,name): self.name = name @property def fly(self): print("jack is flying") s = Stu(‘rain‘) s.fly #不需要加括号了,调用这个方法
神奇的反射:
可以通过字符串的形式来操作对象的属性
Getattr 获取
Hsaattr 查询
Setattr 赋值
Delattr 删除
如何反射一个文件下指定的对应的属性
__name__ 在当前文件主动执行的情况下(不是被导入执行),__name__ 就等于 __main__
在被其他文件当模块执行的时候,就等于这个文件(模块)名
# -*- coding:utf-8 -*- class Person(object): def __init__(self,name,age): self.name = name self.age = age def drink(self): print("drink water ...") def talk(self): print("talking...") p = Person(‘alex‘,22) #查询 if hasattr(p,"name"): print("11111") user_command = input(‘>>‘).strip() if hasattr(p,user_command): fun = getattr(p,user_command) fun() #获取 a = getattr(p,"age") print(a) #修改,增加 setattr(p,"sex","Man") print(getattr(p,‘sex‘)) setattr(Person,"speak",talk) p.speak() #删除 delattr(p,"age") if __name__ == "__main__": #只会被在别的模块导入的时候发挥作用 print(‘jaja‘)
#动态获取当前模块下的属性
import sys mod = sys.modules["__main__"] if hasattr(mod,"p"): o = getattr(mod,"p") print(o.drink)
动态加载模块
# -*- coding:utf-8 -*- #动态加载模块 ,热加载,在程序运行中,加入一个模块 #__import__("Property") #解释器用的 import importlib importlib.import_module("Property") #python官方推荐使用的 和上边的效果是一样的 importlib.import_module("function_def.List_builder")
反射的再应用:
#-*- coding:utf-8 -*- class User(object): def __init__(self): print("welcome to yingxionglianmeng") def login(self): print("login...") def register(self): print("zhucejianmian...") def disk(self): print("welcome to save disk") u = User() while True: user_cmd = input(">>").strip() if hasattr(u,user_cmd): getattr(u,user_cmd)()
以上是关于类的三大特性(继承, 封装, 多态)的主要内容,如果未能解决你的问题,请参考以下文章
Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态)