python基础——面向对象

来源:互联网 发布:js cookie 永不过期 编辑:程序博客网 时间:2024/06/08 00:05

类中关于self的解析

class Role(object):    n=123#类变量    def __init__(self,name,role,weapon,life_value=100,money=15000):        #构造函数,在实例化时做一些类的初始化工作        #此处的self是为了传递变量r1、r2之类的,内部实现实例化的时候是把r1和其他的实参一样当做参数传递进来的,所以在这个地方必须有个形参self,否则参数就不匹配了,我们的        #实例化传递的参数是存储在门牌号为r1的内存中的,而下面的这些函数则是存储在类的内存中的,下面的函数中之所以要有self是为了辨别是哪个变量(类似于r1)在调用它        #它的内部实现是:Role.shot(r1),因为shot是存储在类的内存中的,将r1传递进去底部会对它进行处理,才能实现r1.shot()(等价于Role.shot(r1))        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...,I got shot...")    def buy_gun(self,gunname):        print("%s just bought %s"%(self.name,gunname))r1 = Role('Alex','police',"AK47") #生成一个角色,把一个类变成一个具体对象的过程叫实例化,对象也称为Role的实例r2 = Role('Jack','terrorist',"B22")  #生成一个角色r1.buy_gun("AK47")

这里写图片描述
注意:self的用处有两个,第一可以初始化赋值不至于在类里面其他函数里面调用类似于变量name的时候被销毁了,第二可以使之可以调用类里面的函数。这些功能都是在python底部实现的。

类变量与实例变量

class Role(object):    n=123#类变量    name="类name"#类变量    def __init__(self,name,role,weapon,life_value=100,money=15000):        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...,I got shot...")    def buy_gun(self,gunname):        print("%s just bought %s"%(self.name,gunname))r1 = Role('Alex','police',"AK47") #在类外增加删除属性r1.bullet_prove=True#可以给r1对象增加一个属性,r2不拥有,因为它仅仅是存储在对象r1的内存中的del r1.name#也可以删除一个r1对象的属性,r2对象依然用于name属性,它删除的也只是存储在对象r1内存中的r2 = Role('Jack','terrorist',"B22")  r1.buy_gun("AK47")#类变量print(r1.name)#打印Alex,它会现在实例变量中找,如果找不到则到类变量中找print(Role.n)#打印123,因为存储在类内存中,所以可以直接调用print(r1.n)#打印123,底层将r1传递进去了,可以直接调用(底层实现的)r1.n="修改类变量"print(r1.n)#打印出“修改类变量”,修改类变量相当于在对象的内存中增加了一个与类变量一样的属性,类内存中的变量实质上并没有任何改变,而当跟类变量属性相同时,先找对象内存中的print(r2.n)#打印123,通过对象改变类变量并不会真正的改变类变量,而r2中之前没有这个属性,所以会直接找类内存中的Role.n="通过类修改了类变量"print(r1.n)#打印“修改类变量”,因为上面的r1.n="修改类变量"相当于已经给它增加了一个同类变量n相同的属性,所以它会想找对象内存中的,所以打印出“修改类变量”print(r2.n)#打印“通过类修改了类变量”,因为r2对象内存中并没有n这个属性,所以会到类内存中去找

类变量是对象共用的属性(东西,n都是一样的),能够节省开销(我们在构造函数中定义一个默认参数n也可以实现,但是每次都要初始化并在不同的对象中都得给它分配一个内存),而实例变量则是对象各自独有的属性(nam、role等传递进去的不同,也就不一样了)。当我们个别对象有些特例外,我们在外面也可以通过对象进行修改(实质上是定义一个同类变量一样的属性而已)。

私有属性和方法

