面向对象和面向过程
知乎上有句回答 : 面向过程是编年体;面向对象是纪传体 # 不知道会不会被告侵权 侵删哈23333333
- 面向过程:用一对代码从开始到结束描述整个任务完成的过程.
- 比如你要写一个格斗游戏
- 首先描述擂台场景
- 描述一个角色出现,另一个角色出现
- 再描述两个角色的外形 , 比如体型服装性别特征等等
- 两个人摆好架势等待用户输入
- while 用户输入>>做一次判断>>角色执行对应的动作......
- 面向对象:把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为
- 同样是格斗游戏
- 擂台对象,描述擂台场景的构成
- 角色对象,描述任务外形技能等
- 规则对象,对比赛进行判定
类和对象
创建类和对象
类就是一个模板,模板里包含一类事物的共同特征,同时包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,具化类的特征,通过实例对象可以执行类中的函数
# 创建类 class Foo: # 创建类中的函数 def func(self): pass # 根据类Foo创建对象obj obj = Foo()
- class 关键字 表示创建类
- Foo 类名
- 创建对象,类名后边加括号即可
- 注释 类中定义的函数一般叫方法,方法的第一个参数必须是 self 稍后会讲解
面向对象的三大特性
封装
""" 封装 是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问,要访问该类的代码和数据,必须通过严格的接口控制 封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段 适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。 """ class Foo1: def __init__(self,name,age,face_value): """ 构造方法,根据类创建对象时自动执行 :param name: :param age: :param face_value: """ self.name = name self.age = age self.face_value = face_value def foo(self): # 类中的方法需要通过self间接调用被封装的内容 print(self.name) # 将 ‘nathaniel‘,‘19‘,‘Men of God‘ 封装到obj的 name,age,face_score 属性中 obj = Foo1(‘nathaniel‘,‘19‘,‘Men of God‘) # self是一个形式参数,默认等于根据类创建的对象 # obj0 = Foo1(‘nathaniel‘,‘19‘,‘Men of God‘) self等于obj0 # obj1 = Foo1(‘nathaniel‘,‘19‘,‘Men of God‘) self等于obj1 # 所以,内容其实是被封装在了对象当中,每个对象都具有创建它们的类的属性,并且可以有自己不同的值 # 以上就封装好了,接下来调用 print(obj.name) # 通过对象直接调用类中的属性 obj.foo() # 调用类中的方法 class Person: """ 小游戏 1、创建三个游戏人物,分别是: 苍井井,女,18,初始战斗力10000 泷泽萝沙,女,20,初始战斗力8000 波多多,女,22,初始战斗力8100 2、游戏场景,分别: 草丛大作战,消耗200战斗力 冥想修炼,增长100战斗力 苍穹对决,消耗500战斗力 """ def __init__(self,name,gender,age,fight): self.name = name self.gender = gender self.age = age self.fight = fight def grassland(self): """ 草丛大作战,消耗200战斗力 :return: """ self.fight = self.fight - 200 def meditation(self): """ 冥想修炼,增长100战斗力 :return: """ self.fight = self.fight + 100 def sky_duel(self): """ 苍穹对决,消耗500战斗力 :return: """ self.fight = self.fight - 500 def show(self): """ 展示游戏人物当前状态 :return: """ temp = "姓名:%s ; 性别:%s ; 年龄:%s ; 战斗力:%s" % (self.name, self.gender, self.age, self.fight) print(temp) cjk = Person(‘苍井井‘, ‘女‘, 18, 10000) # 创建苍井井角色 lzl = Person(‘泷泽萝沙‘, ‘女‘, 18, 8000) # 创建泷泽萝沙角色 bdd = Person(‘波多多‘, ‘女‘, 18, 8100) # 创建波多多角色 cjk.sky_duel() # 苍井井进行了一次苍穹对决 lzl.meditation() # 泷泽萝沙进行了一次冥想修炼 bdd.grassland() # 波多多进行了一次草丛大作战 # 展示游戏人物当前状态 cjk.show() lzl.show() bdd.show()
继承
""" 继承 子类可以继承父类,父类中的属性和方法,子类可以直接使用 举个栗子 狗:"汪汪"叫,吃喝拉撒 猫:"喵喵"叫,吃喝拉撒 他们都继承动物类的属性 """ class Animal: def __init__(self,weight): self.weight = weight def action(self): print(‘吃喝拉撒‘) class Dog(Animal): # Dog类继承Animal类 def __init__(self,name): self.name = name # 子类可以都自己的特色 def voice(self): print(‘汪汪汪‘) class Cat(Animal): # Cat类继承Animal类 def __init__(self,name): self.name = name # 子类可以都自己的特色 def voice(self): print(‘喵喵喵‘) dog = Dog(‘大黄‘) dog.voice() # 子类可以调用自己的方法 dog.action() # 也可以调用父类的方法 cat = Cat(‘小黑‘) cat.voice() # 子类可以调用自己的方法 cat.action() # 也可以调用父类的方法 print(‘233‘) # 那么问题来了,创建子类的对象,父类中的构造方法没有被执行,怎么办? class Pig(Animal): def __init__(self,name,weight): self.name = name # 通过super关键字执行父类中的构造方法 super(Pig,self).__init__(weight) # 也可以执行父类中的其他方法 super(Pig,self).action() # 子类可以都自己的特色 def voice(self): print(‘哼唧哼唧‘) pig = Pig(‘阿花‘,300) print(‘有趣的阿花%s多斤‘% pig.weight)
ok,现在你学会了继承,再来看个变态的东西----多继承
类有新式类和经典类之分,从写法上区分,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类
- 当类是经典类时,多继承情况下,会按照深度优先方式搜索
- 当类是新式类时,多继承情况下,会按照广度优先方式搜索
Python 2.x中默认都是经典类,只有显式继承了object才是新式类
Python 3.x中默认都是新式类,不必显式的继承objec
class S0: def func(self): print("This is from S0") class S(S0): def __init__(self): pass class S1(S): def __init__(self): pass class S2(S0): def __init__(self): pass def func(self): print("This is from S2") class S3(S1,S2): def __init__(self): pass obj = S3() obj.func()
执行上述代码
经典类的答案: This is from S0
新式类的答案: This is from S2
# 一个子类能否继承多个类 (爸爸妈妈爷爷奶奶叔叔伯伯 # 如果继承的多个类每个类中都定义了相同的函数,那么那一个会被使用呢 class S: def show(self): print(‘S‘) def show1(self): print(‘S‘) class S1(S): def show(self): print(‘S1‘) class S2: def show(self): print(‘S2‘) def show1(self): print(‘S2‘) class S22(S): def show(self): print(‘S22‘) def show1(self): print(‘S22‘) class S3(S1,S2): pass class S4(S1,S22): pass obj = S3() obj.show() # 广度优先 S4().show1() # 广度优先
多态
对于Java、C#来说 ,创建一个变量必须指定它的数据类型
public static void main(String[] args) {}; Java定义一个方法,指定了变量类型String类,如果赋值不是String类就会报错
public static void main(Foo[] args) {}; 也可以自己写一个类Foo类,Foo类有众多子类,那么赋值类型就可以是Foo类或其子类中的任意一个
而python则没有这种限制,因为python原生多态
def func(*args):pass
变量可以是任意类型
# 有兴趣的小伙伴可以研究下这段代码,emmmmmm print("******多继承使用类名.__init__ 发生的状态******") class Parent(object): def __init__(self, name): print(‘parent的init开始被调用1‘) self.name = name print(‘parent的init结束被调用2‘) class Son1(Parent): def __init__(self, name, age): print(‘Son1的init开始被调用3‘) self.age = age Parent.__init__(self, name) print(‘Son1的init结束被调用4‘) class Son2(Parent): def __init__(self, name, gender): print(‘Son2的init开始被调用5‘) self.gender = gender Parent.__init__(self, name) print(‘Son2的init结束被调用6‘) class Grandson(Son1, Son2): def __init__(self, name, age, gender): print(‘Grandson的init开始被调用7‘) Son1.__init__(self, name, age) # 单独调用父类的初始化方法 Son2.__init__(self, name, gender) print(‘Grandson的init结束被调用8‘) print(Grandson.__mro__) gs = Grandson(‘grandson‘, 12, ‘男‘) print(‘姓名:‘, gs.name) print(‘年龄:‘, gs.age) print(‘性别:‘, gs.gender) print("******多继承使用类名.__init__ 发生的状态******\n\n") # ---------------------------------------------------- print("******多继承使用super().__init__ 发生的状态******") class Parent(object): def __init__(self, name, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 print(‘parent的init开始被调用1‘) self.name = name print(‘parent的init结束被调用2‘) class Son1(Parent): def __init__(self, name, age, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 print(‘Son1的init开始被调用3‘) self.age = age super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数 print(‘Son1的init结束被调用4‘) class Son2(Parent): def __init__(self, name, gender, *args, **kwargs): # 为避免多继承报错,使用不定长参数,接受参数 print(‘Son2的init开始被调用5‘) self.gender = gender super().__init__(name, *args, **kwargs) # 为避免多继承报错,使用不定长参数,接受参数 print(‘Son2的init结束被调用6‘) class Grandson(Son1, Son2): def __init__(self, name, age, gender): print(‘Grandson的init开始被调用7‘) # 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍 # 而super只用一句话,执行了全部父类的方法,这也是为何多继承需要全部传参的一个原因 # super(Grandson, self).__init__(name, age, gender) super().__init__(name, age, gender) print(‘Grandson的init结束被调用8‘) print(Grandson.__mro__) gs = Grandson(‘grandson‘, 12, ‘男‘) print(‘姓名:‘, gs.name) print(‘年龄:‘, gs.age) print(‘性别:‘, gs.gender) print("******多继承使用super().__init__ 发生的状态******\n\n")