python中的面向对象、类

面向对象简介

1.面向对象的编程方法是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,它可以简化程序的维护和扩展,提高程序开发效率 ,代码逻辑易于理解,使团队开发更从容。

2.面向对象的几个核心特性如下:

Class 类
类是面向对象程序设计的主要工具,类就是一些函数的包,这些函数大量地使用并处理内置对象类型。实质上,类的设计是为了创建和管理新的对象,支持继承。(做长期产品开发的对类更有兴趣)
它在程序领域中反映了现实中的对象。

Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法

Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承

Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定

无论用什么形式来编程,我们都要明确记住以下原则:
1.写重复代码是非常不好的低级行为
2.你写的代码需要经常变更
所以引入了面向对象编程方法。
示例如下:

#实例cs
class Role(object): #定义一个类,class是关键字,Role是类名,(object)是新式类的写法,
    # 老式类为class Role:
    def __init__(self,name,role,weapon,life_value=100,money=16000):
        #构造函数,也叫初始化函数,生成对象时初始化的一些属性值在这里定义
        #在实例化时做了一些类的初始工作
        #开辟一个新的内存空间去存储所传参数
        self.name = name #__init__中的self和第一个参数self分别是什么意思呢?
        #参数中的self用于接收r1、r2
        #__init__中的self用途就是可以长久保存传入的数据
        #而不至于每一次实例化就会删除上一次实例化传入的数据
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
    def shot(self):
        #除__init__外,其他方法都是存在类的内存里的,不会开辟新的内存空间
        #实例化时,除了__init__方法外,其它都是对象调用的,
        # 而不是像__init__那样拷贝一份
        print("shooting...")
    def got_shot(self):
        print("ah...,%s got shot"%self.name)
    def buy_gun(self,gun_name):
        print("%s just bought %s"%(self.name,gun_name))

r1 = Role("lc","police","AK47")
#有r1使他不会被销毁,若没有r1,则使用后就被销毁了
#实例化:把一个类变成一个具体对象的过程
#初始化了一个类,相当于生成了一个对象
#生成一个角色,自动将以下参数传给Role下的__init__方法
r2 = Role("xxy","terrorist","M416")
r1.got_shot()  

r1.buy_gun("ssg")

Role.buy_gun(r1,"ssg")  
#与上一行代码等效,可以看出self是接收r1这个对象的,谁调用这个类self就接受谁
r2.got_shot()  #等效于Role.get_shot(r2)
'''

'''
实例化到底干了什么呢?
类在构造好以后就算不调用也存在于内存之中,print(Role)
r1调用后会立即开辟出一块内存空间,数据是如何存到类的构造函数中的呢?
赋值的过程肯定是在类里实现的
r1 = Role(Alex,Police,16000)把初始化的数据
在实例化的时候,不是等着所有的值在内存中建好后才传,而是直接将全部传入,包括r1

Role(r1,'Alex','police',16000)
#相当于
r1.name = 'Alex'
r1.role = 'police'
r1.money = 16000

'''

'''
#实例变量与类变量
class Role(object):
    n = 123
    name = "我是类name"
    # 类变量,存在类的内存里
    def __init__(self,name,role,weapon,life_value=100,money=16000):
        self.name = name
        # 实例变量(静态属性),只在实例内部生效,r1中的实例变量r2不能使用。
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
    def shot(self):
        # 类的方法(动态属性) ,功能
        print("shooting...")
    def got_shot(self):
        print("ah...,%s got shot"%self.name)
    def buy_gun(self,gun_name):
        print("%s just bought %s"%(self.name,gun_name))
print(Role.n)
r1 = Role("cay","police","awm")
print(r1.n,r1.name)
#未定义实例变量n时打印出来的值为类变量123
#实例变量name已经被定义,实际打印name值为实例变量name,而不是类变量name
#规律;先找实例本身的实例变量,如果实例本身没有,就去类里面找类变量
r1.name = "阿瑟东"
#属性可以修改
print(r1.n,r1.name)

r1.bullet_prove = True
# 实例化完成后,可以给实例增加属性
print(r1.bullet_prove)

#但是新增属性和r2没有任何关系
print(r1.weapon)
#del r1.weapon
#删除r1的某个属性
print(r1.weapon)

#实例里面可以查类变量,能改类变量吗?
r1.n = "改变类变量"
print("r1:",r1.n)
#发现在实例r1中可以"修该类变量的值",实际上相当于在r1
#的内存空间里新存了一个n,这个n和类变量n不是一个

r2 = Role("asd","asda","sada")
print(r2.n)
#但是对另一个实例r2没有影响,他们互相独立(彼此的内存空间相互独立)
print(Role.n)
#类变量不变

