面向对象(自动化运维-9)
面向对象简介:
编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数,每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
特性:
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
类和实例:
定义类是通过class
关键字,初始化实例通过 变量名 = 类名()
#新式类 class Worker(object): # class关键字后面是类名,(object)表示类从哪个类继承下来。 pass #经典类 class Boss: pass A = Worker() #生成对象,也就是一个实例 B = Boss() # 生成对象,也就是一个实例 print(A) print(B) #执行结果 <__main__.worker object at 0x000002466737C240> <__main__.boss object at 0x000002466737C320>
类变量和实例变量
class Worker(object): leader = "bushaoxun" #实例变量 def __init__(self,name,age): # 构造函数 self.name = name # 类变量 self.age = age # 类变量 A = Worker("shaoxun",23) print(A.name,A.age,A.leader) A.leader = "guolijuan" # 为实例定义一个新的属性 print(A.name,A.age,A.leader) #执行结果 shaoxun 23 bushaoxun shaoxun 23 guolijuan #实例变量中有,从实例变量寻找,实例变量没有,找类变量
析构函数
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__
方法,在创建实例的时候,就把name,age
等属性绑上去,这个特殊的方法就叫做析构函数
__init__
方法的第一个参数永远是self
,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self
,因为self
就指向创建的实例本身。
class Worker(object): def __init__(self,name,age): # 析构函数 self.name = name self.age = age A = Worker("shaoxun",23) print(A.name,A.age) #执行结果 shaoxun 23
封装
我们从外部看Woker
类,就只需要知道,创建实例需要给出name
和age
,而如何打印person,都是在类的内部定义的,这些数据和逻辑被“封装”起来了,调用很容易,但却不用知道内部实现的细节。同时我们可以很容易的给类增加新的方法。
class Worker(object): def __init__(self,name,age): # 析构函数 self.name = name self.age = age def person(self): print("My name is %s,and my age is %s" %(self.name,self.age)) A = Worker("shaoxun",23) A.person() # 执行结果 My name is shaoxun,and my age is 23
继承
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。
最大的好处是子类获得了父类的全部功能,同时我们也可以在子类中对父类的属性和方法进行重构
class Person(object): def __init__(self,name): # 析构函数 self.name = name def working(self): print("%s is working" %(self.name)) class Man(Person): pass class Woman(Person): def working(self): print("%s is a woman" % self.name) A = Man("shaoxun") # 子类中没有构造函数找父类的构造函数 B = Woman("guolijuan") # 子类中重构父类函数 A.working() B.working() #执行结果 shaoxun is working guolijuan is a woman
多态
简单的说就是一种接口多种形态。
Pyhon 很多语法都是支持多态的,比如 len(),sorted(), 你给len传字符串就返回字符串的长度,传列表就返回列表长度。
class Person(object): def __init__(self,name): # 析构函数 self.name = name def working(self): print("%s is working" %(self.name)) class Man(Person): pass class Woman(Person): def working(self): print("%s is a woman" % self.name) A = Man("shaoxun") # 子类中没有构造函数找父类的构造函数 B = Woman("guolijuan") # 子类中重构父类函数 def work(instance): # 一种接口,多种形态 instance.working() work(A) work(B) #执行结果 shaoxun is working guolijuan is a woman
静态方法、类方法、和属性方法
静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
class Man(object): def __init__(self,name,age): self.name = name self.age = age @staticmethod def work(): print("i am working") a = Man("bushaoxun","32") #实例化 a.work() # 通过实例对象调用 man.work() # 通过类名调用 # 执行结果 i am working
类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class Man(object): name = "shaoxun" # 类变量 def __init__(self,name,age): self.name = name self.age = age @classmethod def work(self): print("%s is working" % self.name) a = Man("bushaoxun","32") #实例化 a.work() # 只能访问类变量,不能访问实例变量 #执行结果 shaoxun is working
属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class Man(object): def __init__(self,name,age): self.name = name self.age = age @property # 把方法变为属性方法 def work(self): print("%s is working" % self.name) a = Man("bushaoxun",32) a.work # 直接调用函数名,获取属性 # 执行结果 bushaoxun is working
类的特殊成员方法
1. __doc__ 表示类的描述信息
class Man(object): ''' This is a man status''' # 类的描述信息 def __init__(self,name,age): self.name = name self.age = age def work(self): print("%s am working" % self.name) print(Man.__doc__) # 打印类的描述信息
2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class Man(object): ''' This is a man status''' # 类的描述信息 def __init__(self,name,age): self.name = name self.age = age def work(self): print("%s am working" % self.name) a = Man("bushaoxun",32) print(a.__module__) # 操作的对象在哪个模块 print(a.__class__) # 操作的对象类是什么 #执行结果 __main__ <class '__main__.man'>
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
5. __call__ 对象后面加括号,触发执行。
构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Man(object): ''' This is a man status''' # 类的描述信息 def __init__(self,name,age): self.name = name self.age = age def work(self): print("%s am working" % self.name) def __call__(self, *args, **kwargs): print("I am callable",args) a = Man("bushaoxun",32) #执行 __init__ a("bushaoxun") #执行 __call__ # 执行结果 I am callable ('bushaoxun',)
6. __dict__ 查看类或对象中的所有成员
class Man(object): ''' This is a man status''' # 类的描述信息 def __init__(self,name,age): self.name = name self.age = age def work(self): print("%s am working" % self.name) a = Man("bushaoxun",32) #执行 __init__ print(Man.__dict__) # 查看类中的成员 print(a.__dict__) # 查看对象中的成员 # 执行结果 {'__module__': '__main__', '__doc__': ' This is a man status', '__init__': <function man.__init__ at 0x000001CE9BF6D2F0>, 'work': <function man.work at 0x000001CE9BF6D378>, '__dict__': <attribute '__dict__' of 'man' objects>, '__weakref__': <attribute '__weakref__' of 'man' objects>} {'name': 'bushaoxun', 'age': 32}
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Man(object): ''' This is a man status''' # 类的描述信息 def __init__(self,name,age): self.name = name self.age = age def work(self): print("%s am working" % self.name) def __str__(self): print("return str") return "pure man" a = Man("bushaoxun",32) #执行 __init__ print(a) # 执行结果 return str pure man
8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class man(object): def __getitem__(self, key): print("get",key) def __setitem__(self, key, value): print(key,value) def __delitem__(self, key): print("del",key) A = man() A["name"] #触发 __getitme__ A["name"] = "bushaoxun" # 触发__setitem del A["name"] # 触发 __delitem # 执行结果 get name name bushaoxun del name
反射详解
反射是通过字符串的形式操作对象相关的成员
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动
4个内置函数分别为:getattr、hasattr、setattr、delattr 获取成员、检查成员、设置成员、删除成员
class Man(object): def __init__(self,name): self.name = name def person(self): print("my name is %s" %self.name) A = Man("bushaoxun") # 检查是否含有成员 print(hasattr(A,"name")) # 有返回 Ture,没有则返回 False print(hasattr(A,"person_name")) # 有返回 Ture,没有则返回 False # 获取成员 print(getattr(A,"person")) # 如果有返回元素的值, print(getattr(A,"person_name","shaoxun")) # 如果没有则报错,可以给一个默认返回值 # 设置成员 setattr(A,"age",33) # 没有返回值 print(getattr(A,"age")) # 删除成员 print(delattr(A,"age")) # 同样没有返回值 # 执行结果 True False <bound method Man.person of <__main__.Man object at 0x000002F10CC0CCC0>> shaoxun 33 None