zoukankan      html  css  js  c++  java
  • Python随笔10

    面向对象最重要的是类和实例,类是抽象的,是具有某些相同属性和方法的集合;实例就是根据类创建出来的一个个对象

    对象=属性+方法

    类的定义:

    class 类名(object) :

      语句

    其中object是指类继承与哪个类,(object)可不写,所有的类都继承与object类

    self参数:

      类中的方法无论是有参还是无参,默认都有第一个参数self,称为实例的引用,它也是方法和函数的区别(除此之外没有任何区别)。这个self参数,你可以将其命名为任意参数,但是最好是默认为self。它相当于Java中的this,在你将类实例化之后赋予一个对象,self参数就是这个对象本身。比如你有一个类Class和这个类的一个实例MyClass,当你调用这个对象的方法MyClass.getName(arg1,arg2)时,其实就是相当于MyClass.getName(MyClass,arg1,arg2)

    init方法:

      在类的一个对象被创建时,会立即运行一个初始化方法init方法,这个方法就相当于Java中的构造函数。在定义时需要注意init前后各有两条下划线__init()__,定义的时候第一个参数还是self。有init方法的类在创建实例化对象的时候必须给它传入和init方法中相匹配的参数,否则函数会报错。子类不能重写父类的构造方法,如果子类的构造方法中用到了父类的构造方法里面的属性,应该考虑继承。

    类的实例化:

      一个类Person()创建之后就会产生一个类对象,通过p = Person()可以创建一个Person类的实例。可以直接通过p来调用类的方法和属性(私有属性不能直接调用)。如果Person类有构造方法,在创建类的实例时,需传入对应的参数。

     类的私有属性:

      类的私有属性一般用两个下划线表示__i,类的实例不能直接访问,需要通过一些方法去访问和处理这些私有属性。这种方式保证了代码的将壮性。

      访问类的私有变量: 

    class Person():
        def __init__(self,name,age):
            self.__name =name
            self.__age = age
        def getName(self):
            return self.__name
        def getAge(self):
            return self.__age
        def setName(self,name):
            self.__name = name
        def setAge(self,age):
            self.__age = age
    
    p = Person("Tom",18)
    print(p.__name)
    print(p.__age)

      这段代码中Person类中的__name和__age属性都是私有属性,如果想直接访问这里面的属性,p.__name和p.__age,会报错

    Traceback (most recent call last):
      File "D:/PythonDemo/hello.py", line 171, in <module>
        print(p.__name)
    AttributeError: 'Person' object has no attribute '__name'

      这是因为,Python将私有变量变为了,_Person__name和_Person__age,但是不要用p._Person__name这样的方式去直接访问私有变量,因为不同版本的解释器会把__name变为不同的变量名。需要写一些方法去访问和改变私有变量。上面代码中的getName()、getAge()、setName()、setAge()方法,是用来访问和改变这些私有变量的。

    p = Person("Tom",18)
    print(p.getAge())
    print(p.getName())
    p.setName("Jerry")
    print(p.getName())
    p.setAge(22)
    print(p.getAge())

      结果为:

    18
    Tom
    Jerry
    22

    封装、继承和多态:

      类的属性和方法都是放在内部的,我们直接可以在外部使用这些方法去访问类的内部数据,不需要在外面重新写方法,也不需要知道实现的细节,这就叫封装,封装还有一个好处就是可以增加类的方法,比如getAge(),外部同样不用知道方法的细节,但是可以去访问类的数据。

      继承:当我们定义一个类时,可以从某个类继承,这个被继承的类叫做父类(SupperClass或者BaseClass)、新类叫做子类(SubClass),所有的类都继承于Object类。比方说定义一个Man()类继承于Person()类,写法应该是class Man(Person):      子类可以继承父类的方法和属性,比如Person类中有eat()方法,则Man()类中不必再写eat()方法,可以直接使用eat()方法,同样,子类也可以重写父类的方法,在子类的实例调用这个方法时,总是会调用子类的方法。

    class Person():
        def __init__(self,name,age):
            self.name =name
            self.age = age
        def eat(self):
            return "i can eat"
    
    class Man(Person):
        pass
    
    m = Man("Tom",12)
    print(m.name)
    print(m.age)
    print(m.eat())

      输出为:

    Tom
    12
    i can eat

      可以看到子类能直接使用类的属性和方法

      再来看子类重写父类的方法“

      

    class Person():
        def __init__(self,name,age):
            self.name =name
            self.age = age
        def eat(self):
            return "i can eat"
    
    class Man(Person):
        def eat(self):
            return "i eat more"
    
    m = Man("Tom",12)
    print(m.name)
    print(m.age)
    print(m.eat())

      输出为:

    Tom
    12
    i eat more

      可以看到,调用的是子类的方法

      如果一个类同时继承多个类,从左到右依次继承,对于继承的方法,也是从左到右依次查找,调用先查找到的方法。比如:

    class People:
        name = ""
        age = 0
        __weight = 0
    
        def __init__(self, n, a, w):
            self.name = n
            self.age = a
            self.__weight = w
    
        def speak(self):
            print("%s说:我今年%d岁,体重是%d公斤" % (self.name,self.age,self.__weight))
    
    
    class Student(People):
        grade = 0
    
        def __init__(self, n, a, w, g):
            People.__init__(self, n, a, w)
            self.grade = g
    
        def speak(self):
            print("%s说:我今年%d岁,读%d年级" % (self.name, self.age, self.grade))
    
    
    class Speaker:
        topic = ""
        name = ""
    
        def __init__(self, n, t):
            self.name = n
            self.topic = t
    
        def speak(self):
            print("%s说,我今天演讲的主题是%s" % (self.name, self.topic))
    
    
    class Sample(Speaker, Student):
        a = ""
    
        def __init__(self, n, a, w, g, t):
            Student.__init__(self, n, a, w, g)
            Speaker.__init__(self, n, t)
    
    test = Sample("小明", 20, 55, 3, "Python")
    print(test.speak())

      Sample(Speaker,Student)类继承于Speaker()和Student(),那么输出的结果为:

    小明说,我今天演讲的主题是Python

      如果把继承的顺序变为Sample(Student,Speaker),那么输出的结果为:

    小明说:我今年20岁,读3年级

      同时从”People.__init__(self, n, a, w)“也可以看出,子类在写构造方法时,可以直接使用父类.__init__(self,arg1,arg2...)的方式继承父类的构造方法里的属性

      多态:Python本身就是一种多态类的语言,如果某些类具有相同的方法,我们可以把它们看作同一类型的。如果Cat类和Dog类都继承于Animal类,它们都有behaviour()方法。我们可以把Animal、Cat、Dog看成Animal、Cat、Dog类型的数据,同时Cat和Dog也是Animal类型的数据,但是反过来就不成立了。我们写一个函数叫做beh,有方法behaviour(),参数类型为Animal类型,这样我们就可以往里面传入Animal、Cat和Dog类型的参数,同时如果我们新建一个类Bird(Animal)继承于Animal,也不必修改beh函数。

    class Animal:
        def behaviour(self):
            print("Animal can run")
    
    class Cat(Animal):
        def behaviour(self):
            print("Cat can miaomiaomiao")
    
    class Dog(Animal):
        def behaviour(self):
            print("Dog can wangwangwang")
    
    lst = [Animal(),Cat(),Dog()]
    for items in lst:
            print(items.behaviour())
    print("===============================")
    def beh(animal):
        animal.behaviour()
    print(beh(Animal()))
    print(beh(Cat()))
    print(beh(Dog()))

      结果为:

    Animal can run
    None
    Cat can miaomiaomiao
    None
    Dog can wangwangwang
    None
    ===============================
    Animal can run
    None
    Cat can miaomiaomiao
    None
    Dog can wangwangwang
    None

      我们只需关注,这个这个参数是Animal类型的就行了,至于具体的是属于Cat类型还是属于Dog类型,则需要看传入的参数是什么,而且当我们新增一个类Bird继承于Animal时,不需要去修改这个函数,只需要保证这个函数的正确性即可,这个就是多态便利性的一个体现。

    
    
    

      

  • 相关阅读:
    MVC,MVP,MVVM的区别
    jQuery Mobile 实现苹果滑动删除闹钟功能的几点总结
    AngularJS执行流程详解
    基于angularJS的表单验证练习
    jQuery 中 attr() 和 prop() 方法的区别
    天猫消息盒子的CSS实现
    jQuery事件之传递参数
    浅谈js中的垃圾两种回收机制
    js中的DOM操作汇总
    log4net
  • 原文地址:https://www.cnblogs.com/bigbigtong/p/10089235.html
Copyright © 2011-2022 走看看