面向对象基础

2018-08-28  本文已影响3人  UlissesJr

类的相关知识     

初识类
声明函数
def functionName(args):
     '函数文档字符串'
      函数体 

声明类
'''
class 类名:
    '类的文档字符串'
    类体
'''

#我们创建一个类
class Data:
    pass


class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法,也叫动态属性
        print("person is walking...")
类有两种作用:属性引用和实例化

    属性引用(类名.属性)

class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def walk(self):  #人都可以走路,也就是有一个走路方法
        print("person is walking...")


print(Person.role)  #查看人的role属性
print(Person.walk)  #引用人的走路方法,注意,这里不是在调用

    实例化:类名加括号就是实例化,会自动触发init函数的运行,可以用它来为每个实例定制自己的特征

class Person:   #定义一个人类
    role = 'person'  #人的角色属性都是人
    def __init__(self,name):
        self.name = name  # 每一个角色都有自己的昵称;
        
    def walk(self):  #人都可以走路,也就是有一个走路方法
        print("person is walking...")


print(Person.role)  #查看人的role属性
print(Person.walk)  #引用人的走路方法,注意,这里不是在调用

实例化的过程就是类——>对象的过程

    原本我们只有一个Person类,在这个过程中,产生了一个egg对象,有自己具体的名字、攻击力和生命值。

语法:对象名 = 类名(参数)

egg = Person('gan')  #类名()就等于在执行Person.__init__()
#执行完__init__()就会返回一个对象。这个对象类似一个字典,存着属于这个人本身的一些属性和方法。

    查看属性&调用方法

print(egg.name)     #查看属性直接 对象名.属性名
print(egg.walk())   #调用方法,对象名.方法名()

    关于self
    self:在实例化时自动将对象/实例本身传给init的第一个参数,你也可以给他起个别的名字,但是正常人都不会这么做。
因为你瞎改别人就不认识
    类属性的补充

一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值

二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
对象的相关知识

    回到咱们的人狗大战:现在我们需要对我们的类做出一点点改变
人类除了可以走路之外,还应该具备一些攻击技能。

class Person:  # 定义一个人类
    role = 'person'  # 人的角色属性都是人

    def __init__(self, name, aggressivity, life_value):
        self.name = name  # 每一个角色都有自己的昵称;
        self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
        self.life_value = life_value  # 每一个角色都有自己的生命值;

    def attack(self,dog):  
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.life_value -= self.aggressivity

egg = Person('gan',10,1000)
print(egg.name)
print(egg.aggressivity)
print(egg.life_value)


当然了,你也可以引用一个方法,因为方法也是一个属性,只不过是一个类似函数的属性,我们也管它叫动态属性。
引用动态属性并不是执行这个方法,要想调用方法和调用函数是一样的,都需要在后面加上括号

print(egg.attack)

对象是关于类而实际存在的一个例子,即实例
对象/实例只有一种作用:属性引用

    我知道在类里说,你可能还有好多地方不能理解。那我们就用函数来解释一下这个类呀,对象呀到底是个啥,你偷偷的用这个理解就好了,不要告诉别人

这里把self理解成一个空的列表,属性由__init__进行初始化

def Person(*args,**kwargs):
    self = {}
    def attack(self,dog):
        dog['life_value'] -= self['aggressivity']

    def __init__(name,aggressivity,life_value):
        self['name'] = name
        self['aggressivity'] = aggressivity
        self['life_value'] = life_value
        self['attack'] = attack

    __init__(*args,**kwargs)
    return self

egg = Person('egon',78,10)
print(egg['name'])
面向对象小结——定义及调用的固定模式
class 类名:
    def __init__(self,参数1,参数2):
        self.对象的属性1 = 参数1
        self.对象的属性2 = 参数2

    def 方法名(self):pass

    def 方法名2(self):pass

对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                  #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                  #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                  #结果返回一个对象
对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
对象之间的互动

创建一个狗类,狗就不能打人了,只能咬人,所以我们给狗一个bite方法。

class Dog:  # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗

    def __init__(self, name, breed, aggressivity, life_value):
        self.name = name  # 每一只狗都有自己的昵称;
        self.breed = breed  # 每一只狗都有自己的品种;
        self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
        self.life_value = life_value  # 每一只狗都有自己的生命值;

    def bite(self,people):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
     dog.life_value -= self.aggressivit

实例化
ha2 = Dog('二愣子','哈士奇',10,1000)  #创造了一只实实在在的狗ha2

交互 egon打ha2一下
print(ha2.life_value)         #看看ha2的生命值
egg.attack(ha2)               #egg打了ha2一下
print(ha2.life_value)         #ha2掉了10点血

完整代码如下:

class Person:  # 定义一个人类
    role = 'person'  # 人的角色属性都是人

    def __init__(self, name, aggressivity, life_value):
        self.name = name  # 每一个角色都有自己的昵称;
        self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
        self.life_value = life_value  # 每一个角色都有自己的生命值;

    def attack(self,dog):
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.life_value -= self.aggressivity

class Dog:  # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗

    def __init__(self, name, breed, aggressivity, life_value):
        self.name = name  # 每一只狗都有自己的昵称;
        self.breed = breed  # 每一只狗都有自己的品种;
        self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
        self.life_value = life_value  # 每一只狗都有自己的生命值;

    def bite(self,people):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        people.life_value -= self.aggressivity

egg = Person('gan',10,1000)  #创造了一个实实在在的人egg
ha2 = Dog('二愣子','哈士奇',10,1000)  #创造了一只实实在在的狗ha2
print(ha2.life_value)         #看看ha2的生命值
egg.attack(ha2)               #egg打了ha2一下
print(ha2.life_value)         #ha2掉了10点血

另一个面向对象例子:

from math import pi

