python-公有和私有以及继承组合

开始前我们先讲讲最基本的魔法方法

(1)python的对象它自身有一些方法,他是面向对象的python的一切,它们能给类增加“魔力”的特殊方法,如果对象实现了这些方法中的某一个,那么这个方法就会在特殊情况下被python调用,而这一切都是自动发生的
python的这些具有魔力的方法,总是被左右各两个下划线所包围。而这我们只说最基本的特殊方法:init()。(很奇怪这个没显示全)
(2)它通常被称为构造方法init()(这个也没显示全。。)方法的魔力体现在只要实例化一个对象,这个方法每次使用类创建新对象时都会被自动调用。【还有一点就是实例化对象时,是可以传入参数的,这些参数会自动传入__init__()(这个是显示完整了。。)方法中,可以将这个方法重写来自定义对象的初始化操作】
举个栗子:

>>>class People :
    def __init__(self,name)
    self.name = name
    def kick(self):
    	print("我叫%s,谁踢我!":% self.name)
 >>>p = People("小二")
 >>>p.kick()
 我叫小二,谁踢我!	

共有和私有!

(1)进入正题~一般面向对象的编程语言都区分公有和私有的数据类型,像c++和java,都使用public和private关键字
由于声明数据是公有还是私有,但python并没有类似的关键字修饰。
难道python就是只能“赤裸裸”的?毫无隐私可言?其实不然,默认对象的方法和属性虽然都是公开的,并且可以通过点操作符(.)进行访问:

>>>class People:
   name = "小二"
>>>p = People
>>>p.name#就是这样访问哦~
小二
	

(2)python为了实现类似私有变量的特征,python内部采用了一种叫 Name Mangling(名字改编)的技术,在python中定义私有变量只需要在变量名或者函数名前加上“__”两个下划线,那么这个函数或者变量就变成私有的了。

>>>class People:
   __name = "小二" #这样就变成私有的啦~
 #用点操作符也访问不了哦~

(3)上面的代码块就是在外部将变量名隐藏起来了,理论上如果要访问就要从内部进行,如下:

>>>class People:
   def __init__(self,name):
       self.__name = name
   def getName(self):
       return self.__name
>>>p = People("小二")
   P.__name#这里会报错!!!
>>> p.getName()
'小二'#成功!
#强调一下!私有变量是不能直接通过:p.__name直接访问滴,而是必须在类内部通过方法返回私有变量的哦~
   
     

(4)那么双下划线开头的实例变量(私有变量)是不是一定不能从外部访问呢?当然不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_People__name这个样子
所以,我们仍然可以通过 使用_类名__变量名 来访问__name变量(注意这里的下划线)~

>>>p._People__name
'小二'  #成功!

注意: python目前的私有机制其实是伪私有,python的类是没有权限控制的,所有变量都是可以被外部调用的。最后这部分有些读者(尤其没接触过面向对象编程的读者)可能看的有点懵,想不明白有什么用,下面的继承可能会对你有所启发!(好尴尬,我看完后面我好像也没啥感觉~)

继承!

(1)如果我们要在python里创建一个关于类的小游戏,我们首先要对鱼类进行细分,有金鱼(Goldfish),鲤鱼(Carp),鲨鱼(Shark),and三文鱼(Salmo)。我们就开始对它们定义,欸!发现他们一个个定义十分麻烦,因为大部分鱼的属性和方法都相似,可是,要怎么将它们相似的地方让它们自动传递呢?为了方便,快捷,继承就出现了!
类继承的语法也很简单:

class 类名(被继承的类):

(2)被继承的类被称为基类,父类或超类;继承者称为子类或派生类,一个子类可以继承它的父类的任何属性和方法。
举个栗子:

>>>class Parent:
   def hello(self):
       print("正在调用父类的方法")
>>>class Child(Parent):
   pass  #类定义不能为空,但是如果处于某种原因写了无内容的类定义语句,要使用pass语句来避免错误
>>>p = parent()
>>>p.hello()
正在调用父类的方法
>>>c =  Child()
>>>c.hello()
正在调用父类方法       

注意:如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性:

>>>class Child(Parent):
   def hello(self):
       print("正在调用子类方法")
>>>c = Child()
>>>c.hello()
正在调用子类方法

(3)当我们用继承进行实际应用时,在子类要重写了__init__方法,调用后出错,这可怎么办?很显然,在子类重写了父类的__init__方法我们就在子类重写的时候先调用父类的__init__方法。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

#Fish为父类  Shark为子类
class Shark(Fish):
    def __init__(self)
        Fish.__init__(self)#这是先调用的父类
        #下面再进行重写

其实这个不理解也没关系,有一个更好的方法可以解决这个问题,那就是使用super函数。

使用super函数

super函数能够自动找到父类的方法,而且还传入了self参数,举个栗子:

#Fish为父类  Shark为子类
class Shark(Fish):
    def __intit__(self)
    super().__init__()#就是这么用的

super() 函数,它会使子类从其父继承所有方法和属性,关键是还不需要明确给出任何基类(父类)的名字,它就自动找出所有基类以及对应方法。不用给出基类名字,这就意味着如果要改变类继承关系,只要改变class语句里的父类即可!想想不用大量代码修改所有被继承的方法,就觉得super函数真香!!

多重继承

除了一个个继承外,python还支持多重继承,就是可以同时继承多个父类的属性和方法。就是这样的:

class 类名(父类1,父类2,父类3...等等)

多重继承看起来更方便,但很容易导致代码混乱,我觉得对于我们这些新手来说能不用就不用吧,当然有兴趣的可以尝试尝试,但如果它出现bug的时候那就很舒服了(再次说明,不到必要的时候不要用多重继承)。钻石继承(菱形继承)这里就不说了,当然我也不会~

组合

(1)我们在写继承的时候会发现一些问题,比如:我们有乌龟类,鱼类,现在要定义一个类,叫水池,水池里要有乌龟和鱼。乌龟和鱼本就是不同的物种,在使用继承时就觉得很奇怪,那像这类不同物种的我们要如何把它们组合成一个水池的类呢?
在python里其实也很简单,就是直接把需要的类放进去实例化就可以了,这也叫组合:

class Turtle:
    def __init__(self,x):
        self.num = x
class Fish:
    def __init__(self,x):
    	self.num = x
class Pool:
    def __init__(self,x,y):
    	self.turtle = Turtle(x)
    	self.fish = Fish(y)
    def print_num(self):
        print("水池里总共有乌龟%d只,小鱼%d条!"%(self.turtle.num,self.fish.num))
   	        

然后我们运行它:

#先运行前面的代码
>>>pool = Pool(1,10)
>>>pool.print_num()
水池里总共有乌龟1只,小鱼10条!

(2)其实组合就是指:1.在一个类中以另外一个类的对象作为数据属性,称为类的组合。2.组合就是一个类中使用到另一个类,从而把几个类拼到一起。3.组合的功能也是为了减少重复代码
作用:将两个本来不相关的类联系起来,一般是两个类之间有显著的不同,很多时候还要附属关系(有相同的属性也有不同的属性)。比如水池和乌龟,手机和电池等等。
组合和继承什么时候使用呢?——无纵向关系时用组合,有纵向关系时用继承

这里的例子只是给大家参考理解,有错的地方希望大家能指出来我好改~谢谢!
加上这篇博文的例子不多想要有深的理解可以点击这篇博文好好品品,会让你有更深的理解!
好了就说这么多了,有什么问题可以评论,或者私发问我,我会尽力解答的哦~

你可能感兴趣的:(python-公有和私有以及继承组合)