文章目录
一个简单的对比
面向过程式解决
def foo(name,age,gender,content):
print(name,age,gender,content)
foo(小明,10岁,男,上山去砍柴)
foo(小明,10岁,男,开车去东北)
foo(小明,10岁,男,开车去拉萨)
面向对象解决
class Bar:
def foo(name,age,gender,content):
print(name,age,gender,content)
obj = Bar()
obj.foo(小明,10岁,男,上山去砍柴)
obj.foo(小明,10岁,男,开车去东北)
obj.foo(小明,10岁,男,开车去拉萨)
咋 一对比感觉面向对象的编程比函数式编程更复杂,还多了几行代码。但是…
self
伪代码
class 类名:
def 方法名(self,arg):
print(arg)
return 1
对象名 = 类名()
ret = 对象名.方法名(1)
print(ret)
self --------谁调用的类(或者说谁用类创建了对象),self就代指谁,所以代指的是相应的对象
self的小示例
class Bar:
def foo(self,arg):
print(self)
print(self.name)
print(arg)
z = Bar()
z.name = "Elon Musk"
z.foo(666)
"""以下为输出的值
<__main__.Bar object at 0x012AC028>
Elon Musk
666
"""
如上代码所示:Bar是创建的一个类,而z是通过Bar这个类所建的对象,此时其实是通过一个指针指向了这个类所在的内存空间。那么在这个地方,z所代表的对象就是self,所以在类里面的self.name 就是z.name。这是一一对应的。
另外,可以通过类创建多个对象,那么每次在通过对象调用类的时候就会调用自己这个对象所代表的值。
创建两个对象,并使用self定义参数
class Bar:
def foo(self,arg):
print(self)
print(self.name,self.age,self.gender,arg)
print(arg)
z = Bar()
z.name = "Elon Musk"
z.age = "38"
z.gender = "male"
z.foo(666)
"""
<__main__.Bar object at 0x01842FB8>
Elon Musk 38 male 666
666
"""
x = Bar()
x.name = "Steve Jobs"
x.age = "50"
x.gender = "male"
x.foo(777)
"""
<__main__.Bar object at 0x01192FB8>
Elon Musk 38 male 666
666
<__main__.Bar object at 0x011AC0D0>
Steve Jobs 50 male 777
777
"""
以上为通过一个类创建了两个对象,通过这两个对象的对象名定义几个参数,如name,age,gender等等这些信息,这些信息是在对象里面定义的,而在程序运行的时候,会将相应的类的代码装入内存,然后再运行,所以每个对象在运行的时候self都代表自己的对象。并不是类
封装
什么叫封装
将共有的参数封装到对象里。 封装的本质是封装到内存里,用的时候可以直接拿即可。
封装示例
class Bar:
def add(self,comment):
print(self.name,self.age,self.gender,comment)
def delete(self,comment):
print(self.name,self.age,self.gender,comment)
def update(self,comment):
print(self.name,self.age,self.gender,comment)
def get(self,comment):
print(self.name,self.age,self.gender,comment)
z = Bar()
z.name = "Elon Musk"
z.age = "38"
z.gender = "male"
z.add("上山去砍柴")
z.delete("开车去东北")
z.update("开车去拉萨")
"""
Elon Musk 38 male 上山去砍柴
Elon Musk 38 male 开车去东北
Elon Musk 38 male 开车去拉萨
"""
如上所示:z是通过类创建的一个对象,所以像name,age,gender这些参数封装到了对象里,但是这些参数在类里面定义了,所以都是定义对象需要用到的共有参数。
构造方法__init__(self)
首先是个方法,构造就是创建的意思。
有一个特殊的作用,就是在通过类创建对象时会做两件事情:
1,通过类创建对象时,此__init__(self)会自动执行一遍
2,通过对象执代码内的一个特殊方法 “init(self)” 所以在创建对象的时候,这个self就是对象自己
验证构造方法两个特性
class Bar:
def __init__(self):
print("123")
z = Bar()
print(z)
"""
123
<__main__.Bar object at 0x0156C028>
"""
通过类Bar创建了一个对象z,而在创建对象的时候就执行了print(“123”),就已经执行了。
而最后一句print(z) 是打印z这个对象所指向的内存地址。
构造方法与其它方法唯一不同的是谁调用的问题__init__(self)是自动调用的。
所以init方法内放一些初始化的信息,在一创建的时候就自动形成了。
构造方法示例
示例一:
class Bar:
def __init__(self,n1,n2,n3,n4,n5,n6):
self.name1 = n1
self.name2 = n2
self.name3 = n3
self.name4 = n4
self.name5 = n5
self.name6 = n6
def foo(self):
print(self.name1,self.name2,self.name3,self.name4,self.name5,self.name6)
z = Bar(1,2,3,4,5,6)
z.foo()
"""
1 2 3 4 5 6
"""
示例二:
class person:
def __init__(self,name,age):
self.n = name
self.a = age
def show(self):
print("%s--%s"%(self.n,self.a))
CEO = person("Elon Musk",38)
CEO.show()
"""
Elon Musk--38
"""
示例三:创建两个对象
class person:
def __init__(self,name,age):
self.n = name
self.a = age
def show(self):
print("%s--%s"%(self.n,self.a))
Tesla = person("Elon Musk",38)
Tesla.show()
Apple = person("Steve Jobs",50)
Apple.show()
"""
Elon Musk--38
Steve Jobs--50
"""
示例四:固定一个参数
class person:
def __init__(self,name,age):
self.n = name
self.a = age
self.g = "male"
def show(self):
print("%s %s %s"%(self.n,self.a,self.g))
Tesla = person("Elon Musk",38)
Tesla.show()
Apple = person("Steve Jobs",50)
Apple.show()
"""
Elon Musk 38 male
Steve Jobs 50 male
"""
继承
什么是继承
类可以有子类,所以这里类就分为两种:
1,父类,或者叫基类
2,子类,或者叫派生类
所谓继承就是子类可以继承父类的的各种方法
继承不一定要全部继承,也可以选择不继承。
只能是类继承类
怎么继承
伪代码
class Father:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
pass
def swimming(self):
pass
class Son(Father):
def running(self):
pass
继承之后,如果没有特殊的定义,则父类的所有方法都可以直接拿过来用
多次继承
什么叫多次继承
就是儿子可以继承父亲的,那孙子可以继承儿子的,可以一级一级的继承
class GrandFather:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
pass
def swimming(self):
pass
class Father(GrandFather):
def running(self):
pass
class Son(Father):
def dancing(self):
pass
obj = Son()
obj.dancing()
obj.football()
重写(即重写不想直接继承的方法)
class GrandFather:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
print("GrandFather.smoking")
def swimming(self):
pass
class Father(GrandFather):
def running(self):
pass
class Son(Father):
def dancing(self):
pass
def smoking(self):
print("Son.smoking")
obj = Son()
obj.smoking()
"""
Son.smoking
"""
如上代码所示,将父类的方法自己重写一遍代码,表示不想用父类的方法。
重写的查找过程
- 重写先找该对象所指向的类中有没有该方法,有的话直接执行。
- 如果类指针指向的类中没有该方法,则判断是否继承了父类,若父类有该访问则直接执行父类的方法
- 依次顺着继承的方向往上找。
如何即执行自己的代码,又执行父类的方法(super)
super(Son,self).smoking()
class GrandFather:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
print("GrandFather.smoking")
def swimming(self):
pass
class Father(GrandFather):
def running(self):
pass
class Son(Father):
def dancing(self):
pass
def smoking(self):
super(Son,self).smoking()
print("Son.smoking")
obj = Son()
obj.smoking()
"""
GrandFather.smoking
Son.smoking
"""
使用Super代码,两个参数,先把自己传进去,再把self传入进去,固定写法。
另外一种方法实现
Father.smoking(self) 将对象传入到父类中进行执行
这种方法简单粗暴,直接调用。但是需要把self传入进去,
通过一个类创建一个对象,那么self就是这个对象,但是如果在类里面再调用其它的类,此时的self就等于这个对象,所以把self再传入去父类,则self其实就是这个对象。
class GrandFather:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
print("GrandFather.smoking")
def swimming(self):
pass
class Father(GrandFather):
def running(self):
pass
class Son(Father):
def dancing(self):
pass
def smoking(self):
#super(Son,self).smoking()
print("Son.smoking")
Father.smoking(self)
obj = Son()
obj.smoking()
"""
Son.smoking
GrandFather.smoking
"""
python 可以继承多个父类
多个父类的执行顺序
class GrandFather:
def basketball(self):
pass
def football(self):
pass
def smoking(self):
print("GrandFather.smoking")
def swimming(self):
pass
class GrandMother:
def Cooking(self):
pass
def Sing(self):
pass
def PinPong(self):
print("GrandMother.PinPong")
def smoking(self):
print("GrandFather.smoking")
class Father(GrandFather,GrandMother):
def running(self):
pass
obj = Father()
obj.smoking()
"""
GrandFather.smoking
"""
如上示例所示:Father这个类继承了两个父类,一个是GrandFather,另外一个是GrandMother,但是是有顺序的,先写的先查,后写的后查,如代码所示,都有smoking()方法,但是先找的是GrandFather中的方法。
多级继承的执行顺序
class Ancestor:
def Cooking(self):
print("Ancestor.cooking")
class GrandFather(Ancestor):
def basketball(self):
pass
def football(self):
pass
def smoking(self):
print("GrandFather.smoking")
def swimming(self):
pass
class GrandMother(Ancestor):
def Cooking(self):
print("GrandMother.cooking")
def Sing(self):
pass
def PinPong(self):
print("GrandMother.PinPong")
def smoking(self):
print("GrandFather.smoking")
class Father(GrandFather,GrandMother):
def running(self):
pass
obj = Father()
obj.Cooking()
"""
GrandMother.cooking
"""
- 多继承(一个子类继承了多个父类)的情况下,按照继承子类括号中从左往右的方向找,先从左边找,左边的父类没有方法再找左边的父类有没有父类,如果有继承往上找。
- 多继承的情况下,如果左边的继承线条找完了再找右边的父类,右边的父类没有相应的方法就再看父类还有没有父类。
- 多继承的情况下,如果左边的父类与右边的父类都还有一个共同的父类,则先找左边,直到非共同的,再找右边,最后再找这个共同的父类
一条道走到黑,先照 着左边的线路重新走。走完再走右边,如果有共同的根,左边先不去找,右边走完后再找。
使用self回调对象
class RequestHandler:
def serve_forever(self):
print("RequestHandler.serve_forever")
self.process_request()
def process_request(self):
print("RequestHandler.process_request")
class Minx:
def process_request(self):
print("Minx.process_request")
class Son(Minx,RequestHandler):
pass
obj = Son()
obj.serve_forever()
"""
RequestHandler.serve_forever
Minx.process_request
"""
如上述代码中逻辑,该代码片中使用了一条“ self.process_request()”,这里请注意,self指的就是对象,所以这里相当于执行了obj.process_reques(),所以在这里又转回去了。
关于__init__(self)在继承中执行情况
这个init方法,找到后执行一次,查找顺序还是按上述顺序找,并不会层层去查找,不会层层执行,但是如果想调用的时候执行一下继承的父类的init方法,可再用上述super或者另外一种方法调用一次执行,如下图所示:
示例一:
class Father:
def __init__(self):
print("Father.__init__()")
class Son(Father):
def __init__(self):
print("Son.__init__()")
obj = Son()
"""
Son.__init__()
"""
示例二:
class Father:
def __init__(self):
print("Father.__init__()")
class Son(Father):
def __init__(self):
print("Son.__init__()")
super(Son,self).__init__()
obj = Son()
"""
Son.__init__()
Father.__init__()
"""
另外需要记住的是,在通过创建对象的时候会执行init,这个时候会去找一遍
然后再通过对象执行方法的时候会再找一遍。
多态
在python里面不用考虑多态,python原生就是多态
而在java,或者c#中,是一种强类型的语言,在定义变量或者定义函数的时候需要指定变量的类型,例如在定义函数的时候,需要指定参数为字符串,整型等等,那么指定之后就只支持一种形态。
在java这种语言中,为了解决这个问题,支持创建子类,而子类可以定义其它的数据类型。以此来支持多种数据类型的形态。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++