python 面向对象

面向对象(类编程)

简介:全称Object Oriented Programing(OOP) ,是一种程序设计思想,面向对象编程

面向对象名词简介

借鉴菜鸟教程

  • 类(class):类事抽象的模板,用来描述具有相同属性和方法的对象的集合。定义了集合中每个对象所拥有的方法,对象是类的实例
  • 方法:类中自定义的函数
  • 类变量:类变量在整个实例化的对象中是公用的,每个对象都可以调用类变量。类变量定义在类中且函数体之外。类变量通常不作为实例变量使用
  • 数据成员:类变量或者实例变量用于处理类及实例对象所使用的相关数据
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对齐进行重新,这个过程叫做方法的覆盖,也叫做方法的重写
  • 局部变量:定义在方法中的变量,只作用与当前实例的类
  • 实例变量:在类的声明中,属性是用变量来表示的。这种变量也叫做实例变量
  • 继承:既一个派生类(同有的方法调用另一个类),继承基类(例如Person)的字段和方法。例如:A类和B类都需要调用相同的方法,既创建C类,把相同的方法放到C类,A类和B类继承C类,A类和B类就可以直接调用C类的方法了
  • 实例化:创建一个类的实例,类的具体对象,例如:人类是一个类的集合,你不知道里边有谁谁谁,但是我如果说马云,你肯定就想到了他的身高,长相,money等等,这个过程也叫做实例化
  • 对象:也叫做实例,通过类定义的数据结构实例,对象包括两个数据成员(类变量和实例变量)和方法,例如:你就知道人类,但是你不知道某个人,如果给这某个人来一个定义,他是马云,那么马云就是一个对象,它是人类的对象。

面向对象最重要的概念就是类(class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都具有相同的方法,但各自的数据不同

类的相关知识

  • 类名一共有三个作用:
    1. 可以调用类中的变量 Fruits.discount
    2. 实例化创建一个对象 Fruits('苹果',5)
    3. 调用一个方法(现在不常用):类名.方法名()
  • 对象名
    1. 查看对象的属性 对象名.属性
    2. 调用对象的方法 对象名.方法名()
  • 类和对象和实例和实例化
    1. 什么是类 ? Dog Person Fruits
    2. 什么是对象 ? alex 二饼 旺财 苹果 李子
    3. 什么是实例 ? 对象就是实例
    4. 实例化 是一个动词 类创造实例的过程叫做实例化
    5. 对象 = 类名() 实例化

属性引用(类名.属性)

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

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

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

print(Person.role)  # 查看人的属性
print(Person.walk)  # 引用人的走路方法,注意这里不是调用,函数需要后面加括号,才算调用

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

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

print(Person.role)  # 查看人的属性
print(Person.walk)  # 引用人的走路方法,注意这里不是调用,函数需要后面加括号,才算调用

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

原本我们只有一个Person类,但在这个过程中,产生了一个mhy对象,他有自己的名字等等

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

查看属性及调用方法

mhy = Person('mhy') # 类名()就等于执行Person.__init__

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

关于self

self:在实例化过程中自动将对象/实例本身传给__init__函数的第一个参数,你也可以起别的名称,但是不要用,这是一种开发规范

类属性的补充:

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


二:特殊的类属性
print(Person.__name__)  # 类的名字(字符串)
# 结果 Person

print(Person.__doc__) # 类的注释文档
# 结果 这是一个人类

print(Person.__base__) # 查看类的第一个父类(在讲继承时会讲)
# 结果 

print(Person.__bases__) # 类所有父类构成的元组(在讲继承时会讲)
# 结果 (,)

print(Person.__dict__) # 类的字典属性
# 结果 {'__module__': '__main__', '__doc__': '这是一个人类', 'role': 'person', '__init__': , 'walk': }

print(Person.__module__) # 类定义所在的模块
# 结果 __main__

print(Person.__class__) # 实例对应的类(仅新式类中)
# 结果 

例子:人狗大战

class Person: # 定义一个人类 
    role = 'person'
    def __init__(self,name,hp,ad,sex,job):
        self.username = name  # 每一个角色都有自己的昵称;
        self.hp = hp   # 每一个角色都有自己的hp;
        self.ad = ad   # 每一个角色都有自己的攻击力;
        self.sex = sex  # 每一个角色都有自己的性别;
        self.job = job   # 每一个角色都有自己的职业;
    
    def attack(self,dog):  # 攻击狗的方法
         # 人可以攻击狗,这里的狗也是一个对象。
         # 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
        dog.hp -= self.ad
        print('%s攻击了%s,%s掉了%s点血'%(self.username,dog.name,dog.name,self.ad))

class Dog:  # 定义一个狗类
    role = 'dog'
    def __init__(self,name,kind,hp,ad):   # 初始化方法
        self.name = name   # 每一只狗都有自己的昵称;
        self.kind = kind   # 每一只狗都有自己的品种;
        self.hp = hp    # 每一只狗都有自己的血量
        self.ad = ad    # # 每一只狗都有自己的攻击力
    
    def bite(self,person):   # 狗咬人的方法
        # 狗可以咬人,这里的狗也是一个对象。
        # 狗咬人,那么人的生命值就会根据狗的攻击力而下降
        person.hp -= self.ad  
        print('%s咬了%s,%s掉了%s点血'%(self.name,person.username,person.username,self.ad))    # 谁在类的外部调用了这个方法,方法中的第一个self参数就是谁
        
alex = Person('alex',100,5,'不详','乞丐')  # 实例化一个人对象
wangcan = Dog('旺财','teddy',2000,300)  # 实例化一个狗 对象
erbing = Dog('二饼','哈士奇',10000,500) # 不同的对象
erbing.bite(alex)     # Dog.bite(二饼,alex)  # 狗对象调用狗的咬人方法攻击了人
print(alex.hp)  # 查看人的血量

例子:求圆的面积及体积

from math import pi  # 导入3.14

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) #打印圆面积和周长