Role.n = "ABC"
print(r1.n,r2.n,Role.n)
#r1仍然为实例变量n,r2和Role都变了
'''


'''
#如果类变量为一个列表呢?
class Role(object):
    n_list = []
    def __init__(self,name,role,weapon,life_value=100,money=16000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
    def shot(self):
        print("shooting...")
    def got_shot(self):
        print("ah...,%s got shot"%self.name)
    def buy_gun(self,gun_name):
        print("%s just bought %s"%(self.name,gun_name))

r1 = Role("cay",'police','m4')
r1.n_list.append('from r1')
r2 = Role("jacky","police",'ak')
r2.n_list.append('from r2')

print(r1.n_list)
print(r2.n_list)
print(Role.n_list)
#发现它们全都变成了['from r1', 'from r2'],因为它们三个用的都是同一块内存
#所以打印结果都相同
'''





#析构函数
#作用:在实例释放、销毁的时候执行的,通常用于做一些收尾工作,如关闭一些数据库连接,打开的临时文件
class Role(object):
    def __init__(self,name,role,weapon,life_value=100,money=16000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

    def __del__(self):
        print("%s 彻底死了"%self.name)
    def shot(self):
        print("shooting...")
    def got_shot(self):
        print("ah...,%s got shot"%self.name)
    def buy_gun(self,gun_name):
        print("%s just bought %s"%(self.name,gun_name))

r1 = Role("cay",'police','m4')
r2 = Role("jacky","police",'ak')
#cay 彻底死了
#jacky 彻底死了


类的继承

'''
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self):
        print("%s is eating"%self.name)
    def sleep(self):
        print("%s is sleeping"%self.name)
class Man(People): #继承父类的方法和属性,在自己内部可以进行新建、覆盖、重构和增加(属性和方法)
    def smoke(self):
        print("%s is smoking"%self.name)
    #def sleep(self):  #可以重写父类的方法,调用时就不执行父类的了
        #print("man is sleeping")
    #如果想在父类的基础上增加新功能呢?
    def sleep(self):
        People.sleep(self)
        print("man is sleeping")
class Woman(People):
    def get_birth(self):
        print("%s is boring a baby")

m1 = Man('cay',23)
m1.eat()
m1.sleep()
w1 = Woman("kk",28)
w1.eat()
w1.sleep()
w1.get_birth()
# w1.smoke()
# 虽然它们继承同一个类,但他们之间相互独立,不可以相互调用对方的方法
'''





'''
#子类中重构
class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self):
        print("%s is eating"%self.name)
    def sleep(self):
        print("%s is sleeping"%self.name)
class Man(People):
    def __init__(self,name,age,money):
    #除了初始化父类人的外,还想再初始化一些男人的属性
        #法一 继承父类的构造函数
        # People.__init__(self,name,age)
        #法二 继承父类的构造函数,比法一方便了,如果要修改People类,就要修改多个People,复杂的很
        #如果子类是多继承的,要重构多个父类的方法,就更麻烦了。。
        super(Man,self).__init__(name,age)
        self.money = money
        print("一出生就有%s元钱"%self.money)


    def smoke(self):
        print("%s is smoking"%self.name)
    def sleep(self):
        People.sleep(self)
        print("man is sleeping")
class Woman(People):
    def get_birth(self):
        print("%s is boring a baby")

m1 = Man("cay",23,10)
print(m1.name,m1.age,m1.money)
w1 = Woman("KK",25)
'''



'''
#多继承情况一:在子类中有构造函数,初始化时就已经拥有属性
#新式类,上面的为经典类,二者在多继承上有区别
class People(object): #新式类的写法
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self):
        print("%s is eating"%self.name)
    def sleep(self):
        print("%s is sleeping"%self.name)
class Relation(object):
    def make_friends(self,obj):
        print("%s is making friends with %s" % (self.name,obj.name))
        #这里没有定义过构造函数,那么self.name是哪里来的呢?        
        #继承是从左向右的,即先继承People,再继承Relation
        #如果先继承Relation,再继承People也不会出错,因为当生成m1的时候就在Man里生成name了
        
class Man(People,Relation):
    def __init__(self,name,age,money):
        super(Man,self).__init__(name,age) #新式类写法,生成m1时已经生成了一些属性
        self.money = money
        print("一出生就有%s元钱"%self.money)


    def smoke(self):
        print("%s is smoking"%self.name)
    def sleep(self):
        People.sleep(self)
        print("man is sleeping")
class Woman(People,Relation):
    def get_birth(self):
        print("%s is boring a baby")
        
