zoukankan      html  css  js  c++  java
  • 【Python学习之七】类和对象

    环境
      虚拟机:VMware 10
      Linux版本:CentOS-6.5-x86_64
      客户端:Xshell4
      FTP:Xftp4
      python3.6

    一、面向对象编程
    1、概念
    (1)面向对象编程(OOP),是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。面向对象是一种对现实世界理解和抽象的方法。
    面向过程是一件事“该怎么做“,面向对象是一件事“该让谁来做”,然后那个“谁”就是对象,他要怎么做是他自己的事,反正最后一群对象合力能把事做好就行了。
    面向对象三个特性:继承,封装,多态。
    (2)类:具有相同属性和行为事物的统称:类(Class) 由3个部分构成:类的名称:类名;类的属性:一组数据;类的方法:允许对进行操作的方法 (行为)
    (3)对象:某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的,可以是直接使用的;
    (4)类和对象关系:类就是创建对象的模板;

    2、定义类
    格式:class 类名: 方法列表
    (1)定义类时有2种:新式类和经典类,下面的Car为经典类,如果是Car(object)则为新式类;
    (2)类名的命名规则按照"大驼峰";

    #定义一个Car类
    class Car:
        def move(self):
            print('车正在移动...')
        def getCarInfo(self):
            print('车油耗数:%d, 颜色%s'%(self.oil, self.color))

    3、创建对象
    当创建一个对象时,就是用一个模子,来制造一个实物
    格式:对象名 = 类名()

    #创建对象     
    bmw=Car()
    #给对象bmw添加属性
    bmw.color='白色'
    bmw.oil=30
    #调用对象的方法
    bmw.getCarInfo()
    bmw.move()
    print(bmw.color)
    print(bmw.oil)

    (1)创建实例对象,一定在内存中有一块空间存放对象的数据信息。此时也可以通过实例对象bmw来访问属性或者方法,bmw是一个对象,它拥有属性(数据)和方法(函数);

    (2)第一次使用bmw.color = '白色'表示给bmw这个对象添加属性,如果后面再次出现bmw.color = xxx表示对属性进行修改;

    4、self
    类定义的方法中的参数self,可以理解为自己,可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思。
    (1)某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可;
    (2)self可以不写self,方法中至少有一个参数,第一个参数表示当前对象。名字随便取,但是习惯都写self;

    5、__init__()方法:初始化函数,用来完成一些默认的设定;该方法在创建对象后,就立刻被默认调用了。

    (1)__init__()方法,在创建一个对象时默认被调用,不需要手动调用;
    (2)__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y);
    (3)__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去;

    示例:

    class Car:
        def __init__(self):
            self.color='白色'
            self.wheel=4
            self.oil=10
                    
        def move(self):
            print('车正在移动...')
            
        def getCarInfo(self):
            print('车油耗数:%d, 颜色%s'%(self.oil, self.color))

    初始化函数使用入参:

    class Car:
        def __init__(self,color,wheel,oil):
            self.color=color
            self.wheel=wheel
            self.oil=oil
                    
        def move(self):
            print('车正在移动...')
            
        def getCarInfo(self):
            print('车油耗数:%d, 颜色%s'%(self.oil, self.color))
    
    bmw=Car('黑色',4,10)
    print('汽车颜色=%s,轮子数量=%d,油耗数量=%d'%(bmw.color,bmw.wheel,bmw.oil))

    6、__new__方法
    (1)__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
    (2)__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
    (3)__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
    (4)我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节

    __new__与__init__关系:
    (1)__new__方法(第一个执行)先于__init__方法执行;
    (2)__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self);
    (3)__new__方法的第一个参数是这个类,而其余的参数会在调用成功后全部传递给__init__方法初始化;
    (4)__new__和__init__想配合才是python中真正的类构造器;

    示例:

    class Dog(object):
        #创建对象
        def __new__(cls,name,age):
            print('__new__方法')
            print("类内存地址:%s"%id(cls))
            #return super().__new__(cls)
            ret=object.__new__(cls)
            print("实例化对象:%s"%ret)
            return ret
        
        def __init__(self,name,age):
            print('__init__方法')
            print("实例化对象:%s"%self)
            self.name=name
            self.age=age
    
    print('类内存地址:%s'%id(Dog))
    d=Dog('haha',12)
    
    # 类内存地址:3992792
    # __new__方法
    # 类内存地址:3992792
    # 实例化对象:<__main__.Dog object at 0x0000000002961390>
    # __init__方法
    # 实例化对象:<__main__.Dog object at 0x0000000002961390>

    7、__del__方法

    当内存中销毁(释放)一个对象时回调__del__()方法;

    import time
    class Animal(object):
        def __init__(self,name,age):
            print('__init__被调用...')
            self.__name=name
            self.__age=age
        def __del__(self):
            print('__del__被调用...')
            print('%s对象马上被干掉了'%self.__name)
        def __str__(self):
            return '名字'+self.__name+',年龄:'+str(self.__age)
        
    #创建对象
    dog=Animal('哈皮狗',1)
    #删除对象
    del dog
    # __init__被调用...
    # __del__被调用...
    # 哈皮狗对象马上被干掉了
    
    cat=Animal('波斯猫',2)
    print(cat)
    cat2=cat
    cat3=cat
    print("---马上 删除cat对象") 
    del cat 
    print("---马上 删除cat2对象") 
    del cat2 
    print("---马上 删除cat3对象") 
    del cat3 
    print("程序2秒钟后结束") 
    time.sleep(2)
    
    # __init__被调用...
    # 名字波斯猫,年龄:2
    # ---马上 删除cat对象
    # ---马上 删除cat2对象
    # ---马上 删除cat3对象
    # __del__被调用...
    # 波斯猫对象马上被干掉了
    # 程序2秒钟后结束

    关于对象被其他变量引用时,删除对象时的处理:
    (1)当有1个变量保存了对象的引用时,此对象的引用计数就会加1
    (2)当使用del删除变量指向的对象时,如果对象的引用计数不是1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除

    8、魔法方法
    在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
    __str__()类似toString()
    当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

    9、id()用于打印对象内存地址

    二、类和对象的属性
    1、公有属性和私有属性
    (1)Python中没有像C++中public和private这些关键字来区别公有属性和私有属性;
    (2)它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。

    2、类属性和实例属性
    (1)类属性:所属类,类似C++,java中类的静态成员变量;
    公有的类属性,在类外可以通过类和实例对象访问;
    私有的类属性,类和实例对象均不能在类外访问。
    (2)实例属性:在__init__通过self.XXX方式添加或者创建对象后,使用对象变量.XXX=数据时添加的

    class People(object):
        name='Tom'#公有类属性
        __age=10#私有的类属性
        def __init__(self,address):
            self.address=address
        
    p=People('山东')
    #公有类属性与私有类属性
    print(p.name)
    print(People.name)
    # print(p.__age)#报错:AttributeError: 'People' object has no attribute '__age'
    # print(People.__age)#报错:AttributeError: 'People' object has no attribute '__age'
    
    #实例属性与类属性
    print(p.address)
    # print(People.address)#报错:AttributeError: type object 'People' has no attribute 'address'
    
    #通过实例(对象)去修改类属性
    print(p.name)#Tom
    p.name='Jack'
    print(p.name)#实例属性会屏蔽掉同名的类属性 :Jack
    print(People.name)#Tom
    del p.name#删除实例属性
    print(p.name)#Tom

    注意:
    如果需要在类外修改类属性,必须通过类去引用然后进行修改。
    如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

    三、类方法和静态方法

    1、类方法
    (1)是类所拥有的方法,用修饰器@classmethod来标识;
    (2)第一个参数必须是类对象,一般以cls做标识(可用其他名称);
    (3)可以通过实例对象和类调用类方法;

    2、静态方法
    通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数。

    class Person(object):
        country='山东'
        
        @classmethod
        def getCountry(cls):
            return cls.country 
        @classmethod
        def setCountry(cls,country):
            cls.country=country
        
        @staticmethod
        def getCountry2():
            return Person.country
    
    pn=Person()
    #通过实例对象和类调用类方法
    print(pn.getCountry())#山东
    print(Person.getCountry()) #山东
    pn.setCountry('北京')
    print(pn.getCountry())#北京
    print(Person.getCountry()) #北京
    #静态方法
    print(Person.getCountry2())#北京

    方法类别

    语法

    描述

    类方法

    @classmethod

    第一个形参cls,默认传递, 通过cls引用的必定是类对象的属性和方法

    静态方法

    @staticmethod

    没有默认传递的形参

    对象方法(成员方法)

    def  方法名

    第一个形参self ,默认传递,通过self引用的可能是类属性、也有可能是实例属性, 不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。

    四、继承、多继承、多态
    1、继承
    (1)子类在继承的时候,在定义类时,小括号()中为父类的名字;
    (2)父类的属性(不包括私有属性)、方法(不包括私有方法),会被继承给子类

    class Animal(object):
        def __init__(self,name='动物',color='白色'):
            self.__name=name
            self.color=color
        def __test(self):
            print(self.__name)
            print(self.color)
        def test(self):
            print(self.__name)
            print(self.color)
    
    class Dog(Animal):
        def doTest(self):
            #print(self.__name)#不能访问到父类的私有属性
            print(self.color)
            
        def doTest2(self):
            #self.__test()#不能访问父类中的私有方法
            self.test()
        
    a=Animal()
    # print(a.__name)#报错:AttributeError: 'Animal' object has no attribute '__name'
    print(a.color)
    # a.__test()#报错:AttributeError: 'Animal' object has no attribute '__test'
    a.test()
    print('-'*30)
    d=Dog(name='小花',color='花色')
    d.doTest()
    d.doTest2()

    2、多继承,即子类有多个父类,并且具有它们的特征

    class Base(object):
        def test(self):
            print('---Base test---')
            
    class A(Base):
        def test(self):
            print('---A test---')
            
    class B(Base):
        def test(self):
            print('---B test---')
            
    class C(A,B):
        pass
    
    c=C()
    c.test()#---A test---
    #可以查看C类的对象搜索方法时的先后顺序,C.__mro__算法得到一个元组
    print(C.__mro__)#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)

    注意:按照继承顺序调用父类的方法

    3、重写

    所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

    class Cat(object):
        def __init__(self,name):
            self.name=name
            self.color='黑色'
            
        def sayHello(self):
            print('-----Cat-----')
        
    class Bosi(Cat):
        def __init__(self,name):
            # 调用父类的__init__方法1(python2) 
            Cat.__init__(self, name)
            # 调用父类的__init__方法2 
            super(Bosi,self).__init__(name)
            # 调用父类的__init__方法3 
            super().__init__(name)
            
        def sayHello(self):
            print('-----Bosi-----')
            
    bosi=Bosi('小花') 
    bosi.sayHello()#-----Bosi-----
    print(bosi.name)#小花
    print(bosi.color)#黑色

    4、多态
    所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态

    class Animal(object):
        def run(self):
            print('Animal is running...')
            
    class Dog(Animal):
        def run(self):
            print('Dog is running...')
    
    class Cat(Animal):
        def run(self):
            print('Cat is running...')
    
    def run_twice(animal):
        animal.run()
    
    run_twice(Animal())#Animal is running...
    run_twice(Dog())#Dog is running...
    run_twice(Cat())#Cat is running...

    参考:
    Python学习笔记

  • 相关阅读:
    mui签到日历
    简单的vue-resourse获取json并应用到模板
    Ubuntu16.04安装wineqq国际版
    spring RestTemplate调用string和URL 请求问题
    java.util.AbstractSequentialList
    java.util.AbstractList
    maven pom 报错 inspects a maven model for resolution problems
    2019/9/6 spring实战第二章,shiro权限加密,授权
    2019/9/4 spring实战,shiro权限简单记录
    mybatis 转换结果问题
  • 原文地址:https://www.cnblogs.com/cac2020/p/10815231.html
Copyright © 2011-2022 走看看