Python面向对象的编程

1概述

(1)面向对象编程

  面向对象的编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

(2)面向对象的特征

   1)类(Class):一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法

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

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

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

   5)多态(Polymorphism):多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。

(3)简单用法

class People(object):    #创建一个类,类名首字母要大写,并继承object类def walk(self):print "i am walking..."def talk(self):print "talking with sb..."p1 = People()   #创建一个对象,属于People类
p1.walk()        #调用walk方法
p1.talk()p2 = People()
p2.walk()
p2.talk()

2类的方法

(1)类的方法及属性

   1)类的方法——self

   类的方法(类函数)与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。

  如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)

   2)__init__()初始化

   作用:对实体进行初始化

   如:classDog:

      def__init__(self,name):

      self.DogName= name #必须赋值self,否则类中其它函数无法调用

(3)类的方法举例:

class People(object):info= 'test'  #共享变量,如果实例变量中找不到时,会找共享变量def __init__(self,name,age,job): #构造函数(实例化函数)self.name = name #变成实例变量,即将类的局部变量变为类的全局变量self.age = ageself.job = job#self.info = 't2'  #改变info的值def walk(self):print "i am walking..."def talk(self):print "talking with sb...",People.infop1 = People("Dayi",22,"it")
p2 = People("liuyi",24,"itman")
p3 = People("t3",18,"ll")p1.info = "P1"
print 'P1:',p1.info
People.info = "haha"       #如果构造函数中修改了info的值,则此处再无法修改
print 'p2:',p2.info
print 'p3:',p3.info

(4)析构函数

  在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,如关闭一些数据库连接,关闭打开的临时文件。

#!/usr/bin/env python
class Create_role:def __init__(self,name,age,job):self.name= nameself.age =ageself.job =jobdef show(self):print("Name:%s Age:%s Job:%s"%(self.name,self.age,self.job))def __del__(self):  #定义一个析构方法print("%s 已经彻底清理了" %(self.name) )r1 = Create_role("Dayi",18,"it")
print(r1.name)
r1.show()
del r1   #在r1调用结束后,立即执行析构方法,默认在程序执行完成之后才会执行
r2 = Create_role("xiaoliu",23,"no")
r2.show()
r3 = Create_role("hehe",30,"bois")

(5)类的私有属性及私有方法(类的封装)

   python默认的成员函数和成员变量都是公开的。在python中定义私有变量只需要在变量名或函数名前加上 "__"两个下划线,那么这个函数或变量就会为私有的了。在内部,将 __membername替换成 _classname__membername后,你在外部使用原来的私有成员的名字时,会提示找不到,但是可以在内部调用。

class People(object):info = 'test'  #共享变量def __init__(self,name,age,job): #构造函数(实例化函数)self.name = name #变成实例变量,即将类的局部变量变为类的全局变量self.__age = age  #定义一个私有属性,方法为在属性名前加__self.job = jobself.info = 't2'  #改变info的值self.info_dic = {"name":'day',"age":"33"}def get_info(self,info_type):if info_type == 'age':return self.__ageelif info_type == 'job':return self.jobdef __breath(self):    #定义一个私有方法,只能在内部调用,创建方法为函数名前加__print("%s is breathing..." %self.name)def walk(self):print "i am walking..."print(self.__breath())       #在内部调用私有方法def talk(self):print("talking with sb...",People.info)p1 = People("Dayi",22,"it")
p2 = People("liuyi",24,"itman")p1.walk()
print(p1.get_info("age"))
print(p1._People__age)   #调用只读属性

3类的的继承

   Python中类可以承继父类属性,也可以同时继承多个父类;形式为class 类名(父类1,父类2),子类可以继承父类的所有方法和属性,也可以重载父类的成员函数及属性,须注意的是子类成员函数若重载父类(即名字相同),则会使用子类成员函数

(1)类的基本继承

class SchoolMember(object):def __init__(self,name,age,sex): #创建父类构造函数self.name = nameself.age = ageself.sex = sexdef tell(self):    #父类创建一个方法print('''--info of %s--name:%sage :%ssex :%s'''%(self.name,self.name,self.age,self.sex))class Student(SchoolMember):    #创建一个类,并继承SchoolMemberdef __init__(self,name,age,sex,grade):   #创建子类继承函数SchoolMember.__init__(self,name,age,sex)   #让子类的构造函数继承父类self.grade = gradedef pay_money(self):       #给子类创建一个方法print("---%s is paying the tuition fee---" % self.name)def tell(self):SchoolMember.tell(self)    #让子类的tell()方法继承父类print("---from %s" % self.grade)
class Teacher(SchoolMember):def __init__(self,name,age,sex,course,salary):SchoolMember.__init__(self,name,age,sex)self.course = courseself.salary = salarydef teaching(self):print("Teacher %s is teaching class of %s" %(self.name,self.course))s = Student("dayi",33,"M","py s10")
t = Teacher("liu",18,"M","python", 60000)
s.tell()
t.tell()
s.pay_money()
t.teaching()