class Role(object):    n=123#类变量    name="类name"#类变量    def __init__(self,name,role,weapon,life_value=100,money=15000):        self.name = name#实例变量        self.role = role        self.weapon = weapon        self.__life_value = life_value#__life_value前面加了两个横线就变成了私有属性,私有属性只能在类内部访问,外部访问不了        self.money = money    def getPrivate(self):        print("the life is:%s"%self.__life_value)#正确,这是在类的内部    def shot(self):        print("shooting...")    def got_shot(self):        print("ah...,I got shot...")    def buy_gun(self,gunname):        print("%s just bought %s"%(self.name,gunname))r1 = Role('Alex','police',"AK47")#在类外增加删除属性r1.buy_gun("Ak47")r1.got_shot()#print(r1.__life_value)#错误,这是在类的外部,访问不了r1.getPrivate()

析构函数
析构函数的作用:在实例释放、销毁的时候自动执行(不需要调用,只需要写一个析构函数即可),通常用于一些收尾工作,如关闭一些数据库链接、打开的临时文件

class Role(object):    n=123#类变量    name="类name"#类变量    def __init__(self,name,role,weapon,life_value=100,money=15000):        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...,I got shot...")    def buy_gun(self,gunname):        print("%s just bought %s"%(self.name,gunname))r1 = Role('Alex','police',"AK47")#在类外增加删除属性r1.buy_gun("Ak47")r1.got_shot()del r1.namedel r1#手动删除对象的时候,它会调用析构函数,否则它只会在对象释放的时候或在程序结束的时候调用,只有在删除对象的时候才会调用析构函数,删除一个属性的时候不会调用析构函数r2 = Role('Jack','terrorist',"B22")r2.buy_gun("BBS")

继承

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)    def talk(self):        print("%s is talking……"% self.name)'''class Man(People):#class Man(People) Man类继承People类    passm1=Man("Jorocco",22)#此处必须传递两个参数,即使Man类中没有其他的属性,原因是:继承的People类中有传递参数,所以此处传递的参数不仅仅涉及到Man类自身的参数,还要考虑父类的参数,因为父类的构造函数有两个参数,这里的构造函数是继承的父类,因为子类它本身,没有构造函数m1.eat()'''class Man(People):    def piao(self):        print("%s game over……20s"% self.name)#这里之所以可以直接self.name,是因为继承了父类People,父类People有name属性    '''    def sleep(self):        print("man is sleeping")#名字与父类方法名相同,这是重写父类的方法    '''    #在父类的基础方法的基础上添加新的功能,即重构    def sleep(self):        People.sleep(self)#先执行父类的方法        print("man is sleeping")m1=Man("Jorocco",22)#此处必须传递两个参数,即使Man类中没有其他的属性,原因是:继承的People类中有传递参数,所以此处传递的参数不仅仅涉及到Man类自身的参数,还要考虑父类的参数,因为父类的构造函数有两个参数,这里的构造函数是继承的父类,因为子类它本身,没有构造函数m1.eat()m1.piao()m1.sleep()

继承之经典类与新式类

#class People:#经典类class People(object):#新式类,super和这个是配套的,super也是新式写法    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)    def talk(self):        print("%s is talking……"% self.name)class Man(People):#class Man(People) Man类继承People类    def __init__(self,name,age,money):#当需要给子类在初始化的时候加个属性,则父类的形参属性也需要被传进来        #People.__init__(self,name,age)#并且需要先调用父类的构造函数进行先初始化,经典写法        super(Man,self).__init__(name,age)#这种写法和上面的People.__init__(self,name,age)写法一样的意思        self.money=10#然后再进行初始化子类所特有的属性,其实这也相当于重构    def piao(self):        print("%s game over……20s"% self.name)#这里之所以可以直接self.name,是因为继承了父类People,它有name属性    def sleep(self):        People.sleep(self)#先执行父类的方法        print("man is sleeping")class Woman(People):#多继承,先执行自己的构造函数,此处它本身没有构造函数,则继承People的构造函数,如果People没有则继承Relation的构造函数,并不是一一继承的    def get_birth(self):        print("is born a baby……")m1=Man("Jorocco",22,10)#父类的参数name age以及子类的参数moneyw1=Woman("Morocco",24)m1.make_friends(w1)

super之参数问题

