zoukankan      html  css  js  c++  java
  • python入门(十二):面向对象

    1、场景:
    玩过游戏。主人公,进入了一个场景,有10个小怪物是一样的。有攻击力,血(100格)。如果小怪物有多个数值需要管理,小怪物的血量、小怪物出现在屏幕的地点。

    可以使用字典来进行记录:

    {"blood":100,"location":"10,10"}
    [[100,(10,10)]]

    10 个小怪物。记住10个小怪物所有的变量在哪里,怎么操作?

    写一些函数,来操作这些数据。
    函数你实现的时候,你觉得需要实现哪些功能?

    10个方法:所有操作的数据的方法

    add_blood():
    blood+=1

    minus_blood():
    blood-=1

    move():
    x-=10
    y-=10

    类的好处:

        1) 把数据封装到实例里面,用同一的规则来进行存取,保证数据的安全和一致性

        2)基于类,方便进行扩展 (设计模式)

        3)类相当于模板,可以通过构造函数做初始化,快速生成实例

     class soldier(): #小怪物的类

        """小怪物的类,类定义"""

        def __init__(self,blood,location_x,location_y):    #构造函数,用来传参,可以无参
            self.blood = blood
            self.location_x = location_x
            self.lcoation_y = location_y

        def add_blood(self,num):    #实例方法:方法中有self参数
            if self.blood<=100:
                self.blood+=num
                if self.blood>100:
                    self.blood = 100

        def minus_blood(self,num):    #实例方法:方法中有self参数
            if self.blood>=0:
                self.blood-=num
                if self.blood<0:
                    self.blood = 0

        def tell_blood(self):    #实例方法:方法中有self参数
            return self.blood

    s1= soldier(100,10,10)    #实例化,传参
    s2= soldier(90,10,20)    #实例化,传参
    s3= soldier(80,10,30)    #实例化,传参

    print(s1.tell_blood())    #调tell_blood函数,输出每个小怪物的血量
    print(s2.tell_blood())
    print(s3.tell_blood())
     
     

    """小怪物的类,类定义"""

    class soldier():

        def __init__(self,blood,location_x,location_y):   #构造函数,用来传参,可以无参

            self.blood=blood

            self.location_x=location_x

            self.location_y=location_y

     

        def add_blood(self,num):                    #实例方法:方法中有self参数

            if self.blood<=100:

                self.blood+=num

                if self.blood>100:

                    self.blood=100

            return self.blood

     

        def minus_blood(self,num):                   #实例方法:方法中有self参数

            if self.blood>=0:

                self.blood-=num

                if self.blood<0:

                    self.blood=0

            return self.blood

     

        def tell_blood(self):                          #实例方法;方法中有self参数

            return self.blood

     

    s1=soldier(89,10,10)       #实例化,用模板做出来的东西,传参

    s2=soldier(67,10,20)       #实例化,用模板做出来的东西,传参

    s3=soldier(23,10,30)       #实例化,用模板做出来的东西,传参

     

    print(s1.add_blood(70))     #调用add_blood函数,给小怪物1加血

    print(s2.minus_blood(80))   #调用minus_blood函数,给小怪2物减血

    print(s3.add_blood(80))     #调用add_blood函数,黑小怪物3加血

    运行结果:

    E:>python a.py

    100

    0

    100

     

    2、类:(相关数据存在一起,并且有一组操作相关数据的方法)

        1)数据(属性)
        2)方法(类里面写的函数叫做方法。)

    类比说明:
    生产杯子,杯子的模具(类),可以设定不同的参数来生产杯子。
    设定好不同的参数(通过构造函数传参),生产出具体的杯子(实例化)。
    类:soldier
    实例化:传入不同的参数(调用构造函数)
    s1
    s2
    s3

    3、批量生成实例化对象

    import math
    class circle(object):    #object可写可不写

        def __init__(self,radius):
            self.radius = radius    #radius这个变量在构造函数里,是一个局部变量,走出构造函数,radius这个变量是不能使用的。如果要使用该变量值,需要存在一个带self.的变量中,才能在其他的类方法中使用该值
        def get_area(self):
            return math.pi*self.radius*self.radius    #self.XXX称作实例变量

        def get_perimeter(self):
            return 2*math.pi*self.radius

    for i in range(1,6):
        a= circle(i)
        print(a.get_area())
        print(a.get_perimeter())

    #self.xxxx实例变量
    #在类里面定义的函数叫做方法

    def add():#函数
      return a+b

     
    4、类:封装了数据,和操作数据的规则,保证数据的安全。

    1. 如果用列表存储数据:

     a=[1,2,3]  #只存正数的列表
     1)也可使用函数来限制输入的数字
    def set(a,index,new_value):
        if new_value>=0:     #当输入的值>=0时,新值会替代原始数据
            a[index] = new_value

    set(a,0,100)      #新输入的值为100大于0,替换a[0]的值    
    print(a)
    set(a,0,-50)    #新输入的值为-50,小于0.不会替换a[0]的值
    print(a)

    2)但是无法限制别人修改值

    a[0]=-50      
    print(a)
     

    2. 用类来实现限制修改输入负数

     class positive_num_list(object):

        def __init__(self,a):
            self.__value = a    #将输入的列表值赋值给实例变量

        def set(self,index,value):
            if value<0:    #当输入的值为负数时,什么都不做
                return
            self.__value[index] = value    #当输入的不为负数时,替换a中的数据;两个下划线是私有变量,除了类中的实例方法可以访问,外部不可以直接访问和修改
        def get(self):
            return self.__value    #读取列表中的值

    p= positive_num_list([1,2,3,4])    #a=[1,2,3,4]

    p.__value[0]=-100    #类保护了数据被修改

    运行结果:

    AttributeError: 'positive_num_list' object has no attribute '__value'    


    print(p.get())    #结果:[1, 2, 3, 4]

    p.set(1,50)    #试图替换a[1]的值为50
    print(p.get())   #读取替换后的值,结果:[1, 50, 3, 4]


    print(set([1,1,2,2]))

    结果:{1, 2}  #set集合去重

     

    class positive_num_list(object): 

        def __init__(self,a):

            self.value=a                      #实例变量没有双下划线

        def set(self,index,value):

            if value<0:

                return

            self._value[index]=value

        def get(self):

            return self._value

    p=positive_num_list([1,2,3,4])

    p.value[0]=-8                             #尝试修改数值

    print(p.get())

    运行结果:

    E:>python a.py

    [-8, 2, 3, 4]                           #数据依然被是修改成功,说明私有变量的重要性

     

    3.用类来限制修改半径:

     import math
    class circle(object):

        def __init__(self,radius):
            if radius<=0:    #当输入值是<=0的数时,将输入值重新赋值为1
                self.radius = 1
            else:
                self.radius = radius
            

        def modify_radius(self,radius):    #可以定义一个方法,限制输入值是负数
            if radius<0:
                self.radius = abs(radius)
            elif radius==0:
                self.radius = 1

        def get_area(self):
            return math.pi*self.radius*self.radius

        def get_perimeter(self):
            return 2*math.pi*self.radius

    c=circle(-1)    #走构造函数的程序
    print(c.get_area())
    c.modify_radius(-2)    #调用modify_radius方法
    print(c.get_area())
     
    5、self
     class P:

        def __init__(self,value): #构造方法,初始化的
            self.value = value     #value局部变量,self.value叫做实例变量
    p =P(10)
    print(p.value)
    p.value=-10
    print(p.value)
     
     
     class P:

        def __init__(self,value): #构造方法,初始化的
            self.__value = value     #value局部变量,self.value叫做实例变量
    p =P(10)
    print(p.__value)    #私有变量
     
     
     class P:

        def __init__(self,value): #构造方法,初始化的
            self.__value = value     #value局部变量,self.value叫做实例变量
        def get(self):              #实例方法
            return "***:"+str(self.__value)
        def set(self,value):           #实例方法
            if isinstance(value,(int,float)):
                self.__value = value
            return None

    p =P(10)
    print(p.get())    #私有变量
    p.set("a")
    print(p.get())    #私有变量
    p.set(-5)
    print(p.get())    #私有变量
     
     
     class P:

        def __init__(self,value): #构造方法,初始化的
            self.__value = value   #value局部变量,self.value叫做实例变量
        def get(self):  #实例方法
            return "***:"+str(self.__value)
        def set(self,value):  #实例方法
            if isinstance(value,(int,float)):
                self.__value = value
            return None

    p1 =P(1)
    p2 =P(2)
    p3 =P(3)

    内存中的位置:A
    P:类变量
    类定义的方法

    类中所有定义的方法,类变量,只有一份

    实例在内存中:有0个,1个或多个
    内存中的位置:b
    p1的实例:self.__value=1

    内存中的位置:c
    p2的实例:self.__value=2

    内存中的位置:d
    p3的实例:self.__value=3

    p1.get()--->p1的实例调用get的方法:调用的时候,会把内存位置b发送给类定义的方法P.get
    self:是一个方法的参数,该参数传的值是内存b的位置

    get方法从内存b的位置找到__value值,然后执行方法中的代码。

    但是定义的时候:def get(self),有self参数,调用的时候p1.get(),没有self.

    实际get拿到了self的地址(该方法在内存中的位置b),找到了__value值

    如果不把self的值传过去,找不到value所在的内存地址,方法执行失败


    self传递的是某个实例的地址。实例地址里面的所有变量都可以在方法中进行使用。

     
     p3.set(1,2) #p3的地址传递给了self,1-》value,2是多余的。。
    TypeError: set() takes 2 positional arguments but 3 were given
     
     
    类中方法参数包含self的方法:实例方法
    每个实例方法,只能操作本实例中的实例变量。

    变量前面带有self.的叫做实例变量,可以在多个方法中访问,实例变量都存在对应的实例所在的内存地址中。

    如果不加self.的叫做局部变量,不能跨方法访问

     

    class P(object):

     

        def __init__(self,value):        #构造方法,初始化的

            value1=value           #value1和value局部变量,不能跨方法访问

        def get(self):

            return value1          #在这个方法中返回value1

     

    p1=P(1)

    print(p1.get())

    运行结果

    E:>python a.py

    Traceback (most recent call last):

      File "a.py", line 10, in <module>

        print(p1.get())

      File "a.py", line 7, in get

        return value1

    NameError: name 'value1' is not defined  #value1未定义

     

    总结:
     
     类:
       1 可以封装数据,制定数据的存储规则,保证数据的安全
       2 类相当于模板,可以通过构造函数做初始化,快速生成实例
       3 基于类,可以进行扩展。(设计模式)
       4 内存中存储的类变量和方法,只有一份。每个类的实例,都在内存中有一个地址(类产生的实例可以有0个、1个或多个)
       5 类中定义的实例方法(方法中有self参数),可以操作每个实例中封装的变量
       6 实例变量(self.开头的)可以在不同的实例方法中被访问。实例变量都存在对应的实例所在的内存地址中。
       7 __变量是私有变量,除了类中的实例方法可以访问,外部不可以直接访问和修改。
     
     
     

     

     

     

     
     

     

     

     

  • 相关阅读:
    提取左公因子
    如何使用正则表达式构造相对应的ε-NFA
    DFA-NFA 简单介绍 怎么区分
    编译原理 短语 直接短语 定义
    编译原理 符号表为什么设计字符串表这样的结构?
    编译原理 词法分析
    paper 自动翻译论文软件推荐
    github 单个文件超过100M 解决办法 Git LFS 使用
    马哥博客作业第四周
    马哥博客作业第三周
  • 原文地址:https://www.cnblogs.com/suitcases/p/10480328.html
Copyright © 2011-2022 走看看