(2)类的多继承

   1)继承一:

class SchoolMember(object):def __init__(self,name,age,sex): #创建父类构造函数self.name = nameself.age = ageself.sex = sexdef tell(self):    #父类创建一个方法print '''--info of %s--name:%sage :%ssex :%s'''%(self.name,self.name,self.age,self.sex)
class School(object):def __init__(self,name,addr,tel): #再创建一个父类构造函数self.school_name = nameself.addr = addrself.tel = telself.stu_list = []self.tech_list = []
class Student(SchoolMember,School):    #创建一个类,并继承SchoolMember和School两个类def __init__(self,name,age,sex,grade):   #创建子类继承函数SchoolMember.__init__(self,name,age,sex)   #让子类的构造函数继承父类School.__init__(self,"beida","shahe",999) #让子类的构造函数继承父类并给传递参数self.grade = gradedef pay_money(self):       #给子类创建一个方法print "---%s is paying the tuition fee---" % self.namedef tell(self):SchoolMember.tell(self)    #让子类的tell()方法继承父类print '''---from school name :%sclass :%saddr  :%s'''%(self.school_name,self.grade,self.addr)s = Student("dayi",33,"M","py s10")
s.tell()
s.pay_money()

2)继承二(通过super):

class School(object):def __init__(self,name,addr):self.name= nameself.addr= addrself.students =[]self.staffs=[]def enroll(self,stu_obj):print("为学员%s 办理注册手续"%stu_obj.name )self.students.append(stu_obj)def hire(self,staff_obj):self.staffs.append(staff_obj)print("雇佣新员工%s" % staff_obj.name)class SchoolMember(object):def __init__(self,name,age,sex):self.name= nameself.age =ageself.sex =sexdef tell(self):passclass Teacher(SchoolMember):def __init__(self,name,age,sex,salary,course):super(Teacher,self).__init__(name,age,sex)self.salary= salaryself.course= coursedef tell(self):print('''---- info of Teacher:%s ----Name:%sAge:%sSex:%sSalary:%sCourse:%s'''%(self.name,self.name,self.age,self.sex,self.salary,self.course))def teach(self):print("%s is teaching course [%s]" %(self.name,self.course))class Student(SchoolMember):def __init__(self,name,age,sex,stu_id,grade):super(Student,self).__init__(name,age,sex)self.stu_id= stu_idself.grade= gradedef tell(self):print('''---- info of Student:%s ----Name:%sAge:%sSex:%sStu_id:%sGrade:%s''' % (self.name, self.name,self.age, self.sex, self.stu_id,self.grade))def pay_tuition(self,amount):print("%s has paid tution for $%s"% (self.name,amount) )school = School("qinghua","海淀")   #为School对象创建一个类t1 = Teacher("day",56,"MF",200000,"Linux")
t2 = Teacher("liu",22,"M",3000,"PythonDevOps")s1 = Student("dayi123",36,"MF",1001,"PythonDevOps")
s2 = Student("hehe",19,"M",1002,"Linux")t1.tell()    #调用Teacher类的tell()方法
s1.tell()
school.hire(t1)
school.enroll(s1)
school.enroll(s2)print(school.students)
print(school.staffs)
school.staffs[0].teach()#获取staffs列表中的第一个元素,并调用Teacher类中的teach方法
#school.students[0].pay_tuition(2000) for stu in school.students:     #循环School类中的student列表的元素并赋值给stustu.pay_tuition(5000)       #调用School中的pay_tuition()方法,并传一个参数

(3)继承总结

   py2 经典类是按深度优先来继承的,新式类是按广度优先来继承的

   py3 经典类和新式类都是统一按广度优先来继承的

4、多态(一个接口、多种实现):

  多态意味着就算不知道变量所应用的对象类型是什么,还是能对他进行操作,而它也回根据对象(或类)类型的不同而表现出不同的行为。