class Circle:
    '''
    定义了一个圆形类;
    提供计算面积(area)和周长(perimeter)的方法
    '''
    def __init__(self,radius):
        self.radius = radius

    def area(self):
         return pi * self.radius * self.radius

    def perimeter(self):
        return 2 * pi *self.radius


circle =  Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长
类命名空间与对象、实例的命名空间

    创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

而类有两种属性:静态属性和动态属性
        静态属性就是直接在类中定义的变量
        动态属性就是定义在类中的方法

其中类的数据属性是共享给所有对象的
>>>id(egg.role)
4341594072
>>>id(Person.role)
4341594072

而类的动态属性是绑定到所有对象的
>>>egg.attack
<bound method Person.attack of <__main__.Person object at 0x101285860>>
>>>Person.attack
<function Person.attack at 0x10127abf8> 

创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性

    在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

面向对象的组合用法

软件重用的重要方式除了继承之外还有另外一种方式,即:组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

class Weapon:
    def prick(self, obj):  # 这是该装备的主动技能,扎死对方
        obj.life_value -= 500  # 假设攻击力是500

class Person:  # 定义一个人类
    role = 'person'  # 人的角色属性都是人

    def __init__(self, name):
        self.name = name  # 每一个角色都有自己的昵称;
        self.weapon = Weapon()  # 给角色绑定一个武器;
        
egg = Person('gan')
egg.weapon.prick() 
#egg组合了一个武器的对象,可以直接egg.weapon来使用组合类中的所有方法

    圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
    这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用

from math import pi

class Circle:
    '''
    定义了一个圆形类;
    提供计算面积(area)和周长(perimeter)的方法
    '''
    def __init__(self,radius):
        self.radius = radius

    def area(self):
         return pi * self.radius * self.radius

    def perimeter(self):
        return 2 * pi *self.radius


circle =  Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长

class Ring:
    '''
    定义了一个圆环类
    提供圆环的面积和周长的方法
    '''
    def __init__(self,radius_outside,radius_inside):
        self.outsid_circle = Circle(radius_outside)
        self.inside_circle = Circle(radius_inside)

    def area(self):
        return self.outsid_circle.area() - self.inside_circle.area()

    def perimeter(self):
        return  self.outsid_circle.perimeter() + self.inside_circle.perimeter()


ring = Ring(10,5) #实例化一个环形
print(ring.perimeter()) #计算环形的周长
print(ring.area()) #计算环形的面积

    用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程

class BirthDate:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

class Couse:
    def __init__(self,name,price,period):
        self.name=name
        self.price=price
        self.period=period

class Teacher:
    def __init__(self,name,gender,birth,course):
        self.name=name 
        self.gender=gender
        self.birth=birth
        self.course=course
    def teach(self): 
        print('teaching')

p1=Teacher('egon','male', 
            BirthDate('1995','1','27'), 
            Couse('python','28000','4 months')
           ) 

print(p1.birth.year,p1.birth.month,p1.birth.day) 

print(p1.course.name,p1.course.price,p1.course.period)
''' 
运行结果: 
1 27 
python 28000 4 months 
'''

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好

面向对象小结:

#定义一个人类
class Person:  # 定义一个人类
    role = 'person'  # 人的角色属性都是人

    def __init__(self, name, aggressivity, life_value, money):
        self.name = name  # 每一个角色都有自己的昵称;
        self.aggressivity = aggressivity  # 每一个角色都有自己的攻击力;
        self.life_value = life_value  # 每一个角色都有自己的生命值;
        self.money = money

    def attack(self,dog):
        # 人可以攻击狗,这里的狗也是一个对象。
        # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.life_value -= self.aggressivity

#定义一个狗类
class Dog:  # 定义一个狗类
    role = 'dog'  # 狗的角色属性都是狗

    def __init__(self, name, breed, aggressivity, life_value):
        self.name = name  # 每一只狗都有自己的昵称;
        self.breed = breed  # 每一只狗都有自己的品种;
        self.aggressivity = aggressivity  # 每一只狗都有自己的攻击力;
        self.life_value = life_value  # 每一只狗都有自己的生命值;

    def bite(self,people):
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        people.life_value -= self.aggressivity

#创建一个新的兵器类
class Weapon:
    def __init__(self,name, price, aggrev, life_value):
        self.name = name
        self.price = price
        self.aggrev = aggrev
        self.life_value = life_value

    def update(self, obj):  #obj就是要带这个装备的人
        obj.money -= self.price  # 用这个武器的人花钱买所以对应的钱要减少
        obj.aggressivity += self.aggrev  # 带上这个装备可以让人增加攻击
        obj.life_value += self.life_value  # 带上这个装备可以让人增加生命值

    def prick(self, obj):  # 这是该装备的主动技能,扎死对方
        obj.life_value -= 500  # 假设攻击力是500

#测试交互
lance = Weapon('长矛',200,6,100)
egg = Person('gan',10,1000,600)  #创造了一个实实在在的人egg
ha2 = Dog('二愣子','哈士奇',10,1000)  #创造了一只实实在在的狗ha2

#egg独自力战"二愣子"深感吃力,决定穷毕生积蓄买一把武器
if egg.money > lance.price: #如果egg的钱比装备的价格多,可以买一把长矛
    lance.update(egg) #egg花钱买了一个长矛防身,且自身属性得到了提高
    egg.weapon = lance #egg装备上了长矛

print(egg.money,egg.life_value,egg.aggressivity)

print(ha2.life_value)
egg.attack(ha2)   #egg打了ha2一下
print(ha2.life_value)
egg.weapon.prick(ha2) #发动武器技能
print(ha2.life_value) #ha2不敌狡猾的人类用武器取胜,血槽空了一半
上一篇 下一篇

猜你喜欢

热点阅读