m1 = Man("cay",23,10)
w1 = Woman("KK",25)
m1.make_friends(w1)
'''


'''
#多继承情况二:子类中没有构造函数,在初始化时需要去父类中进行
class People(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def eat(self):
        print("%s is eating" % self.name)
    def sleep(self):
        print("%s is sleeping" % self.name)
class Relation(object):
    def make_friends(self, obj):
        print("%s is making friends with %s" % (self.name, obj.name))
class Man(People, Relation):
    #在这里将构造函数注释,即初始化m1时所传实参需到父类中找,这里的继承顺序是从左到右的
    #所以先去People里继承,可以初始化name、age等属性,然后再继承Relation里的make_friends方法
    #这时没有任何问题,但是如果将People和Relation的继承顺序调换,当初始化m1时,m1先去Relation里
    #寻找对应的要传的实参的形参,发现没有,这样就会报错了
    # def __init__(self, name, age, money):
    #     super(Man, self).__init__(name, age)  # 新式类写法,生成m1时已经生成了一些属性
    #     self.money = money
    #     print("一出生就有%s元钱" % self.money)

    def smoke(self):
        print("%s is smoking" % self.name)

    def sleep(self):
        People.sleep(self)
        print("man is sleeping")


class Woman(People, Relation):
    def get_birth(self):
        print("%s is boring a baby")


m1 = Man("cay", 23)
w1 = Woman("KK", 25)
m1.make_friends(w1)#组合
'''



'''
class People(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.friends = []
    def eat(self):
        print("%s is eating" % self.name)
    def sleep(self):
        print("%s is sleeping" % self.name)
class Relation(object):
    # def __init__(self):#这里的构造函数有无影响了m1能否被成功初始化
    #     print(self.name)
    def make_friends(self, obj):
        #这里的obj就是w1,传入的是一个对象,而不能传入一个字符串
        #如果你的朋友改名了,这里也不会变化,还是这个对象是你的朋友
        #
        print("%s is making friends with %s" % (self.name, obj.name))
        self.friends.append(obj)
class Man(Relation, People):
    #在这里将构造函数注释,即初始化m1时所传实参需到父类中找,这里的继承顺序是从左到右的
    #所以先去People里继承,可以初始化name、age等属性,然后再继承Relation里的make_friends方法
    #这时没有任何问题,但是如果将People和Relation的继承顺序调换,当初始化m1时,m1先去Relation里__init__
    #寻找对应的要传的实参的形参,发现没有,这样就会报错了
    #但是如果Relation里没有__init__构造函数,那么就不会报错了,m1生成时会先在Relation中寻找构造函数
    #发现里面没有构造函数,那么他就会继续去People里找,而People里有构造函数,所以可以成功的初始化m1这个
    #实例,类里方法的调用m1.make_friends(w1)是在对象初始化之后进行的,所以不会报错
    # def __init__(self, name, age, money):
    #     super(Man, self).__init__(name, age)  # 新式类写法,生成m1时已经生成了一些属性
    #     self.money = money
    #     print("一出生就有%s元钱" % self.money)
    def smoke(self):
        print("%s is smoking" % self.name)
    def sleep(self):
        People.sleep(self)
        print("man is sleeping")
class Woman(Relation, People):
    def get_birth(self):
        print("%s is boring a baby")

m1 = Man("cay", 23)
w1 = Woman("KK", 25)

m1.make_friends(w1)#组合
print(m1.friends[0].name)  # KK
w1.name = "san pao"
print(m1.friends[0].name)  
# san pao 这样即使朋友改了姓名,但是他在你朋友圈中没有变过,还是原来的那个实例
'''







#经典类与新式类的继承顺序(py2和py3中的区别)
class A:
    def __init__(self):
        print("A")
class B(A):
    # def __init__(self):
    #     print("B")
    pass
class C(A):
    # def __init__(self):
    #     print("C")
    pass
class D(B,C): #继承了B的构造函数后就不会去继承C的了
    # def __init__(self):
    #     print("D")
    pass

d = D()  #D
#注释掉D中的构造函数后输出:B
#注释掉B中的构造函数后输出:C
#注释掉B、C中的构造函数后输出:A
#这样我们就可以看到,在python3中,经典类和新式类的多继承都按广度优先继承
# 查完上一层所有的,没有的话再去找上上层

#深度优先策略:先搜B,再搜A,再搜C  python2中经典类按深度优先继承
#但是在python2中的新式类按广度优先继承

类的多态

#多态的特性:一个接口,多种实现,为了类在继承和派生的时候,保证使用"家谱"中任一类的实例的某一属性时
#的正确调用
#允许你将父对象设置为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给他的子对象的
#特性以不同的方式运作。简单的说,就是允许将子类类型的指针赋值给父类类型的指针。
#python不直接支持多态,但可以间接实现。
class Animal(object):
    #类中的一个方法就是一个接口,通过这一个接口实现多种动物的叫
    #根据所传参数的不同实现了不同的功能
    def __init__(self, name):  # Constructor of the class
        self.name = name

    def talk(self):  # Abstract method, defined by convention only
        pass #raise NotImplementedError("Subclass must implement abstract method")

    @staticmethod #静态方法,见以后博客细说,是一个装饰器
    def animal_talk(obj):
        #可以不加self
        obj.talk()

class Cat(Animal):
    def talk(self):
        print('Meow!')


class Dog(Animal):
    def talk(self):
        print('Woof! Woof!')


d = Dog("旺财")
#d.talk()

c = Cat("阿喵")
#c.talk()
#
# def animal_talk(obj):
#     obj.talk()


#同一接口,多种形态
Animal.animal_talk(c)
Animal.animal_talk(d)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值