#class People:#经典类class People(object):#新式类,super和这个是配套的,super也是新式写法    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)    def talk(self):        print("%s is talking……"% 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):#class Man(People) Man类继承People类#     def __init__(self,name,age,money):#         super(Man,self).__init__(name,age)#当继承多个父类的时候,这里的参数怎么填?一般这种继承多个父类的时候,我们要么知道它继承的是谁,就填相应的参数#         self.money=10                     #要么就用组合的方式,意思就是单继承,但是在它的内部调用另一个父类,尽量能知道继承的构造函数,就用那种方式#     def piao(self):#         print("%s game over……20s"% self.name)#     def sleep(self):#         People.sleep(self)#         print("man is sleeping")# class Woman(People,Relation):#         print("is born a baby……")## m=Man("Jorocco",22,10)## w1=Woman("Morocco",24)# m.make_friends(w1)#组合方式class Man1(People):#class Man(People) Man类继承People类    def __init__(self,name,age,money,Relation_obj):        super(Man1,self).__init__(name,age)#当继承多个父类的时候,这里的参数怎么填?一般这种继承多个父类的时候,我们要么知道它继承的是谁,就填相应的参数        self.money=10                     #要么就用组合的方式,意思就是单继承,但是在它的内部调用另一个父类        self.relation=Relation_obj    def piao(self):        print("%s game over……20s"% self.name)    def sleep(self):        People.sleep(self)        print("man is sleeping")    def make_friends(self,obj):#要么就用组合的方式,意思就是单继承,但是在它的内部调用另一个父类         self.relation.make_friends(obj)class Woman(People,Relation):        print("is born a baby……")relation_obj=Relation()m1=Man1("Jorocco",22,10,relation_obj)w1=Woman("Morocco",23)m1.make_friends(w1)

python构造函数的继承顺序

python3的经典类和新式类继承都是广度优先策略的,python2的经典是按深度优先来继承的,新式类是按广度优先来继承的

class A:    def __init__(self):        print("A")class B(A):#B继承A    def __init__(self):        print("B")class C(A):#C继承A    def __init__(self):        print("C")#若D中没有构造函数,则找B,若B中也没有构造函数,则再找C,C中也没有则找A,它并不是我们惯性认为的一一继承,为此当我们实例化传递参数的时候需要注意考虑它是如何继承的,因为需要根据它继承的方式进行相应的参数传递class D(B,C):#从左到右进行继承的,即先继承B再继承C    passobj=D()

多继承(同级父类调用它自身没有的属性)

class People(object):#新式类,super和这个是配套的,super也是新式写法    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)    def talk(self):        print("%s is talking……"% self.name)class Relation(object):    def __init__(self,money):        self.money=money    def make_friends(self,obj):#这里之所以可以直接self.name,obj.name,是因为函数只有在调用的时候才执行的,比如此处只有在程序执行m1.make_friends(w1)的时候函数才被调用执行,在这之前我们都已经初始化完了,初始化了self.name,obj.name这个就合法了,因为子类有了这些属性(继承自父类的)。#初始化的时候是按广度优先进行继承的,先继承自左父类(People)的构造函数,如果有,则继承(继承完了不继承后面的),没有则继承右父类(Relation)#当继承了左父类的构造函数时,self.name已经被初始化了,对象obj(w1)也已经被初始化了,所以obj.name也合法#如果写成class Woman(Relatio,People),则先继承Relatio的构造函数,但它没有构造函数,则再找People的构造函数,在这个地方也不会出错#若是Relatio有构造函数,且初始化时没有name属性(self.name),则在此调用则会报错,正如位置1展示的那样        print("%s is making friends with %s"%(self.name,obj.name))#如果是位置1则报错,因为调用的构造函数是Relation的,但是它并没有name这个属性,obj.name不会出错,因为它初始化继承的是People,People有name属性                                                                  #如果是位置2则不会报错,People有name属性#class Man(Relation,People):#位置1class Man(People,Relation):#位置2    def piao(self):        print("%s game over……20s"% self.name)#这里之所以可以直接self.name,是因为继承了父类People,它有name属性    def sleep(self):        People.sleep(self)#先执行父类的方法        print("man is sleeping")class Woman(People):    def get_birth(self):        print("is born a baby……")#m1=Man(10)#位置1  此处的参数我们要看继承的是哪个构造函数,然后再视其构造函数的参数进行给予,比如:此处我们继承的是Relation,它的构造函数只有一个参数,所以此处只能传递一个参数m1=Man("Jorocco",23)#位置2  位置2调用的是People的构造函数,它的参数是两个,所以此处只需给予两个w1=Woman("Morocco",24)m1.make_friends(w1)