类命名空间与对象、实例的命名空间

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

而类有两种属性:静态属性和动态属性

  • 静态属性就是直接在类中的变量
  • 动态属性就是定义在类中的方法

其中类的属性是共享给所有对象的

print(id(erbing.role))
47994208
print(id(Dog.role))
47994208

而类的动态属性是绑定到所有对象的

print(alex.attack)
print(Person.attack)
# 结果
>

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

例如:obj.name会先在obj自己的命名空间中查找name,查找不到则回去类里去找,类也找不到会去父类找..最后都找不到会抛出异常

组合用法

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

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

class arms:
    def prick(self):  # 这是该装备的主动技能,扎死对方
        print('我靠 居然使用了无尽')
        # obj.life_value -= 500  # 假设攻击力是500


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

    def __init__(self, name):   
        self.name = name  # 每一个角色都有自己的昵称;
        self.arms = arms()  # 给角色绑定一个武器;

mhy = Person('mhy')
mhy.arms.prick()  
# mhy组合了一个武器的对象,可以直接mhy.arms来使用组合类中的所有方法

组合例子

圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。

这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用

from math import pi

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

    def area(self):
        '''计算圆形面积公式:πr²'''
        return pi* self.radius * self.radius

    def perimeter(self):
        '''计算圆的周长公式:2πr'''
        return 2 * pi * self.radius

ret_object = Circle(5)  # 实例化一个圆
print(ret_object.area()) # 打印圆计算的面积
print(ret_object.perimeter()) # 打印圆计算的周长

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

    def ring_perimeter(self):
        return self.radius_outside.perimeter() + self.radius_inside.perimeter()


ring = Ring(10, 5)  # 实例化一个圆环
print(ring.ring_area())  # 打印圆环计算的面积
print(ring.ring_perimeter())  # 打印圆环计算的周长

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

初识面向对象小结

  • 定义一个人类

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('egon',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不敌狡猾的人类用武器取胜,血槽空了一半

继承

什么是继承

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类超类,新建的类称为派生类子类

python中类的继承分为:单继承和多继承

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现

>>> ParentClass1.__bases__
(,)
>>> ParentClass2.__bases__
(,)

你可能感兴趣的:(python 面向对象)