首页 > 技术文章 > 面向对象基础

zouruncheng 2017-04-17 19:42 原文

类和对象

在现实生活中是先有对象,再去发现对象的共有特征,归类。

在程序设计中先设计好类,再去实例化一个对象。

在python中,用变量表示特征,用函数表示技能,因而类是变量与函数的结合体,对象是变量与方法(指向类的函数)的结合体

声明一个类

大前提:
1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类
3.所有类甭管是否显式声明父类,都有一个默认继承object父类

在python2中的区分
经典类:
class 类名:
    pass

经典类:
class 类名(父类):
    pass

在python3中,上述两种定义方式全都是新式类

类的作用

属性引用和实例化

# 声明类
class Student:
    country = "china"

    def __init__(self,ID,NAME,GENDER,PROVINCE):
        self.id = ID
        self.name = NAME
        self.gender = GENDER
        self.province = PROVINCE
        self.country = "England"

    def search_score(self):
        print("tell score")


    def study(self):
        print("study",self)


# 类的用法,实例化和属性引用
s1 = Student(421023,"zou","male","hubei") # 实例化
print(Student.country) # china 引用类的属性,该属性与所有对象/实例共享
print(Student.study)    # <function Student.study at 0x01276228> 引用类的函数属性,该属性也共享
Student.x = 132  # 新增属性
del Student.x  # 删除属性

类属性补充

# 类的特殊用法
print(Student.__name__)   #  Student 类的名字(字符串)
print(Student.__doc__)   #  None 类的文档字符串
print(Student.__base__)   # <class 'object'> 类的第一个父类(在讲继承时会讲)
print(Student.__bases__)   #  (<class 'object'>,)类所有父类构成的元组(在讲继承时会讲)
print(Student.__dict__)   #  类的字典属性 {'country': 'china', 'search_score': <function Student.search_score at 0x01B46228>,
#  '__doc__': None,
print(Student.__module__)   # __main__ 类定义所在的模块
print(Student.__class__)   # <class 'type'> 实例对应的类(仅新式类中)

对象的用法
对象只有一个用法就是属性引用

对象/实例本身只有数据属性,但是python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法,绑定方法唯一绑定一个对象,同一个类的方法绑定到不同的对象上,属于不同的方法,内存地址都不会一样

# 对象只有一个用法 :属性引用
print(s1.country) # china


# 对象的绑定方法,绑定方法的核心在于"绑定",唯一绑定一个确定的对象,谁来调用就作用于谁
print(Student.study,id(Student.study))  # <function Student.study at 0x015C6228> 22831656 内存地址不同
print(s1.study,id(s1.study))            # <bound method Student.study of <__main__.Student object at 0x015CCE50>> 22174976

查看对象和类的名称空间
类名.dict:查出的是一个字典,key为属性名,value为属性值

print(s1.__dict__)      # 对象的字典属性----{'gender': 'male', 'id': 421023, 'province': 'hubei', 'name': 'zou'}
print(Student.__dict__) # 类的字典属性----{'__doc__': None, 'country': 'china',
                                        #  '__weakref__': <attribute '__weakref__' of 'Student' objects>,
                                        # '__dict__': <attribute '__dict__' of 'Student' objects>,
                                        #  '__module__': '__main__', '__init__': <function Student.__init__ at 0x01F06DF8>,
                                        #  'search_score': <function Student.search_score at 0x01F06228>,
                                        #  'study': <function Student.study at 0x01F06E40>}

对象之间的交互

基于面向对象设的游戏:英雄联盟,每个玩家选一个英雄,每个英雄都有自己的特征和和技能。一个英雄可以攻击另外一个英雄,这就是对象之间的交互
交互:锐雯雯攻击草丛伦,反之一样

# 对象之间的交互
class Garen:
    def __init__(self,nickname,aggressivity=54,life_value=414):
        self.nickname = nickname
        self.life_value = life_value
        self.aggressivity = aggressivity

    def attack(self,obj):
        obj.life_value -= self.aggressivity


class Riven:
    camp = '诺克萨斯'  # (锐雯)的阵营都是Noxus;
    def __init__(self,nickname,aggressivity=54,life_value=414):  #英雄的初始攻击力和生命值
        self.nickname = nickname      # 为自己的锐雯起个别名
        self.life_value = life_value   # 英雄都有自己的生命值;
        self.aggressivity = aggressivity   # 英雄都有自己的攻击力;


    def attack(self,obj):      # 普通攻击技能,obj是敌人;
        obj.life_value -= self.aggressivity    # 根据自己的攻击力,攻击敌人就减掉敌人的生命值。


r1 = Riven("瑞雯")
# print(r1.nickname)
g1 = Garen("盖伦")
print("from Riven",r1.life_value)  # from Riven 414
g1.attack(r1)
print(r1.life_value)   #    360
print("from Garen",g1.life_value)   #  from Garen 414
r1.attack(g1)
r1.attack(g1)
print("from Garen",g1.life_value)    # from Garen 306

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

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

模拟对象交互

# 对象交互,模拟英雄联盟盖伦和瑞文的攻击
class Garen:
    camp = '德玛西亚'
    def __init__(self,nickname,aggressivity=54,life_value=414,money = 500):
        self.nickname = nickname
        self.life_value = life_value
        self.aggressivity = aggressivity
        self.money = money
    def attack(self,obj):
        obj.life_value -= self.aggressivity


class Riven:
    camp = '诺克萨斯'
    def __init__(self,nickname,aggressivity=54,life_value=414,money = 500):
        self.nickname = nickname
        self.life_value = life_value
        self.aggressivity = aggressivity
        self.money = money
    def attack(self,obj):
        obj.life_value -= self.aggressivity


class Weapon:
    def __init__(self,add_life_value=80, add_aggressivity=10,price=450 ):
        self.add_life_value = add_life_value
        self.add_aggressivity = add_aggressivity
        self.price = price


    def update(self,obj):
        obj.life_value +=  self.add_life_value # 加生命值
        obj.aggressivity += self.add_aggressivity   # 加攻击
        obj.money -= self.price                   # 减钱


    def dazhao(self,obj):        # 这是该装备的主动技能,喷火,烧死对方
        obj.life_value -= 100     # 假设大招的攻击力是100


g1 = Garen("盖伦")
r1 = Riven("瑞文")
w1 = Weapon()
print(g1.life_value,g1.aggressivity,g1.money) #  g1的攻击力,生命值,护甲
# g1.life_value=414  g1.aggressivity = 54    g1.money = 500
if g1.money > w1.price:
    g1.w1 = w1
    w1.update(g1)
print(g1.life_value,g1.aggressivity,g1.money)   # 穿上装备后,r1的攻击力,生命值,护甲
# g1.life_value=494  g1.aggressivity = 64    g1.money = 50

print(r1.life_value)       # life_value = 414
g1.attack(r1)      # 普通攻击
g1.w1.dazhao(r1)   # 用装备攻击
print(r1.life_value)  #g1的生命值小于0就死了 life_value = 250

推荐阅读