zoukankan      html  css  js  c++  java
  • Python面向对象(一)

    Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
     
    一、面向对象技术简介
    • 类(class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

    • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

    • 数据成员:类变量或者实例变量用于处理类及其例对象的相关的数据。

    • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。

    • 实例变量:定义在方法中的变量,只作用于当前实例的类。

    • 继承:即一个派生类继承基类的字段和方法。继承也允许把一个派生类的对象作为一个基类的对象对待。例如,有这样一个设计:一个dog类型的对象派生自animal类,这是模拟“是一个”关系(例如,dog是一个animal)

    • 实例化:创建一个类的实例,类的具体对象。

    • 方法:类中定义的函数

    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

     
    二、什么是面向对象的程序设计及为什么要有它

    面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

    优点是:极大的降低了程序的复杂度,复杂的问题简单化,流程化

    缺点是:扩展性差,一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得大改,改一个组件,牵一发而动全身。

    应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

    面向对象的程序设计的核心是对象(上帝式思维),对象是特征(变量)与技能(函数)的结合体,要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。

    在现实世界中:对象----(共同的特征与技能)--->类

    在程序中:先定义类----(实例化)----->对象

    应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方

    优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

    缺点:可控性差;编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合

     面向对象的设计并不是全部。对于一个软件质量来说,面向对象的程序设计只是用来解决扩展性。
    三、类和对象
    """
    类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体。
    那么问题来了,先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看
    在现实世界中:先有对象,再有类
    世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
    也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
    在程序中:务必保证先定义类,后产生对象
    这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
    不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
     
    """
    概述

    3.1 什么是对象,什么是类

    Python中一切皆为对象,且Python统一了类与类型的概念,类型就是类

    类定义

    语法格式如下:

    1.
    class 类名:    # 类名首字母大写
        '''注释'''
        类体
    2.
    class ClassName:
        <statement-1>
        .
        .
        .
        <statement-N>

    类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。

    类对象

    类对象支持两种操作:属性引用和实例化

    属性引用使用和Python中所有的属性引用一样的标准语法:obj.name

    类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样的:

    class Myclass:
        """一个简单的类实例"""
        i=12345
        def f(self):
            return 'hello world'
    # 实例化类
    x=Myclass()
    # 访问类的属性和方法
    print("MyClass 类的属性i为:",x.i)
    print("MyClass 类的方法f输出为:",x.f())

    以上创建了一个新的类实例并将对象赋给局部变量x,x为空的对象。

    输出结果为:

    MyClass 类的属性i为: 12345
    MyClass 类的方法f输出为: hello world
    

    很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为__init__()的特殊方法(构造方法),像下面这样:

     
    def __init__(self):
            self.data = []    #定义空列表

    当然,__init__()方法可以有参数,参数通过__init__()传递到类的实例化操作上。例如:

    class Teacher:
        school='oldboy'    #定义对象的共同特征
        def __init__(self,name,age):    #用户创建对象传入的参数
            self.name=name
            self.age=age
        def talk(self):
            print('is talking')
        def walk(self):
            print('is walking')
    t1=Teacher('egon',23)   # 实例化:__init__(t1,'egon',23)
    t2=Teacher('alex',32)   # 实例化:__init__(t2,'alex',32)
    self代表类的实例。而非类
    类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例它的名称是self。
    # 属性引用
    # 数据属性
    # print(Teacher.school)
    # print(Teacher.__dict__)
    # 函数属性
    # print(Teacher.walk)
    # print(t1.name)
    # print(t2.talk)
    

      

    类的方法

    在类的内部,使用def关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数,self代表的是类的实例。

    #类定义
    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 岁。" %(self.name,self.age))
    # 实例化类
    p = people('runoob',10,30)
    p.speak()

    类有两种作用:属性引用和实例化

    1)属性引用(类名.属性)

    class Student:
        school = 'oldboy'
        def __init__(self,name,age):
            #只用来初始化的,并且一定不能有返回值
            self.name=name
            self.age=age
        def study(self):
            print('%s is studying' %self.name)
    
    s1=Student('egon',84)    #步骤一:造出对象s1  #步骤二:初始化s1,把s1,'egon',84传给__init__
    __init__只用来初始化函数的,并且一定不能有返回值
    数据属性、函数属性:
    print(Student.school)    #引用类的数据属性    #输出结果:oldboy
    print(Student.study)    #引用类的函数属性    #输出结果:<function Student.study at 0x00000149F72B7620>
    

    对象的修改、删除和添加:

    #修改
    Student.school='偶的博爱'    #修改变量school的值
    print(Student.school)        #输出结果:偶的博爱
    
    #删除
    del Student.school    #删除school属性的值
    print(Student.__dict__)    #类名.__dict__:查出的是一个字典,key为属性名value为属性值
    
    输出结果:(上面为没删除之前,删除之后,通过__dict__可查看到类的信息)
    {'__module__': '__main__', 'school': '偶的博爱', '__init__': <function Student.__init__ at 0x000001BB20097598>, 'study': <function Student.study at 0x000001BB20097620>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
    {'__module__': '__main__', '__init__': <function Student.__init__ at 0x000001BB20097598>, 'study': <function Student.study at 0x000001BB20097620>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
    
    #添加
    Student.x=6666666666666    #添加一个属性x=6666666666666
    print(Student.x)    
    print(Student.__dict__)    #可查看到字典里多了一值

    只要是对象绑定方法都会字典传值,把自己传给函数

    s1.study()   #调用函数 egon is studying
    

     补充:

    类有两种属性:数据属性和函数属性
    1 类的数据属性是所有对象共享的
    2 类的函数属性是绑定给对象用的
    
    类的数据属性是所有对象共享的,id都一样
    类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样
    
    ps:id是python的实现机制,并不能真是反映内存地址,如果有内存地址,还是以内存地址为准
    
    在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类(基类),最后都找不到就抛出异常
    
    类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数
    
    类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向都是相同的功能,但是绑定到不同的对象就是不同的绑定方法
    
    强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)
     
    2)我们定义的类的属性到底存在哪里了?有两种方式查看
    dir(类名):查出的是一个名字列表
    类名.__dict__:查出的是一个字典,key为属性名,value为属性值
     
    3)特殊的类属性
    类名.__name__ # 类的名字(字符串)
    类名.__doc__    # 类的文档字符串
    类名.__base__    # 类的第一父类
    类名.__bases__ # 类所有父类构成的元组
    类名.__dict__ # 类的字典属性
    类名.__module__ # 类定义所在的模块
    类名.__class__ # 实例对应的类(仅新式类中)
    4)对象/实例
    对象/实例本身只有数据属性,但是Python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法,绑定方法唯一绑定一个对象,同一个类的方法绑定到不同的对象上,属于不同的方法,内存地址都不会一样
    对象的绑定方法的特别之处在于:obj.func()会把obj传给func的第一个参数
     
    5)类名称空间与对象/实例名称空间
    创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
    而类有两种属性:数据属性和函数属性
    其中类的数据属性是共享给所有对象的,而类的函数属性是绑定到所有对象的
     
    创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
    在obj.name会优先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类,最后都找不到就抛出异常
     
    6)对象之间的交互
    class Garen:        #定义英雄盖伦的类,不同的玩家可以用它实例出自己英雄;
        camp='Demacia'  #所有玩家的英雄(盖伦)的阵营都是Demacia;
        def __init__(self,nickname,aggressivity=58,life_value=455): #英雄的初始攻击力58...;
            self.nickname=nickname  #为自己的盖伦起个别名;
            self.aggressivity=aggressivity #英雄都有自己的攻击力;
            self.life_value=life_value #英雄都有自己的生命值;
        def attack(self,enemy):   #普通攻击技能,enemy是敌人;
            enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。

    我们可以仿照garen类在创建一个Riven类

    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 #根据自己的攻击力,攻击敌人就减掉敌人的生命值。

    实例出俩英雄

    >>> g1=Garen('草丛伦')
    >>> r1=Riven('锐雯雯')

    交互:锐雯攻击草伦,反之一样

    >>> g1.life_value
    455
    >>> r1.attack(g1)
    >>> g1.life_value
    401 
    练习一堆类:
    # 老师类
    class Teacher:
        school='oldboy'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talk(self):
            print('is talking')
        def walk(self):
            print('is walking')
    t1=Teacher('egon',23)   # 实例化:__init__(t1,'egon',23)
    t2=Teacher('alex',32)   # 实例化:__init__(t2,'alex',32)
    

      

    # 学生类
    class Student:
        job='student'
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def talk(self):
            print('is talk')
        def eat(self):
            print('is eating')
    s1=Student('buer',20)    # 实例化:__init__(s1,'buer',20)
    s2=Student('dongbei',22) # 实例化:__init__(s2,'dongbei',22)
    print(s1)
    

      

    # 狗类
    class Dog:
        bottle='dog'
        def __init__(self,name,color):
            self.name=name
            self.color=color
        def talk(self):
            print('汪汪汪')
        def eat(self):
            print('dog good')
    d1=Dog('哈士奇','blank')   # 实例化:__init__(d1,'哈士奇','blank')
    d2=Dog('泰迪','brown')    # 实例化:__init__(d2,'泰迪','brown')
    

      

    # 猪类
    class Pig:
        bottle='big'
        def __init__(self,name):
            self.name=name
        def talk(self):
            print('哼哼哼')
        def eat(self):
            print('pig good')
    p1=Pig('xiangzhu')  # 实例化:__init__(p1,'xiangzhu')
    p2=Pig('huazhu')    # 实例化:__init__(p2,'huazhu')
    print(p1)
    

      

    # 动物类
    class Animal:
        local='zoo'
        def __init__(self,name,kind):
            self.name=name
            self.kind=kind
        def talk(self):
            print('people do not know what to say')
        def pull(self):
            print('no need for toilet')
    a1=Animal('xingxing','monkey')
    a2=Animal('fenda','panda')
    

      

  • 相关阅读:
    eclipse安装插件最简单的方法!!
    mysql数据库导入sql文件的方法。
    拿起丢掉的东西,才叫做坚持。
    个人总结作业
    黄金点游戏程序注解
    结对项目的完成与体会
    第三周任务学习记录
    vs2013的安装与使用 测试
    习题作业
    对于四则运算编程自己的过程问题
  • 原文地址:https://www.cnblogs.com/shenbuer/p/7375523.html
Copyright © 2011-2022 走看看