Python自动化运维 - day7 - 面向对象
概述
面向过程变成:函数式变成,C程序等
面向对象编程:C++,Java,Python等
类和对象:
类:是对事物的抽象,比如人类、球类
对象:是类的一个实例,比如足球、篮球
实例说明:
球类可以对球的特征和行为进行抽象,然后可以实例化一个真实的球体出来
Python中:
Class类:
一个类既是对一类拥有相同属性的对象的抽象、蓝图、原形。在类中定义了这些对象的都具备的属性和共同的方法
Object对象:
一个对象既是一个类的实例化后的实例,一个类必须经过实例化后方可再程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指的具体对象,人与人之间有共性,亦有不同
特性
面向对象的主要思想是:封装、继承、多态
Encapsulation封装:
在类中对数据的赋值,内部的调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance继承:
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism多态:
简单来说就是一种接口,多种实现方式
创建类
对象是特征(变量)与技能(函数)的结合,类是一些列对象共有的特征与技能的结合体
在现实生活中:先有对象,再总结归纳出的类
在程序中:一定先定义类,再实例化出对象
类定义(封装): 类把需要的变量和函数组合在一起,这种包含成为封装
类的结构:
class 类名:
成员变量-属性(类的属性,可以称为成员变量)
成员函数-方法(类的方法,可以称为成员函数)
定义类的语法:
class 类名: '''注释''' 类体(可以是任意代码)
在类内初始化属性:
def __init__(self,var1,var2...): -->成为构造函数 self.var1 = var1 -->称作实例变量(静态属性),实例变量的作用域为实例本身 pass
在类内定义功能(方法):
def 方法名(self,var1,var2...): pass
注意:类的方法称之为动态属性,定义方法和普通的函数相同,只不过第一个参数必须为self
在类下定义的变量称之为类变量,而在构造函数内定义的变量称之为实例变量。类变量主要存放,大家共用的属性
类的第一种使用方法:实例化
实例化方法1: p1 = Chinese('daxin',18)
实例化方法2: Chinese.__init__(p2,'daxin',18)
类的第二种使用方法:属性引用
方法1:Chinese.country (本质上实现的过程就是方法2)
方法2:Chinese.__dict__['country']
__dict__ : 查看类的属性字典,或者说类的名称空间
对象本身只会存放自己的数据属性
类会存放自己的数据属性和方法
绑定方法:
绑定到谁身上,就是给谁用的,谁来调用就会自动把自己当作第一个参数传入
例子:
#!/usr/bin/env python class People(object): color = 'yellow' def info(self): print "hello world!" print 'I am a %s' % self.color ren = People() ren.info()
这里定义的info函数(方法),指定了self参数(类的本身),表示把类People的属性传递进去,这样的话,我们在函数内部可以直接使用self.属性来调用
这里定义了类名为People的类,其中定义了成员变量color,并且定义了方法info,下面的 ren = People()等于是 People实例化的对象,我们直接通过该对象去调用类的方法和属性。
小结
对象的创建:
- 创建对象的过程称之为实例化:当一个对象被创建后,包含三个方面的特性:对象句柄、属性和方法。
- 句柄用于区分不同的对象(实例化出来的对象的名称可以称之为句柄)
- 对象的属性和方法与类中的成员变量和成员函数对应
- obj = myclass() 创建类的一个实例(对象)
- 通过对象来调用方法和属性
类的属性:
- 类的属性按照使用范围分为共有属性和私有属性,类的属性范围取决于属性的名称。
- 共有属性:在类中和类外都能调用的属性
- 私有属性:不能在类外调用的属性
- 定义方式:以'__'双下滑线开始的成员变量就是私有属性
- 可以通过instance._classname__attribute方式访问
- 内置属性:由系统在定义类的时候默认添加的,又前后双下划线构成,(__dict__,__module__)
类方法
可以在外部直接使用类名.方法名来调用的方法称为 类方法,类方法属于一种动态加载的概念,默认情况下只会加载某个方法,需要使用classmethod()函数来进行处理,才能直接在外部使用类名调用
- 动态类方法:可以直接通过self.属性来访问类属性,只有访问的时候配合classmethod函数,动态的去加载对应的类属性。(优点 省内存)
- 静态类方法:不传递self参数,需要通过staticmethod函数来加载所有类属性和类方法,需要通过类名.属性来调用,才可以在类外直接使用类名进行调用(优点,速度快)
- 类方法的第一个参数必须是self,因为self是类本身,如果不加self,将无法通过类或实例化的类调用类方法,如果想要通过类名来调用
静态方法:
@staticmethod
可以理解为和类没什么关系了,既截断了,类和类方法的关系,变成了单纯的一个函数了。
如果非要说有关系,那么就是调用的时候,必须要通过类进行调用
如果要调用类的属性,那么就需要使用 类名.属性名 来调用了
@staticmethod def eat(): print('{0} want to eat {1}'.format('name','apple'))
类方法(动态方法):
@classmethod
可以在类外直接使用 类名.方法名去访问的方法,并且类方法只能访问类变量,不能访问实例变量(类方法的self,代表着类,而非实例自己)
@classmethod def hello(self): print('hello %s' % self.name) -->这里打印的变量皆为类变量,不能传递实例变量
例子:
class People(object): color = 'yellow' -->类的全局静态属性 def __init__(self,name,age): self.name = name -->类的动态属性 self.age = age @classmethod -->装饰器版本(talk = classmothod(talk) ) --->动态类方法(也叫类方法) def talk(self): -->类的方法 print('%s want to talk' % self.name ) @staticmethod -->装饰器版本(say = classmothod(say) ) ---->静态类方法 def say(): -->类的方法 print('%s want to say' % People.color ) #函数版本 和装饰器版本效果相同 talk = classmethod(talk) say = staticmethod(say) 调用方法: People.talk() People.say()
私有方法,私有属性:
在变量或者方法前面加两个下划线(__),表示该变量/方法 为私有的,私有变量可以在内部定义方法来返回私有变量的方式访问,也可以通过类名的方式调用,但是不建议这样用
class People(object): cn = 'china' def __init__(self,name,age): self.name = name self.age = age self.__job = 'Linux' def __del__(self): print('THE END') daxin = People('daxin',20) xiaobai = People('xiaobai',30) print(daxin._People__job)
属性方法
把一个方法变成属性,进行调用
可以实现既对属性参数进行了检查,又能通过属性的方式进行调用
@property
标识后面的方法为属性方法,同时激活setter,deleter
@方法.setter
设置属性时调用方法
@方法.deleter
删除属性时调用方法
例子:
class Screen(object): def __init__(self): self._width = 0 self._heigh = 0 @property -->激活setter,deleter方法 def width(self): return self._width @width.setter -->通过实例.width = x 时,调用该方法 def width(self,value): if not isinstance(value,int): -->对传入参数进行检查 raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._width = value @width.deleter -->通过 del 实例.width 是,调用该方法 def width(self): del self._width @property def heigh(self): return self._heigh @heigh.setter def heigh(self,value): self._heigh = value @heigh.deleter def heigh(self): del self._heigh @property def resolution(self): return self._width * self._heigh s = Screen() s.width = 1024 s.heigh = 768 print(s.width) print(s.heigh) print(s.resolution)
静态字段方式(类属性)创建property。
property(getter,setter,deleter,'description ....')
例子:
class Screen(object): def __init__(self): self._weith = 0 self._heigh = 0 def get_weith(self): return self._weith def set_weith(self,value): self._weith = value def del_weith(self): del self._weith weith = property(get_weith,set_weith,del_weith) hello = Screen() print(hello.weith) hello.weith = 100 print(hello.weith)
继承
继承是面向对象的重要特性之一;
继承关系:继承是相对两个类而言的父子关系,子类继承了父类的所有共有属性和方法;
继承最大的好处是实现了代码的重用;
继承可以重用已经存在的数据和行为,减少代码的重复编写,Python在类名后使用一对括号来表示继承关系,括号中的类即为父类
格式:class Myclass( Parent Class):
如果父类定义了__init__方法,子类必须显式调用父类的__init方法
格式:ParentClaSS.__init__(self,argv) 高级用法:super(当前类名,self).__init__(所有的参数list)
如果子类需要扩展父类的行为,可以添加__init__方法参数
例子: class People(object): #-->加object表示新式类 def __init__(self,name): self.name = name def think(self): print('hello %s' % self.name) class Man(People): def __init__(self): People.__init__(self,'daxin') #-->显示的调用父类(通用) super(Man, self).__init__('name') #-->方法同上(新式类) daxin = Man() print(daxin.name)
重构父类的属性:
如果要在子类中重新构造属性,那么首先就需要把父类的属性进行继承,然后再构造自己的属性。
def __init__(self,name,age,money):
People.__init__(self,name,age)
self.money = money
这里定义了子类的构造函数,需要把父类的构造在本地执行,然后再定义子类的额外的属性
这里通过People.__init__的方式调用了父类的构造函数,还有第二种方式调用super(Man,self).__init__(name,age)这种方法更方便,这里的Man表示子类的名称
多继承:
只需在子类的括号中写多个 父类即可,但是需要注意的是,多继承会从左边开始继承,如果有父类调用子类的属性和其他父类有关系,那么就把其他父类放在左边预先继承
当要同时继承多个父类的时候,如果多个父类都有自己的构造函数,那么子类只会集成第一个父类中的构造函数
经典类和新式类:
class People: -->经典类 --> People.__init__
class People(object): -->新式类 --> super(Man,self).__init__
经典类和新式类主要的区别在于子类的继承策略上
多类继承策略:
1、广度优先:既先横向查找后 向上级查找 -->3.x程序默认
2、深度优先:即先深度查询 -->2.x程序默认
Python2的经典类是安深度优先来继承的,新式类是按广度优先来继承的
Python3经典类和新式类都是统一按广度优先来继承的
例子:
1 class People(object): 2 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 def eat(self,food): 8 print('%s eating %s' % (self.name,food)) 9 10 def sleep(self): 11 print('%s is sleeping..' % self.name) 12 13 14 class Man(People): 15 16 def __init__(self,name,age,money): 17 super(Man,self).__init__(name,age) 18 self.money = money 19 20 def playGame(self,game): 21 print('%s like play %s' % (self.name,game)) 22 23 24 class Woman(People): 25 26 def __init__(self,name,age,look): 27 super(Woman,self).__init__(name,age) 28 self.look = look 29 30 def huazhuang(self,face): 31 print('%s like to %s' % (self.name,face)) 32 33 34 daxin = Man('daxin',20,15000) 35 xiaona = Woman('xiaona',20,'beautiful') 36 37 print('''daxin's name is %s 38 daxin's age is %s 39 daxin's money is %s 40 xiaona's name is %s 41 xiaona's age is %s 42 xiaona's look is %s ''' % (daxin.name,daxin.age,daxin.money,xiaona.name,xiaona.age,xiaona.look)) 43 44 daxin.playGame('CF') 45 xiaona.huazhuang('huazhuang')
例子:
1 # Author:Lee Sir 2 3 class School(object): 4 5 def __init__(self,name,addr): 6 self.name = name 7 self.addr = addr 8 self.students = [] 9 self.teachers = [] 10 11 def guyong(self,tea_obj): 12 print('雇佣 [ %s ] ,工资为 [ %s ]' % (tea_obj.name, tea_obj.salary)) 13 self.teachers.append(tea_obj) 14 15 def zhuce(self,stu_obj): 16 print('[ %s ] 注册成功' % stu_obj.name) 17 self.students.append(stu_obj) 18 19 20 class SchoolMember(object): 21 22 def __init__(self,name,age,sex): 23 self.name = name 24 self.age = age 25 self.sex = sex 26 27 28 class Teacher(SchoolMember): 29 30 def __init__(self,name,age,sex,salary,course): 31 super(Teacher,self).__init__(name,age,sex) 32 self.salary = salary 33 self.course = course 34 35 def tell(self): 36 print(''' 37 -------- info for Teacher --------- 38 Name: %s 39 Age: %s 40 sex : %s 41 Salary: %s 42 Course: %s 43 ''' % (self.name,self.age,self.sex,self.salary,self.course)) 44 45 class Student(SchoolMember): 46 47 def __init__(self,name,age,sex,xuefei,grade): 48 super(Student,self).__init__(name,age,sex) 49 self.xuefei = xuefei 50 self.grade = grade 51 52 def pay_xuefei(self,sch_obj): 53 print('[ %s ] 缴纳学费 [ %s ]' % (self.name,self.xuefei)) 54 sch_obj.students.append(self) 55 56 def tell(self): 57 print(''' 58 -------- info for Students --------- 59 Name: %s 60 age: %s 61 sex: %s 62 xuefei: %s 63 Grade: %s 64 ''' % (self.name,self.age,self.sex,self.xuefei,self.grade)) 65 66 67 school = School('Oldboy Linux running','shahe') 68 t1 = Teacher('Alex',33,'M',15000,'PythonDevOps') 69 t2 = Teacher('Oldboy',56,'MF',200000,'Linux') 70 s1 = Student('Daxin',22,'M',5000,'Linux') 71 s2 = Student('xiaobai',22,'F',5000,'Python') 72 73 t1.tell() 74 t2.tell() 75 s1.tell() 76 s2.tell() 77 78 school.guyong(t1) 79 school.guyong(t2) 80 school.zhuce(s1) 81 school.zhuce(s2) 82 83 print(school.teachers) 84 85 for teacher in school.teachers: 86 print(teacher.name) 87 88 for student in school.students: 89 print(student.name)
内部类
所谓内部类,就是在类的内部定义的类,主要目的是为了更好的抽象现实世界。
例如:汽车是个类,汽车的地盘,轮胎也可以抽象为类,将其定义到汽车类中,则形成内部类,更好的描述汽车类,因为地盘、轮胎是汽车的一部分
内部类的实例化方法:
1、直接使用外部类调用内部类
2、现对外部类进行实例化后,然后再实例化内部类
3、可以使用类名来继续访问内部类的共有属性
例子:
class School(object): def __init__(self,name,age): self.name = name self.age = age class classroom(object): def __init__(self,job): self.job = job def say(self): print('%s want to say something ' % self.job) def talk(self): print('%s want to talking about ' % self.name ) #方法1 old = School('daxin',20).classroom('Linux') old.say() #方法2 new = School('daxin',20) sub_new = new.classroom('Linux') sub_new.say() #方法3 print(School.classroom.name)