class Animal:def __init__(self,name):  # Constructor of the classself.name= namedef talk(self):  #Abstract method, defined by convention onlypass #raiseNotImplementedError("Subclass must implement abstract method")@staticmethoddef animal_talk(obj):   #将调用方法封装在父类中obj.talk()class Cat(Animal):def talk(self):print('%s :Meow!'%self.name)class Dog(Animal):def talk(self):print('%s: Woof! Woof!'%self.name)d = Dog("我c")
#d.talk()c = Cat("小猫猫")
#c.talk()
#
# def animal_talk(obj):
#     obj.talk()Animal.animal_talk(c)    #调用c对象
Animal.animal_talk(d)

5、静态方法和类方法

(1)静态方法:类的静态方法名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性,静态方法在创建时被装入staticmethod类型的对象中。静态方法创建时没有self参数,且能够被类本身直接调用。

(2)类方法:类方法创建时被装入classmethod类型的对象中,类方法可以直接用类的具体对象调用,但类方法只能访问类变量,不能访问类的实例变量。

(3)属性方法:类的属性方法可以把一个类的方法变成一个类的静态属性。

class MyClass(object):age = 22def __init__(self):self.name= "hehele"def sayhi(self):#必须实例化才能调用print("---sayhi 1")@staticmethoddef sayhi2():#静态方法,跟类没甚么关系,不需要实例化即可调用,类的工具包print("---sayhi 2")@staticmethoddef sayhi2_2(self):#静态方法,如果实在想传参了,可以这样搞print("---sayhi 2",self.name)@classmethoddef sayhi3(self):#不需要实例化即可调用,不能访问实例数据, 访问了实例化中的数据(self.name)调用时会报错。print("---sayhi 3",self.age,self.name)@property#将函数变成静态属性def sayhi4(self):print("---sayhi 4",self.name)return 'test'm = MyClass()
m.sayhi2()
m.sayhi2_2(m)    #调用时将参数给参进去
print(m.sayhi4)
# m.sayhi3()
# MyClass.sayhi3()

类的属性方法应用:

class Attribute(object):def __init__(self,name):self.name= nameself.__food= None@property     #将类的方法变成类的静态属性def eat(self):print("%s eating %s......" %(self.name,self.__food))@eat.setter   #修改属性def eat(self,food):print("set to food:",food)self.__food= food@eat.deleterdef eat(self):  #删除属性del self.__food
d = Attribute("dayi")
# print(d.__dict__)
d.eat
d.eat = "noodle"
d.eat      #修改属性后调用属性
del d.eat    #删除属性
d.eat        #删除时调用属性会报错

6、类的成员方法

(1)__doc__

  作用:获取类的描述信息

class Dayi():"""welcome to ...."""def func(self):"""func"""pass
print(Dayi.__doc__)   #会打印class的描述信息

(2)__module__

  作用:表示当前操作的对象在那个模块

   __class__

  作用:表示当前操作的对象的类是什么

from lib import Dayi
tim = Dayiprint(tim.__module__)
print(tim.__class__)

(3)__call__

  作用:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于__call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Call():def __init__(self):passdef __call__(self, *args, **kwargs):print("__call__")obj = Call()    #执行__init__
obj()           #执行__call__

(4)__dict__

  作用:查看类或对象中的所有成员,以字典的形式显示,

(5)__str__

  作用:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值

class Dayi(object):def dayi123(self):print("dayi123")def __str__(self):return "hello"obj = Dayi()
print(obj)   #没有__str__时输出类的内存地址,有__str__时,输出值

(6)__getitem__、__setitem__、__delitem__

  作用:用于索引操作,如字典。以上分别表示获取、设置、删除数据

class Foo(object):def __init__(self):self.data = {}def __getitem__(self, key):print('__getitem__', key)return self.data.get(key)   #读取字典中key的值def __setitem__(self, key, value):print('__setitem__', key, value)self.data[key] = value       #设置字典中keydef __delitem__(self, key):print('__delitem__', key)del self.data[key] #删除data中的为key的数据obj = Foo()
obj['name'] = "hehe"
print(obj.__dict__)
print(obj.data)
# del obj["name"]    #删除时自动触发__delitem__
result = obj['k1']  # 自动触发执行 __getitem__
print(obj.__dict__)
obj['k2'] = 'kk2'  # 自动触发执行 __setitem__
print(obj.__dict__)  #查看类的字典时,类的字典内容为{'data': {'k2': 'kk2', 'name': 'hehe'}}
del obj['k2']
print(obj.__dict__)