python 面向对象(初级篇)

面向对象和面向过程

知乎上有句回答 : 面向过程是编年体;面向对象是纪传体 # 不知道会不会被告侵权   侵删哈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")

 

posted @ 2018-03-19 14:59  Nathaniel-J  阅读(254)  评论(0编辑  收藏  举报