多态

#多态:一种接口,多种实现,实现接口的重用class Animal(object):    def __init__(self, name):  # Constructor of the class        self.name = name    @staticmethod    def animal_talk(self):              # Abstract method, defined by convention only        self.talk()class Cat(Animal):    def talk(self):        print('%s: 喵喵喵!' %self.name)class Dog(Animal):    def talk(obj):        print('%s: 汪!汪!汪!' %obj.name)#方法1实现的多态# def func(obj): #一个接口,多种形态  方法1#     obj.talk()## c1 = Cat('小晴')# d1 = Dog('李磊')## func(c1)#都是接口func,实现了不同的功能# func(d1)#都是接口func,实现了不同的功能,这就是多态#方法2实现的多态,规范的,一种接口多种实现c1 = Cat('小晴')d1 = Dog('李磊')Animal.animal_talk(c1)Animal.animal_talk(d1)

类方法

class Dog(object):    n=122    def __init__(self,name):        self.name=name    @classmethod#类方法只能访问类变量,不能访问实例变量    def eat(self,food):        print("%s is eating %s"%(self.n,food))#n是类变量所以可以访问        #print("%s is eating %s"%(self.name,food))#错误,name是实例变量,不能访问d=Dog("Jorocco")d.eat("馒头")

静态方法

class Dog(object):    def __init__(self,name):        self.name=name    @staticmethod#只是名义上归类管理,实际上跟类没什么关系了,实际上在静态方法里访问不了类或实例中的任何属性    def eat(self,food):        print("%s is eating %s"%(self.name,food))#这样是错误的,因为它不会将对象本身传到类里头,所以下面的那个"馒头"只是给了self,这个food并没有参数与之匹配,少了一参数,而且self.name会报错d=Dog("Jorocco")d.eat("馒头")

属性方法

class Dog(object):    n=122    def __init__(self,name):        self.name=name        self.__food=None    @property#属性方法,把一个方法变成一个静态属性    def eat(self):        print("%s is eating %s"%(self.name,self.__food))    @eat.setter    def eat(self,food):        print("set to food:",food)        self.__food=food    #位置2    @eat.deleter    def eat(self):        del self.__food        print("删完了")d=Dog("Jorocco")d.eat#调用的是 @property方法d.eat="馒头"#调用的是  @eat.setter方法del d.eat#如果没有位置2,直接删除则会报错

属性方法之赋值

class Dog(object):    n=122    def __init__(self,name):        self.name=name    @property#属性方法,把一个方法变成一个静态属性    def eat(self,food):        print("%s is eating %s"%(self.name,food))    #位置2  加了这个之后的    @eat.setter    def eat(self,food):        print("%s is eating %s"%(self.name,food))d=Dog("Jorocco")#这种赋值都是错误的#d.eat("馒头")#错误,它已经变成一个属性了,不能调用方法#d.eat="馒头"#错误d.eat="馒头"#加了位置1的赋值  才正确

属性方法之删除

class Dog(object):    n=122    def __init__(self,name):        self.name=name        self.__food=None    @property#属性方法,把一个方法变成一个静态属性    def eat(self):        print("%s is eating %s"%(self.name,self.__food))    @eat.setter    def eat(self,food):        print("set to food:",food)        self.__food=food    #位置2    @eat.deleter    def eat(self):        del self.__food        print("删完了")d=Dog("Jorocco")d.eat#调用的是 @property方法d.eat="馒头"#调用的是  @eat.setter方法del d.eat#如果没有位置2,直接删除则会报错
原创粉丝点击