一创建类和对象
面向对象编程其实就是对 “类” 和 “对象” 的使用。类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
二、定义类并执行类中的方法
calss 类名: #class是关键字,表示类
def 方法名(self,arrg):
print(arg)
return 1
对象=类名() #创建对象,类名称后加括号即可
ret = 对象.方法名(1)
print(ret)
self代指调用方法的对象,是特殊参数
三、面向对象三大特征
1、封装
2、继承
3、多态
例1 函数式编程:
def foo (name,sex,age,hobby,work):
print(name,sex,age,hobby,work)
foo('alex','女',23,'run','会计')
foo('王某','男',33,'game','无业')
foo('李某','女',25,'sing','歌手')
foo('刘某','女',27,'run','老师')
例2 面向对象(对例1转换):
class far():
def foo(self,name,sex,age,hobby,work):
print(name,sex,age,hobby,work)
obj=far()
obj.foo('alex','女',23,'run','会计')
obj.foo('王某','男',33,'game','无业')
obj.foo('李某','女',25,'sing','歌手')
obj.foo('刘某','女',27,'run','老师')
问题:self参数是什么?有什么用?
例3:
class foo():
def bar(self,arg):
print(self,arg) #<__main__.foo object at 0x000000000240ADA0> 23
obj1=foo()
print(obj1) #<__main__.foo object at 0x00000000021EACF8>
obj1.bar(23)
print('======================================')
obj2 = foo() #<__main__.foo object at 0x0000000002580EB8> 453
print(obj2) #<__main__.foo object at 0x0000000002580EB8>
obj2.bar(453)
结论:通过以上可以得出,执行obj1和obj2并打印时,它的值和它们执行形式参数self一样,由此可得,对象就是等于形式参数self.
例4
class foo():
def bar(self,arg):
print(self,self.name,self.age,self.sex,arg)
obj1= foo()
obj1.name ='xiaoxiao' #对对象参数进行赋值
obj1.age =45
obj1.sex ='male'
obj1.bar(454)
obj2= foo()
obj2.name ='wangwang'
obj2.age =41
obj2.sex ='female'
obj2.bar(23)
运行结果:
#obj1:<__main__.foo object at 0x0000000002580EB8> xiaoxiao 45 male 454
#obj2:<__main__.foo object at 0x00000000025A2320> wangwang 41 female 23
例5(对例2改进)
class far():
def foo(self,work):
print(self.name,self.sex,self.age,self.hobby,work)
obj=far()
obj.name='alex'#把公用的对象放到对象,以后就不用传了,即就是封装。
obj.sex='女'
obj.age=23
obj.hobby='run'
obj.foo('会计')
obj.foo('无业')
obj.foo('歌手')
obj.foo('老师')
类的特性一:封装
封装,其实就是将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容。需要:
1、将内容封装到某处
2、从某处调用被封装的内容
class far():
def __init__(self):#构造方法,根据类创建时自动执行
print('123')
obj=far() #123 这一句就是内部自动执行构造方法__init__()方法.
print(obj) #<__main__.far object at 0x0000000001D91710>
#因此
调用被封装的内容时,有两种情况:
1)通过对象直接调用
2)通过self间接调用
通过对象直接调用被封装的内容,上图展示了对象 obj 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
class far():
def __init__(self,name,sex,age,hobby):#初始化,python内部自动调用
self.name=name
self.sex=sex
self.age=age
self.hobby=hobby
def foo(self):
print(self.name) #通过self间接调用
obj=far('alex','male','34','run')#将'alex','male','34','run'分别封装到self的name,sex,age,hobby属性中
print(obj.name) #alex ,通过对象直接调用
obj.foo() #alex
注意: self 是一个形式参数,当执行 obj = far(‘alex’,‘male’,‘34’,‘run’),self 等于 obj
根据上个例子进行改进:
如果多个函数中有一些相同参数时,转换成面向对象。
class far(object):#object为什么?
def __init__(self,name,sex,age,hobby):#初始化函数,在生成一个角色时要初始化的一些属性就填写在这里
self.name=name
self.sex=sex
self.age=age
self.hobby=hobby
def goo(self,work):
self.work=work
print(self.name,self.sex,self.age,self.hobby,work)
obj=far('alex','女',23,'run')
obj.goo('会计') #python 会自动帮你转成 far.goo(self,'会计')
obj.goo('老师')
obj.goo('无业')
obj.goo('学生')
类的特性二:继承
class B():
def b1(self):#self是形式参数,self只用于调用方法的调用者
print('B.b1')
def b2(self):
print('B.b2')
def b3(self):
print('B.b3')
class C():
def c1(self):
print('C.c1')
s=C()
s.c1() #C.c1
s.b1() #报错
问题:s.b1()#AttributeError: ‘C’ object has no attribute ‘b1’,因为类B里没有b1这个方法,即不能调用。怎么办呢?
#改进—通过继承如下:
class B():
def b1(self):
print('B.b1')
def b2(self):
print('B.b2')
def b3(self):
print('B.b3')
class C(B):
def c1(self):
print('C.c1')
def b3(self):
print('C.b3')
s=C()
s.c1() #C.c1
s.b1() #B.b1
s.b3() #C.b3,注意:先在C类找方法,找不到时,看是否存在继承关系,若存在去父类找方法,否则报错。
想要同时执行父类的方法和子类的方法:
1、super方法:过super来调用父类的b3
2、父类.方法():类名调用时,自己传sel
改进如下:
class B():
def b1(self):
print('B.b1')
def b2(self):
print('B.b2')
def b3(self):
print('B.b3')
class C(B):
def c1(self):
print('C.c1')
def b3(self):
super(C,self).b3() #B.b3,推荐通过super来调用父类的b3(可以是父类的其他方法)方法
#或者:
#B.b3(self)#类名调用时,自己传self, self==s
print('C.b3') #C.b3
s=C()
s.b3()
类的多继承
3、python中支持多继承过程:
1)左侧优先
2)程序走一条道
3)同一个根时,根最后执行
class B():
def b1(self):
print('B.b1')
def b2(self):
print('B.b2')
class B1(B):
def b4(self):
print('B1.b4')
def b22(self):
print('B1.b22')
class B2(B):
def b5(self):
print('B2.b5')
def b2(self):
print('B2.b2')
class C(B1,B2):
def c1(self):
print('C.c1')
def b3(self):
print('C.b3') #C.b3
s=C()
s.b2() #B2.b2
#1、通过self找方法:
class B():
def b1(self):
print('B.b1')
def b2(self):
print('B.b2')
self.b5()#这时self==s,执行这一句时,相当于回到对象原点继续根据多继承的过程找方法,不过此时的对象方法以变为s.b5(),
def b5(self):
print('B.b5')
class B1(B):
def b4(self):
print('B1.b4')
def b22(self):
print('B1.b22')
class B2(B):
def b55(self):
print('B2.b55')
def b23(self):
print('B2.b23')
class C(B1,B2):
def c1(self):
print('C.c1')
def b3(self):
print('C.b3')
s=C()
s.b2()
#运行结果,时刻记住self是什么
#B.b2
#B.b5
#2、多继承和构造方法
class B():
def __init__(self):
print('B的init方法')
def b1(self):
print('B.b1')
def b2(self):
print('B.b2')
self.b5()#这是self==s,执行这一句时,相当于回到对象原点继续根据多继承的过程找方法,不过此时的对象方法以变为s.b5(),
def b5(self):
print('B.b5')
class B1(B):
def __init__(self):
print('B1的init方法')
def b4(self):
print('B1.b4')
def b22(self):
print('B1.b22')
class B2(B):
def __init__(self):
print('B2的init方法')
def b5(self):
print('B2.b5')
def b23(self):
print('B2.b23')
class C(B1,B2):
# def __init__(self):
# print('C的init方法')
def c1(self):
print('C.c1')
def b3(self):
print('C.b3')
s=C()#默认执行__init__方法
s.b5()
# 运行结果:
# B1的init方法
# B.b2
#B.b5
类的特性三:多态
多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。即允许将子类类型的指针赋值给父类类型的指针。
三大特性的作用:
1、封装可以隐藏实现细节,使得代码模块化;目的都是为了——代码重用。
2、继承可以扩展已存在的代码模块(类);目的都是为了——代码重用。
3、多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
class F1(object):
print('ok')
class S1(F1):
def show(self):
print ('S1.show')
class S2(F1):
def show(self):
print('S2.show')
def Func(obj): #一个接口,多种形态
obj.show()
obj1 = S1()
Func(obj1)
obj2 = S2()
Func(obj2)
#运行结果:
#ok
#S1.show
S2.show
切记:时刻记住如果每个类都有构造方法时,只要创建对象则会自动运行所对应的__init__方法。