zoukankan      html  css  js  c++  java
  • Python基础--面向对象

    本篇博客主要写类、面向对象定义,三大特性:封装、继承、多态,也会简单的介绍魔法(后面将写一篇博文概述)。

    面向对象

      目前面向对象还没有统一的定义,面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。简单一点来概述,面向对象就是使用对象进行程序设计。

    (1)面向对象与面向过程的区别

    • 面向过程,是根据业务逻辑所需要的步骤,使用函数将这些步骤一步一步实现,使用的时候一个一个依次调用即可。
    • 面向对象,将业务逻辑抽象成多个对象,然而在对象中用属性和行为(方法)的定义来描述业务逻辑。

    (2)面向对象和面向过程的优缺点

    • 面向过程

      优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。    
      缺点:没有面向对象易维护、易复用、易扩展

    • 面向对象

      优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护   
      缺点:性能比面向过程低

    (3)面向对象最重要的两个基本概念

      类:类由属性(一些特征数据)和方法(行为)组成,拥有相同或者相近属性、行为的事物可以抽象成为一个类。类往往是抽象的、没有实体。  

      对象:根据所属模板创造出来的实实在在的事物。在程序中我将这个实实在在的事物称之为实例,我们为它的属性赋上特定的值。  

    #定义类
    class Student(object):
        #初始化属性值
        def __init__(self,name,stuId,age):
            self.name = name
            self.stuId = stuId
            self.age = age
        #print输出对象时被调用
        def __str__(self):
            introduce = "我是: " + self.name + ",学号: " + str(self.stuId)  + ",年龄: " + str(self.age) + ""
            return introduce
    
        def study(self):
            print("我会学习")
    #创建对象
    Ming = Student("小明",123545,18)
    print(Ming)
    Ming.study()
    
    输出:
        我是: 小明,学号: 123545,年龄: 18岁
        我会学习
      

    注:定义类对象时一定要传入一个参数self可以为其他字符,便于可读性约定俗成为self,self相当于Java、C++中的this。由于类方法与对象实例相关,Python语言在定义类方法时必须传入一个self,否则报错:study() takes 0 positional arguments but 1 was given。

    封装

    当我们要修改对象属性时,通常有两种方法:

    1. 对象名.属性名 =  数据  (直接修改)
    2. 对象名.方法名()    (间接修改)

    由于直接修改的修改可能导致属性数据不合理,为了更好的保存属性安全性,即不可随意修改,我们有如下的处理方式:

    1. 定义私有属性。不像其他语言有private 、public等关键字修饰,Python直接用双下划线“__”表示私有属性,可以修饰属性和方法。
    2. 对外提供访问的接口。通常使用getXXX()、setXXX()实现,不过Python中还可以使用property属性来实现。
    class Money(object):
    
        def __init__(self,money):
            self.__money = money
        
        def getMoney(self):
            return self.__money
    
        def setMoney(self,value):
            if isinstance(value,int): #内建函数判断输入类型
                self.__money = value
            else:
                print("error:不是整数,%s"%type(value))
        #通过property提供外部访问
        money = property(getMoney,setMoney)
    ming = Money(100)
    print("-1-",ming.getMoney())
    ming.setMoney(200)
    print("-2-",ming.getMoney())
    print("="*30)
    print("property获取属性值:money=%d"%ming.money)
    ming.money = 555
    print("property修改属性值:money=%d"%ming.money)
    
    输出:
    -1- 100
    -2- 200
    ==============================
    property获取属性值:money=200
    property修改属性值:money=555

      启动python解释器,输入dir(__builtins__), 可以看到很多python解释器启动后默认加载的属性和函数,这些函数称之为内建函数, 这些函数因为在编程时使用较多,cpython解释器用c语言实现了这些函数,启动解释器时默认加载,可以直接调用。

    继承

      Python语言支持多继承,在定义类时小括号()里面的即为父类名字,子类可以继承父类的属性、方法,但是私有属性、方法都是不对外公开的,所以不可被继承和访问。

    class Animal(object):
    
        def __init__(self,name):
            self.name = name
    
        def eat(self):
            print("Animal----eat()")
        def run(self):
            print("Animal----不能飞,只能奔跑。。。")
    
    class Cat(Animal):
    
       def eat(self):
            print("cat----重写父类----eat()")
       def sleep(self):
            print("cat----我的爱好是睡觉")
    
    miao = Cat("哆啦A梦")
    print("我是:%s"%miao.name)
    miao.eat()
    miao.run()
    miao.sleep()
    
    输出:
        我是:哆啦A梦
        cat----重写父类----eat()
        Animal----不能飞,只能奔跑。。。
        cat----我的爱好是睡觉

    多态

      不同子对象调用相同的父类方法,在运行时产生不同的结果。多态以继承和重写父类方法为前提,增加了代码的灵活性,是调用方法的技巧,不会影响到类的内部设计。

    class Dog(object):
        def __init__(self,name):
            self.name = name
        def game(self):
            print("%s 很开心的玩耍。。。"%self.name)
    
    class XiaoTianQuan(Dog):
        def game(self):
            print("%s 飞到天上玩..."%self.name)
    
    class Person(object):
        def __init__(self,name):
            self.name = name
        def gameWithDog(self,dog):
            print("%s 和 %s玩的停不下来"%(self.name,dog.name))
            dog.game()
    
    xiaoHuaGou = Dog("小花狗")
    Jack = Person("杰克")
    Jack.gameWithDog(xiaoHuaGou)
    xtq = XiaoTianQuan("哮天犬")
    Jack.gameWithDog(xtq)
    
    输出:
        杰克 和 小花狗玩的停不下来
        小花狗 很开心的玩耍。。。
        杰克 和 哮天犬玩的停不下来
        哮天犬 飞到天上玩...

    类属性、实例属性

    前面几个类在__init__中的属性就是实例属性,Python中所谓的类属性相当于java、C++中的类静态成员变量,即类属性就是类对象所拥有的属性,它被所有类对象的实例对象共有,在内存中只存在一个副本。对于公有类属性在类外可以通过类对象和实例对象访问,私有就无法访问了。

    class Person(object):
        address = "上海"   #类属性
    
        def __init__(self,name,age):
            self.name = name #实例属性
            self.age = age
    person = Person("华仔","18")
    print("实例属性:",person.name,person.age)
    print("类属性:",Person.address)
    #下面报错:AttributeError: type object 'Person' has no attribute 'name'
    #print(Person.name)  
    
    print("通过实例对象修改类属性address:")
    print("---修改前---")
    print("类属性:",Person.address)
    print("实例属性:",person.address)
    person.address = "武汉"
    print("---修改后---")
    print("类属性:",Person.address)
    print("实例属性:",person.address)  #实例属性会屏蔽同名类属性
    del person.address     #删除实例对象属性
    print("---实例属性:",person.address)
    
    输出:
    实例属性: 华仔 18
    类属性: 上海
    通过实例对象修改类属性address:
    ---修改前---
    类属性: 上海
    实例属性: 上海
    ---修改后---
    类属性: 上海
    实例属性: 武汉
    ---实例属性: 上海

      如果需要在类外去修改类属性,必须通过类对象引用去修改;如果使用实例对象引用去修改,实际上产生的是一个同名的实例属性,这种方式修改的是实例属性,并不会改变类属性的值(这一点可以类似理解为全局变量和局部变量)。之后如果通过实例对象去引用该名称的实例属性,实例属性将屏蔽类属性,即此时引用的是实例属性,除非删除这个实例属性。

    类方法、静态方法

    • 类方法是类对象拥有的方法,需要用修饰器@classmethod标识的方法,对于类方法第一参数必须是类对象,一般使用cls作为第一个参数(可以用其他字符,约定俗成用cls),可以使用实例对象和类对象引用去访问。类方法有一个重要作用是可以修改类属性。
    class People(object):
        city = "北京"
    
        @classmethod
        def getCity(cls):
            return cls.city
    
        @classmethod
        def setCity(cls,city):
            cls.city = city
    
    people = People()
    #可以通过实例对象引用类方法
    print(people.getCity())
    #通过类对象引用类方法
    print(People.getCity())
    #修改类属性
    people.setCity("上海")
    print(people.getCity())
    print(People.getCity())
    
    输出:
    北京
    北京
    上海
    上海

    当类方法修改类属性之后,实例对象、类对象访问的类属性都将发生变化。

    • 静态方法,使用修饰器@staticmethod来修饰,静态方法没有必须参数;类方法第一参数必须是cls、通过cls引用的一定是类对象的属性和方法;实例方法第一参数是self,通过self引用的可能是类属性、也可能实例属性,当self引用出现类属性和实例属性名称一样时,实例属性高于类属性。静态方法如果要引用类属性,必须同过类对象来引用。
    class People(object):
        country = "china"
    
        @staticmethod
        def getCountry():
            return People.country
    print(People.getCountry())
    people = People()
    print(people.getCountry())
    
    输出:
        china
        china
  • 相关阅读:
    Codeforces 611C. New Year and Domino 动态规划
    POJ2585 Window Pains 拓扑排序
    HDOJ1242 Rescue(营救) 搜索
    codeforces 数字区分 搜索
    ZOJ2412 Farm Irrigation(农田灌溉) 搜索
    hdu 4389 X mod f(x) 数位dp
    hdu 4734 F(x) 数位dp
    Codeforces Beta Round #51 D. Beautiful numbers 数位dp
    hdu 3652 B-number 数位dp
    bzoj 1026: [SCOI2009]windy数 数位dp
  • 原文地址:https://www.cnblogs.com/jsnhdream/p/10023942.html
Copyright © 2011-2022 走看看