zoukankan      html  css  js  c++  java
  • 学习4: 面向对象

    1. 类的定义和实例化

    class dog():                
        def __init__(self,name,age,s,color):  
            self.name = name
            self.age = age
            self.single = s
            self.color = color
        def walk(self):
            self.a = 'aaa'
            self.b = 100
            print 'running dog'
        def eat(self,food):
            print 'eat..',food
        def talk(self):
            print 'w w w'
    w = dog('heizi',1,True,'black')     
    l = dog('nana',3,True,'yellow')
    l.money = 'bumai!'
    print l.money
    print w.name

    总结:
    1) class后面紧接着是类名,类的类型分为经典类和新式类。经典类后面括号不继承任何东西。新式类括号里面面一般最好添加(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
    2) 由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,age等属性绑上去
    3) 注意到__init__为初始化方法,第一个参数永远是self,表示创建的实例本身
    4) 变量w就是指向dog的类的实例变量,而dog本身就是一个类。()里面的都是给他捆绑的属性
    5) 有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。另外和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数和关键字参数。
    6) 类的方法:在上面的dog类中,每个实例就拥有各自的name和age这些数据,因为dog的实例本身就有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在dog类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。这些封装数据的函数是和dog类本身是关联起来的,我们称之为类的方法。要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入。

    2. 属性

    class student(object):
        grade = 'Four'       #类的公有属性,可以被类和实例访问
        __teacher = 'David'  #类的私有属性(以__为前缀),不可以被类和实例访问,只可用于类的方法中调用
        def __init__(self,name,age):
            self.name = name #实例的公有属性,可以被实例访问
            self.__age = age #实例的私有属性(以__为前缀),不可以被实例访问,只可用于类的方法中
        def getGrade(self):
            print self.grade
        def getTeacher(self):
            print self.__teacher
        def getName(self):
            print self.name
        def getAge(self):
            print self.__age
    s = student('Lina',18)
    print '---测试1:类的公有属性可以被类和实例访问'
    print student.grade
    print s.grade
    print '---测试2:类的私有属性不可以被类和实例访问'
    #print student.__teacher
    #print s.__teacher
    print '---测试3: 实例的公有属性,可以被实例访问,但是不能被类访问'
    print s.name
    #print student.name
    print '---测试4, 实例的私有属性,不可以被实例访问'
    #print s.__age
    print '---测试5, 公有属性和私有属性都可以被类的方法中调用'
    s.getGrade()
    s.getTeacher()
    s.getName()
    s.getAge()

    总结:
    属性分为类的属性和实例属性。定义在类中方法之外的属性,称为类的属性,又分为类的公有属性和私有属性;
    1) 类的公有属性,可以被类和实例访问;
    2) 类的私有属性(以__为前缀),不可以被类和实例访问,只可用于类的方法中通过self.__private_attrs调用
    3) 实例的公有属性,可以被实例访问
    4) 实例的私有属性(以__为前缀),不可以被实例访问,只可用于类的方法中通过self.__private_attrs调用
    5) 如果类的公有属性和实例公有属性同名,则两者互相不影响;

    (类和实例的私有属性都是只能被类中定义的方法使用)

    3. 方法

    class student(object):
        grade = 'Four'       #类的公有属性,可以被类和实例访问
        __teacher = 'David'  #类的私有属性(以__为前缀),不可以被类和实例访问,只可用于类的方法中调
        def __init__(self,name,age):
            self.name = name #实例的公有属性,可以被实例访问
            self.__age = age #实例的私有属性(以__为前缀),不可以被实例访问,只可用于类的方法中
        def getGrade(self):
            print self.grade
        def getTeacher(self):
            print self.__teacher
        def getName(self):
            print self.name
        def __getAge(self):  #私有方法(以__为前缀),不可以被实例访问
            print self.__age
        def getAge(self):    #公有方法,可以被实例访问
            self.__getAge()
    s = student('Lina',18)
    print '---测试1:类的公有属性可以被类和实例访问'
    print student.grade
    print s.grade
    print '---测试2:类的私有属性不可以被类和实例访问'
    #print student.__teacher
    #print s.__teacher
    print '---测试3: 实例的公有属性,可以被实例访问,但是不能被类访问'
    print s.name
    #print student.name
    print '---测试4, 实例的私有属性,不可以被实例访问'
    #print s.__age
    print '---测试5, 公有属性和私有属性都可以被类的方法中调用'
    s.getGrade()
    s.getTeacher()
    s.getName()
    print '---测试6, 私有方法不可以被实例访问'
    #s.__getAge()
    s.getAge()
    class Dav(student):
        grade = 'one'
        __teacher = 'Mrliu'
        def __init__(self,name,age):
            self.name = name
            self.__age = age
        @staticmethod
        def getStu():
            #print self.grade
            #print self.__teacher
            #print self.name
            #print self.__age
            print '调用静态方法'
        @classmethod
        def getInfo(cls):
            print cls.grade
            print cls.__teacher
            #print self.name
            #print self.__age
            print '调用类方法'
    print '---测试10: 静态方法不能访问类和实例的属性,定义时候也不需要加self参数,可以被实例或者类调用且两者效果一致'
    d = Dav('david', 21)
    d.getStu()
    Dav.getStu()
    print '---测试11: 类方法可以访问类的属性,包含类的公有属性和私有属性,可以被实例或者类调用且两者效果一致'
    dd = Dav('tom', 23)
    dd.getInfo()
    Dav.getInfo()

    总结:
    方法包含实例方法,静态方法,类方法。
    1) 私有方法以两个下划线开头,不可以被实例访问,只能在类的方法中通过self.__private_methods调用
    2) 公有方法,可以被实例访问
    3) 以上说的方法实际都是实例方法,其它还有静态方法,类方法。
    4) 静态方法使用装饰器@staticmethod定义,并且方法参数中不能有self. 类对象和实例都可以调用静态方法,但是无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系;
    5) 类方法使用@classmethod装饰器定义,其第一个参数必须为cls,且不需要self参数。类对象和实例都可以调用类方法,可以访问类属性包含公有属性和私有属性,但是无法访问实例属性。


    还有一种类中普通的方法(没有self参数),这种方法既可以被类直接调用也可以被类的实例对象调用,但是被实例对象调用的时候,要求方法至少有一个参数,因为调用时会将实例对象本身传给第一个参数。staticmethod函数功能就是将这种方法定义成类的静态方法,正确的方法是使用 @staticmethod装饰器,这样在实例对象调用的时候,不会把实例对象本身传入静态方法的第一个参数了。

    4. 构造方法

    class student(object):
        grade = 'Four'       #类的公有属性,可以被类和实例访问
        __teacher = 'David'  #类的私有属性(以__为前缀),不可以被类和实例访问,只可用于类的方法中调用
        def __init__(self,name,age):
            self.name = name #实例的公有属性,可以被实例访问
            self.__age = age #实例的私有属性(以__为前缀),不可以被实例访问,只可用于类的方法中
            print '父类构造函数'
        def getGrade(self):
            print self.grade
        def getTeacher(self):
            print self.__teacher
        def getName(self):
            print self.name
        def __getAge(self):  #私有方法(以__为前缀),不可以被实例访问
            print self.__age
        def getAge(self):    #公有方法,可以被实例访问
            self.__getAge()
    s = student('Lina',18)
    print '---测试1:类的公有属性可以被类和实例访问'
    print student.grade
    print s.grade
    print '---测试2:类的私有属性不可以被类和实例访问'
    #print student.__teacher
    #print s.__teacher
    print '---测试3: 实例的公有属性,可以被实例访问,但是不能被类访问'
    print s.name
    #print student.name
    print '---测试4, 实例的私有属性,不可以被实例访问'
    #print s.__age
    print '---测试5, 公有属性和私有属性都可以被类的方法中调用'
    s.getGrade()
    s.getTeacher()
    s.getName()
    print '---测试6, 私有方法不可以被实例访问'
    #s.__getAge()
    s.getAge()
    class Liming(student):
        def getName(self):
            print self.name
    print '---测试7, 子类未定义构造函数,将默认使用父类构造函数'
    l = Liming('liming', 20)
    l.getName()
    class Liutao(student):
        def __init__(self,name,age,height):
            self.name = name
            self.age =age
            self.height = height
            print '子类自己的构造函数'
        def getName(self):
            print self.name
    print '--测试8,子类定义了构造函数,实例化将使用自己的构造函数'
    lt = Liutao('liutao', 35, 168)
    lt.getName()
    class litao2(student):
        def __init__(self,name,age,height):
            student.__init__(self,name,age)
            self.height =height
            print '子类自己的构造函数'
        def getName(self):
            print self.name
    print '---测试9,子类定义了构造函数,还可以继续调用父类构造函数'
    lt2 = litao2('litao2',20,180)    
    lt2.getName()

    总结:
    1) 如果子类没有定义构造函数,将默认使用父类构造函数;
    2) 如果一个子类从多个父类派生,而子类又没有自己的构造函数,则按顺序继承,
    哪个父类在最前面且它又有自己的构造函数,就继承它的构造函数;如果最前面第一个父类没有构造函数,
    则继承第2个的构造函数,第2个没有的话,再往后找,以此类推。
    3) 如果子类有自己的构造函数,不会自动调用父类的构造函数,只会调用自己的构造函数
    4) 如果需要用到父类的构造函数,则需要在子类的构造函数中显式的调用
    5) 显式调用父类构造函数有两种方法:super以及 通过父类直接调用__init__函数;

    5. 多态

    class A():
        def login(self):
            print 'A'
    class B(A):
        def login(self):
            print 'B'
    class C(A):
        def login(self):
            print 'C'
    def test(a)
        a.login()
    test(B()) 
    test(A())
    test(C())

    总结:
    1) 如果父类方法的功能不能满足需求,可以在子类重写父类的方法。实例对象调用方法时会调用其对应子类的重写后的方法

    6. 继承

    class A:
        pass
    class B(A)
        pass

    总结:
    1) 定义:class 派生类名(基类名)
    2) 特点:
    I: 在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。使用super().__init__()或parentClassName.__init__()
    II: 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
    III: 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

    7. 封装

  • 相关阅读:
    Spring 09 : AOP实例
    Spring08 AOP概念
    Spring 07 : 动态代理
    Spring06 Spring+Junit
    Spring05 : 基于注解的IOC
    Spring03 : 依赖注入
    jupyter修改python核(使用不同的python虚拟环境)
    线性代数的本质——引入几何视角
    图像的去雾与加雾
    从MATLAB看一个IDE应该具有的素质
  • 原文地址:https://www.cnblogs.com/lypy/p/6370444.html
Copyright © 2011-2022 走看看