• 面向对象的程序设计


      面向过程的程序设计经常用于操作系统的内核,git等,一成不变的流水线式解决一个问题,极大程度降低程序复杂性。

      面向对象的程序设计解决了程序的扩展性(类可产生各种各样的对象,对于新增技能或修改技能可使用方法直接调用),但是可控性差,因为面向对象程序一旦开始就是由对象之间交互来解决问题。

      OOD面向对象的程序设计

      先找程序中所有的对象,将对象归纳出类(并归纳出共同属性与方法和不同的属性)。

      OOP面向对象编程

      编程时先定义出类,再根据类实例化出对象。

      python3统一了类与类型的概念,python3中的类型就是类。

      编程方式:

      面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行,

      函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性,

      面向对象:对函数进行分类和封装,将同类的函数放到一个类中,使调用更简单。

    类的简介

      类和对象
      类就是一个模板,模板里可以包含多个方法(即函数),方法里实现一些功能,对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。

    #创建类  class+类名
    class foo:               #class是关键字,表示类,foo是类的名字
        def f1(self):               #类的方法1
            pass
        def f2(self):               #类的方法2
            pass
    
    #创建对象  对象 = 类名()
    bar = foo()   #创建一个bar对象 ,此对象中有类中所有的方法 ,创建对象,类名称后加括号即可 
    
    #调用对象的方法  对象.方法名()
    bar.f1()
    bar.f2()
    创建类和变量的方式

      类名+()就等于在执行Person.__init__(),执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。

      这里提一嘴特殊的类属性。

      类名.__name__# 类的名字(字符串)

      类名.__doc__# 类的文档字符串

      类名.__base__# 类的第一个父类

      类名.__bases__# 类所有父类构成的元组

      类名.__dict__# 查看类和对象的名称空间

      类名.__module__# 类定义所在的模块

      类名.__class__# 实例对应的类(仅新式类中)

      python中使用class定义类,在python3中只有新式类(默认继承object),而python2中有新式类(手写继承object)与经典类的区别,可使用__basic__查看继承关系。

      python2的经典类:

      类的一般操作形式:

    class Teacher:                 #定义类
        x=1  #调用属性时不论对象还是类指向的都是同一块内存地址,属性又称静态字段
        def __init__(self,name,sex,age,money):#init不能有返回值,里面放的是独有特征,共有特征使用单独函数定义
            self.name=name                    #普通字段
            self.sex=sex
            self.age=age
            self.money=money
        def search(self):#teacher调用函数或者实例化对象的绑定方法调用的不是同一块内存地址,普通方法
            print("scord")
        def study(self):
            print("study")
    print(Teacher.x)   #1
    t=Teacher('jeff','male','110',10)#实例化出来的对象
    print(t.name)    #jeff
    print(t.age)    #110
    t.study()       #study
    Teacher.y=5
    print(Teacher.y)#5
    class 类名:
        类属性 = None
        def __init__(self,参数1,参数2):
            self.对象的属性1 = 参数1
            self.对象的属性2 = 参数2
    
        def 方法名(self):pass
    
        def 方法名2(self):pass
    
    对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                      #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                      #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                      #结果返回一个对象
    对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
    对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
    #对象增加属性
    对象.新的属性名 = 1000
    通用的class定义方法

      类是整个单独的名称空间,定义类也就是单独定义了他的名称空间(变量,函数和类名字)用来存储类中定义的所有名字,这些名字称为类的属性,静态属性就是直接在类中定义的变量,动态属性就是定义在类中的方法。可以使用__dict__查看类和对象的名称空间。实例化对象会先从自己的dict查找变量,找不到就去类(父类)的dict找,没有则会报错。

      类可以进行实例化,可以进行属性引用。对象只能属性引用。对象本身只能引用属性(变量name,sex,age。。。)。

    t.name2='tom'#
    del t.name2#
    t.name='jerry'#
    print(t.name)#

      实例化对象之间的交互:

    class Riven:
        camp='Noxus'  #所有玩家的英雄(锐雯)的阵营都是Noxus;
        def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻击力54;
            self.nickname=nickname  #为自己的锐雯起个别名;
            self.aggressivity=aggressivity #英雄都有自己的攻击力;
            self.life_value=life_value #英雄都有自己的生命值;
        def attack(self,enemy):   #普通攻击技能,enemy是敌人;
            enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。
    
    class Garen:
        camp='Noxus'  #所有玩家的英雄(锐雯)的阵营都是Noxus;
        def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻击力54;
            self.nickname=nickname  #为自己的锐雯起个别名;
            self.aggressivity=aggressivity #英雄都有自己的攻击力;
            self.life_value=life_value #英雄都有自己的生命值;
        def attack(self,enemy):   #普通攻击技能,enemy是敌人;
            enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。
    
    
    #对象之间的交互
     r1=Riven('芮雯雯')
     g1=Garen('草丛轮')
     print(r1.life_value)
     g1.attack(r1)
     print(r1.life_value)
    德玛西亚大战瑞文

      私有属性

      特点:

      类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。

      这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

      在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

      注意:

      这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N。

    class people:
        __name = 'jeff'
        __age = 12
        def set(self):
            print(self.__name)
            print(self.__age)
    p = people()
    #print(p.__name,p.__age)   #AttributeError: 'people' object has no attribute '__name'
    p.set()
    运行结果;
    jeff
    12

      封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。

    #类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
    class Room:
        def __init__(self,name,owner,width,length,high):
            self.name=name
            self.owner=owner
            self.__width=width
            self.__length=length
            self.__high=high
        def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
            return self.__width * self.__length * self.__high
    
    
    #对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
     r1.tell_area()#对于用户只要知道这个接口的功能就可以了
    扩展性

      property属性

      把绑定方法装饰的像一个属性一样调用,被property装饰的属性会优先于对象的属性被使用。

    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
        @property
        def bmi(self):
            return self.weight / (self.height**2)
    
    p1=People('egon',75,1.85)
    print(p1.bmi)
    property属性
    import math
    class Circle:
        def __init__(self,radius): #圆的半径radius
            self.radius=radius
    
        @property
        def area(self):
            return math.pi * self.radius**2 #计算面积
    
        @property
        def perimeter(self):
            return 2*math.pi*self.radius #计算周长
    
    c=Circle(10)
    print(c.radius)
    print(c.area) #可以像访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter) #同上
    '''
    输出结果:
    314.1592653589793
    62.83185307179586
    '''
    #注意:此时的特性area和perimeter不能被赋值
    c.area=3 #为特性area赋值
    '''
    抛出异常:
    AttributeError: can't set attribute
    '''
    但是不能赋值

      将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。

      对于obj.name我们想要在实际中会有需求能改他的值,实例.name='jeff'就是改self.__name。

      这就需要用到@name.setter,删除特性的方法@name.deleter。

    class People:
        def __init__(self,name,SEX):
            self.name=name
            # self.__sex=SEX
            self.sex=SEX #self.sex='male'   p1.sex='male'
        @property
        def sex(self):
            return self.__sex #p1.__sex
    
        @sex.setter
        def sex(self,value):
            # print(self,value)
            if not isinstance(value,str):
                raise TypeError('性别必须是字符串类型')
            self.__sex=value  #p1.__sex='male'
        @sex.deleter
        def sex(self):
            del self.__sex #del p1.__sex
    
    p1=People('cobila','male')
    p1.sex='female'
    print(p1.sex)
    特性方法的修改和删除

      类方法

    class people:
        country = 'china'
        # 类方法,用classmethod来进行修饰
        @classmethod
        def getCountry(cls):  #类方法自动将类作为cls传递进函数内
            return cls.country
        @classmethod
        def setCountry(cls, country):
            cls.country = country
    p = people()
    print(p.getCountry())  # 可以用过实例对象引用
    print(people.getCountry())  # 可以通过类对象引用
    p.setCountry('japan')
    print(p.getCountry())
    运行结果:
    china
    china
    japan

      静态方法

    class people:
        country = 'china'
        @staticmethod
        # 静态方法使用装饰器方式绑定,并且作用和普通函数一样并不会自动传递self
        def getCountry():
            return people.country
    print(people.getCountry())
    运行结果:
    china

      普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象

      类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类

      静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定

    面向对象三大特性

      封装

      封装顾名思义就是将东西装起来然后留出接口供用户使用,不需要知道内部发生了什么,只需要知道接口如何调用即可。在此之前所说的__init__定义的普通字段的赋值,并提供普通方法作为调用接口就是python中的封装结构。除此之外,私有属性也是封装的一种方法之一。

      好处:将变化隔离; 

      便于使用;

      提高复用性; 

      提高安全性;

      封装原则:

      将不需要对外提供的内容都隐藏起来;

       把属性都隐藏,提供公共方法对其访问。

      多重封装:

    #创建类
    class SQL:
        def __init__(self,name,passwd):
            self.name = name
            self.passwd = passwd
        def create(self,sql):
            print(sql)
    
    class test:
        def __init__(self,name,obj):
            self.name = name
            self.obj = obj
    
        def add(self,arg):
            print(arg)
    
    class test2:
        def __init__(self,obj):
            self.obj = obj
        def iner(slef,arg):
                print(arg)
    
    #创建对象
    c1 = SQL('fuzj','12313')
    c2 = test('aaa',c1)   #把c1对象封装到c2对象里,c2对象会有c1对象的所有方法
    c3 = test2(c2)          #把c2对象封装到c3对象中,c3对象会有c2对象的所有方法,同时也就有了c1对象的所有方法
    
    #调用
    c1.create("c1调用自身create方法")
    c2.obj.create('c2调用c1的create方法')
    c3.obj.add('c3调用c2的add方法')
    c3.obj.obj.create('c3调用c1的create方法')
    
    结果:
    c1调用自身create方法
    c2调用c1的create方法
    c3调用c2的add方法
    c3调用c1的create方法
    多重封装

      继承

      对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

    class ParentClass1: #定义父类
        pass
    
    class ParentClass2: #定义父类
        pass
    
    class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
        pass
    
    class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
        pass
    继承

      一个类可以继承多个父类(基类,超类),这点与其他语言略有不同,当类是经典类时,多继承情况下,会按照深度优先方式查找;当类是新式类时,多继承情况下,会按照广度优先方式查找。

    class D:
        def bar(self):
            print('D.bar')
    class C(D):
        def bar(self):
            print('C.bar')
    class B(D):
        def bar(self):
            print('B.bar')
    class A(B, C):
        def bar(self):
            print('A.bar')
    a = A()
    # 经典类执行bar方法时
    # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
    # 所以,查找顺序:A --> B --> D --> C
    # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    a.bar()
    #新式类执行bar方法时的查找顺序为A --> B --> C --> D
    class Hero:#这个英雄类包含了所有英雄都有的属性和方法
        def __init__(self, nickname,
                     aggressivity,
                     life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value = life_value
    
        def attack(self, enemy):
            enemy.life_value -= self.aggressivity
    
    class Garen(Hero):#盖伦继承了英雄类
        camp='Demacia'
        def attack(self, enemy):
            pass
        def fire(self):#盖伦独有的喷火技能
            print('%s is firing' %self.nickname)
    class Riven(Hero):
        camp='Noxus'
    g1=Garen('garen',18,200)
    r1=Riven('rivren',18,200)
    # print(g1.camp)
    # print(r1.camp)
    # g1.fire()
    g1.attack(g1)
    瑞文大战德玛之继承
    class Animal:      #父类  
        def __init__(self,name,life_value,aggr):
            self.name = name
            self.life_value = life_value
            self.aggr = aggr  #攻击力
        def eat(self):
            self.life_value += 10
    
    class Person(Animal):  #子类 
        def __init__(self,money,name,life_value,aggr):
            super().__init__(name,life_value,aggr)#super调用父类的构造方法
            self.money = money   #派生属性
    
        def attack(self,enemy):    #人的派生方法
            enemy.life_value -= self.aggr
    
    class Dog(Animal): #派生子类
        def __init__(self,breed,name,life_value,aggr):
            #Animal.__init__(self,name,life_value,aggr)   #让子类执行父类的方法,就是父类名.方法名(参数),连self也得传就是super()
            super().__init__(name,life_value,aggr)  #super关键字——新式类
            #super(Dog,self).__init__(name,life_value,aggr)  #super关键字——新式类
            self.breed = breed
        def bite(self,person):   #狗的派生方法
            person.life_value -= self.aggr
    
        def eat(self):       # 父类方法的重写
            super().eat()
            print('dog is eating~~~ ')
    
    ha2 = Dog('牛头梗','旺财',20000,100)
    print(ha2.life_value)
    ha2.eat()
    print(ha2.life_value)
    # super(Dog,ha2).eat()  #调用父类的
    print(ha2.life_value)
    人狗大战之派生
    class Hero:
        def __init__(self, nickname, aggressivity, life_value):
            self.nickname = nickname
            self.aggressivity = aggressivity
            self.life_value = life_value
        def attack(self, enemy):
            print('Hero attack')
            enemy.life_value -= self.aggressivity
    # print(Hero.__init__)
    # print(Hero.attack)
    class Garen(Hero):
        camp = 'Demacia'
        def __init__(self, nickname, aggressivity, life_value, script):
            Hero.__init__(self,nickname,aggressivity,life_value)
            # self.nickname = nickname
            # self.aggressivity = aggressivity
            # self.life_value = life_value
            self.script = script
        def attack(self, enemy):  # self=g1,enemy=r1
            # self.attack(enemy) #g1.attack()
            Hero.attack(self, enemy)
            print('from garen attack')
        def fire(self):
            print('%s is firing' % self.nickname)
    # g1=Garen('garen',18,200) #Garen.__init__(g1,'garen',18,200)
    g1=Garen('garen',18,200,'人在塔在') #Garen.__init__(g1,'garen',18,200)
    print(g1.script)
    继承更加精简了代码

      多态

      多态即多种形态,在运行时确定其状态,在编译阶段无法确定其类型,这就是多态。Python中的多态和Java以及C++中的多态有点不同,Python中的变量是弱类型的,在定义时不用指明其类型,它会根据需要在运行时确定变量的类型(个人觉得这也是多态的一种体现),并且Python本身是一种解释性语言,不进行预编译,因此它就只在运行时确定其状态,故也有人说Python是一种多态语言。

      组合

      与继承不同,组合不是什么是什么的关系,而是一种什么有什么的关系,比如学生有课程,他们是一种并行的关系而不是可以继承的关系。

    class Student:
        def __init__(self,ID,name,sex):
            self.id=ID
            self.name=name
            self.sex=sex
            self.course_list=[]
    class Course:
        def __init__(self,name,price,period):
            self.name=name
            self.price=price
            self.period=period
    
    s1=Student('123123123123','cobila','female')
    
    python_obj=Course('python',1,'7m')
    linux_obj=Course('linux',1,'2m')
    
    s1.course_list.append(python_obj)
    s1.course_list.append(linux_obj)
    print(s1.course_list[0].name)
    print(s1.course_list[0].price)
    运行结果:
    python
    1

      关于组合的问题看到一个哥们在博客里的人狗大战的代码,与德玛西亚大战瑞文一样,可以有一个装备类,装备有技能,也有属性,可以通过购买装备组合,也就是人与狗的实例化对象都可以拥有装备,装备加属性加技能再进行交互。

    class Person:  # 定义一个人类
        '''
            这是一个游戏里人物的数据类型
        '''
        role = 'person'  # 人的角色属性都是人
        def __init__(self, name, aggressivity, life_value):
            self.name = name  # 每一个角色都有自己的昵称;
            self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
            self.life_value = life_value  # 每一个角色都有自己的生命值;
        def attack(self,dog):
            # 人可以攻击狗,这里的狗也是一个对象。
            dog.life_value -= self.aggressivity
            print("{0}打了{1}一下,{1}剩余血量{2}".format(self.name, dog.name, dog.life_value))
    
    class Dog:  # 定义一个狗类
        '''
            这是一个游戏里狗的数据类型
        '''
        role = 'dog'  # 狗的角色属性都是狗
        def __init__(self, name, breed, aggressivity, life_value):
            self.name = name  # 每一只狗都有自己的昵称;
            self.breed = breed  # 每一只狗都有自己的品种;
            self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
            self.life_value = life_value  # 每一只狗都有自己的生命值;
        def bite(self,people):
            # 狗可以咬人,这里的狗也是一个对象。
            people.life_value -= self.aggressivity
            print("{0}咬了{1}一下,{1}剩余血量{2}".format(self.name,people.name,people.life_value))
    
    class Weapon:
        '''
            这是一个游戏里武器的数据类型
        '''
        def __init__(self,name, price, aggrev, life_value):
            self.name = name    #武器名称
            self.price = price  #武器价格
            self.aggrev = aggrev    #武器伤害加成
            self.life_value = life_value    #武器血量加成
    
        def update(self, obj):  #obj就是要带这个装备的人
            obj.money -= self.price  # 用这个武器的人花钱买所以对应的钱要减少
            obj.aggressivity += self.aggrev  # 带上这个装备可以让人增加攻击
            obj.life_value += self.life_value  # 带上这个装备可以让人增加生命值
    
        def prick(self, obj):  # 这是该装备的主动技能,绞龙
            obj.life_value -= 3000  # 假设攻击力是3000
            print("{0}发动主动技:蛟龙==>{1}剩余血量{2}".format(self.name, obj.name, obj.life_value))
    
    
    a = Person("苍井井",10,1000)
    b = Dog("egon","狼狗",200,20000)
    c = Weapon("蛟龙鞭",1000,40,2000)
    a.money = 2000
    
    #判断是否买的起武器
    if a.money > c.price :
        c.update(a)
        a.weapon = c
    
    #大战开始
    while True :
        a.attack(b)
        if b.life_value <= 0 :
            print(b.name + "" + a.name + "打死了!")
            break
        a.weapon.prick(b)
        if b.life_value <= 0 :
            print(b.name + "" + a.name + "绞死了!")
            break
        b.bite(a)
        if a.life_value <= 0 :
            print(a.name+""+b.name+"咬死了!")
            break
    人狗大战实例

      接口归一化设计

      父类中定义不操作,子类进行定义的衍生(子类都有相同功能,并且功能操作可能不一样)。如果子类没有定义或者也pass了,那这个方法就没有实际的意义了,为了防止这种现象的出现要采取一些措施。

    class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
        def read(self): #定接口函数read
            pass
    
        def write(self): #定义接口函数write
            pass
    
    
    class Txt(Interface): #文本,具体实现read和write
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    class Sata(Interface): #磁盘,具体实现read和write
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    class Process(Interface):
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    
    
    
    t1=Txt()
    s1=Sata()
    p1=Process()
    
    
    
    t1.read()
    t1.write()
    
    s1.read()
    s1.write()
    
    p1.read()
    p1.write()
    可能需要的场景
    class Animal:
        def run(self):
            raise AttributeError('子类必须实现这个方法')
        def speak(self):
            raise AttributeError('子类必须实现这个方法')
    class People(Animal):
        def run(self):
            print('人正在走')
    
        # def speak(self):
        #     print('说话')
    
    class Pig(Animal):
        def run(self):
            print('pig is walking')
        def speak(self):
            print('哼哼哼')
    
    peo1=People()
    # peo1.run()
    peo1.speak()#异常咯
    low主动抛异常

      这使得虽然大家的操作都不一样,但是调用的时候方法都是一样的,这就是归一化设计。

      这里存在一个问题,我们需要进行拓展,如果说,我们的子类没有进行父类的某一项普通方法的定义,根据广度优先的查找顺序,会在父类中找到此方法,但是此方法没有任何定义,自然这个操作毫无意义,所以我们可以在父类进行raise主动将异常抛出,或者使用abc模块自动抛出异常。

    import abc
    #抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们
    class Animal(metaclass=abc.ABCMeta):
        tag='123123123123123'
        @abc.abstractmethod
        def run(self):
            pass
        @abc.abstractmethod
        def speak(self):
            pass
    class People(Animal):
        # def run(self):  #子类没有定义父类有的方法,但是没有搜寻父类的方法直接报错
        #     pass
        def speak(self):
            pass
    
    peo1=People()
    print(peo1.tag)
    运行结果:
    TypeError: Can't instantiate abstract class People with abstract methods run

       注意:抽象类不能被实例化

    super()函数的用法

      super在python2中的用法:

      1:super(自己的类,self).父类的函数名字

      2:super只能用于新式类

    class People(object):
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            # self.name=name
            # self.sex=sex
            # self.age=age
            # People.__init__(self,name,sex,age)
            super(Chinese,self).__init__(name,sex,age)
            self.language=language
    c=Chinese('egon','male',18)
    print c.name,c.age,c.sex,c.language
    py2super
    class People:
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            # self.name=name
            # self.sex=sex
            # self.age=age
            # People.__init__(self,name,sex,age)
            super().__init__(name,sex,age)
            self.language=language
        def walk(self,x):
            super().walk()
            print('子类的x',x)
    c=Chinese('egon','male',18)
    # print(c.name,c.age,c.sex,c.language)
    c.walk(123)
    py3super

      __str__

      _str__定义在类内部,必须返回一个字符串类型,打印由这个类产生的对象时,会触发执行.

    class People:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return '<name:%s,age:%s>' %(self.name,self.age)
    
    p1=People('egon',18)
    print(p1)
    str(p1) #此时print触发----->p1.__str__()
    #所以打印结果为<name:egon,age:18>
    __str__
  • 相关阅读:
    学习流程
    Linux计划任务 定时任务 Crond 配置详解 crond计划任务调试 sh x 详解 JAVA脚本环境变量定义
    asp.net 将Excel中某个工作簿的数据导入到DataTable方法
    在浏览器输入url,发生了什么?BSC结构图(百度搜索关键字发生了什么?)
    在C#中使用属性控件添加属性窗口
    转载:面向对象在数据库应用程序中的应用(dotNet)
    中国软件:10个人20年坎坷路
    客户端回调
    鼠标放在图片连接上面,预览图片
    一个合格的程序员该做的事情
  • 原文地址:https://www.cnblogs.com/Jeffding/p/7376515.html
Copyright © 2020-2023  润新知