Python3基础之学习笔记(七)-面向对象

1. 面向对象

1.1 面向对象介绍

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计),面向对象编程是一种编程方式,此编程方式需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。

世界万物,皆可分类,皆为对象。面向对象使程序更加容易扩展和更改。

1.2 面向对象使用

1.2.1 Class类

一个类即是对一类拥有相同属性的 对象的抽象、蓝图、原型。在类中定义了这些对象的都具备属性和方法 。

创建类:

class Foo:#Fool为类名
    def __init__(self,name):#构造方法,类创建对象时自动执行
        self.name=name#实例变量
    def Hello(self):#Hello为类方法,第一个参数必须是self
        print('Hello %s!'%self.name)

1.2.2 Object 对象

一个对象即是一个类的实例化,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象可以拥有不同的属性。

创建对象:

class Foo:#Fool为类名
    def __init__(self,name):#构造方法,类创建对象时自动执行
        self.name=name#实例变量
    def Hello(self):#Hello为类方法(也称为动态属性),第一个参数必须是self
        print('Hello %s!'%self.name)
 
def main():
    foo=Foo('BeiJing')#创建一个对象
    foo.Hello()#调用方法
 
if __name__ == "__main__":
    main()

1.2.3 实例变量与类变量

实例变量(也叫静态属性)是创建实例时使用的,属于对象,类变量是创建类时使用的,属于类,可以节省内存空间。

class Foo:
    a = 123  # 类变量
    name = 'World'  # 类变量
 
    def __init__(self, name):
        self.name = name#先在实例变量查找name,如果有,修改实例变量,没有则去类变量里找。
 
    def Hello(self):
        print('Hello %s!' % self.name)
 
 
def main():
    print(Foo.a)#打印类变量
    foo = Foo('BeiJing')
    foo.type=True#添加一个实例变量,相当与执行__init__方法里的self.type=True
    #也可以删除一个实例变量  del foo.type
    foo.a=1#创建一个实例变量,不会修改类变量
    foo.Hello()
    print(foo.name)#找的是实例变量
    print(Foo.name)
    Foo.a=2#修改类变量
 
 
if __name__ == "__main__":
    main()
 
'''
结果为:
123
Hello BeiJing!
BeiJing
World
 
'''

1.2.4 析构函数

析构函数:在实例释放、销毁的时候执行的,通常用于做一些收尾工作。

class Foo:
    def Hello(self):
        print("Hello World")
    def __del__(self):#析构函数
        print('对象销毁了')
foo=Foo()
del foo#销毁实例,程序结束时所有东西都会被销毁

1.2.5 私有属性和私有方法

私有属性和私有方法只能在类里面使用,私有属性和私有方法在名字前加__

class Foo:
    def __init__(self, name):
        self.__name = name#私有属性
    def __hello(self):#私有方法
        print("Hello World")

1.3 面向对象的三大特性

1.3.1 Encapsulation 封装

在类中对数据的赋值、内部调用对外部用户是透明的(使用私有属性和方法),外部用户不可见的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。

1.3.2 Inheritance 继承

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

单继承

#class People:#经典类
class People(object):#新式类
	def __init__(self,name,age):
		self.name=name
		self.age=age
	def eat(self):
		print('%s正在吃饭'%self.name)
	def sleep(self):
		print('%s正在睡觉'%self.name)
class Man(People):#类Man继承People
	def __init__(self,name,age,money):#重构父类初始化方法
		#People.__init__(self,name,age)#经典类的写法
		super(Man,self).__init__(name,age)#和上面注释的方法效果一样,新式类的写法
		self.money=money
	def work(self):
		print('%s 正在工作,每个月挣%s元'%(self.name,self.money))
	def eat(self):#重写父类eat方法
		print('这个男人正在吃饭')
	def sleep(self):#重构父类方法
		#People.sleep(self)#经典类的写法
		super(Man,self).sleep()#新式类的写法
		print('这个男人正在睡觉')
def main():
	man=Man('张三',18,5000)
	man.work()
	man.eat()
	man.sleep()


if __name__ == "__main__":
	main()

多继承

class People(object):
	def __init__(self,name,age):
		self.name=name
		self.age=age
	def eat(self):
		print('%s正在吃饭'%self.name)
	def sleep(self):
		print('%s正在睡觉'%self.name)
class Relation(object):
	def make_friends(self,obj):
		print('%s正在与%s交朋友'%(self.name,obj.name))
class Man(People,Relation):#多继承,如果自身不存在构造方法,则去父类中查找构造方法
	def __init__(self,name,age,money):
         #super(Man,self).__init__(name,age)#python2用法
		super().__init__(name,age)#python3用法,解决了钻石多继承问题
    	#super() 该方法返回继承顺序下一个类
		self.money=money

def main():
	m1=Man('张三',18,5000)
	m2=Man('李四',19,3000)
	m1.make_friends(m2)
if __name__ == "__main__":
	main()

经典类与新式类的区别:

  • 新式类都从object继承,经典类不需要。
  • 新式类相同父类只执行一次构造函数,经典类重复执行多次。
  • 新式类的MRO(method resolution order 基类搜索顺序)算法采用C3算法广度优先搜索,而经典类的MRO算法是采用深度优先搜索

Python 2.x中默认都是经典类,只有显式继承了object才是新式类 。

Python 3.x中默认都是新式类,经典类被移除,不必显式的继承object 。

Python2.x中

class A:
	pass
class B:
	pass
class C(B):
	pass
class D(C,A):
	pass
#执行顺序为:D->C->B->A

Python3.x中

class A(object):
	pass
class B(object):
	pass
class C(object): 
	pass
class D(A,B,C): 
	pass
#执行顺序为:D->A->B->C->object

python3多继承策略

E继承C和D,C继承A,D继承B

class A(object):
 
    def __init__(self):
        print('A')
 
 
class B(object):
 
    def __init__(self):
        print('B')
 
 
class C(A):
 
    def __init__(self):
        print('C')
 
 
class D(B): 
 
    def __init__(self):
        print('D')
 
 
class E(C, D):
    pass
#执行顺序是E->C->A->D->B

E继承C和D,C和D继承A

class A(object):
 
    def __init__(self):
        print('A')
 
 
class C(A):
 
    def __init__(self):
        print('C')
 
class D(A): 
 
    def __init__(self):
        print('D')
		
class E(C, D):
    pass
#执行顺序 E->C->D->A

总结:在两种不同的继承结构下,python3使用了不同的init方法的搜索策略。

1.3.3 Polymorphism 多态

一个接口,多种实现,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。

多态允许将子类的对象当做父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。

class Animal(object):
	def __init__(self,name):
		self.name=name
	def talk(self):
		pass
	@staticmethod#定义一个静态方法
	def animal_talk(obj):#实现多态,同一种接口多种实现
		obj.talk()
class Dog(Animal):
	def talk(self):
		print('小狗的名字是%s'%self.name)
class Cat(Animal):
	def talk(self):
		print('小猫的名字是%s'%self.name)
def main():
	d=Dog('小黑')
	c=Cat('小白')
	Animal.animal_talk(d)
	Animal.animal_talk(c)
if __name__ == "__main__":
	main()

1.4 静态方法、类方法、属性方法

静态方法:只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性。

类方法:只能访问类变量,不能访问实例变量。

属性方法:将一个方法变为一个静态属性。

class Dog(object):
	name='小黑'
	def __init__(self,name):
		self.name=name
		self.__sound=None
	@staticmethod
	def eat(food):#一个静态方法,实际上是一个函数,跟类没什么关系,可以通过类名直接调用
		print('一只小狗正在吃%s'%food)
	@classmethod
	def bite(self):#类方法,只能访问类变量name
		print('%s咬人了'%self.name)
	@property
	def cry(self):#不能传参数
		print('一只小狗正在%s'%self.__sound)
	#传参数
	@cry.setter#给属性方法传值
	def cry(self,sound):
		self.__sound=sound
	@cry.deleter#删除
	def cry(self):
		del self.__sound
def main():
	Dog.eat('包子')
	d=Dog('小白')
	d.bite()
	d.cry='汪汪汪'
	#del d.cry 删除属性
	d.cry

if __name__ == "__main__":
	main()
'''
结果为:
一只小狗正在吃包子
小黑咬人了
一只小狗正在汪汪汪

'''

1.5 深入了解类的特殊成员方法

class Foo(object):
	'''
	This is a Example
	'''
	a=None
	def __init__(self):
		self.name=None
		self.data={}
	def method1(self):
		pass
	def __call__(self, *args, **kwargs):#让一个实例对象可以被调用
		print(args,kwargs)
	def __str__(self):#定义一个对象返回值
		return 'Foo'
	#将一个实例变为字典
	def __getitem__(self, item):
		return self.data[item]
	def __setitem__(self, key, value):
		self.data[key]=value
	def __delitem__(self, key):
		del self.data[key]
def main():
	print(Foo.__doc__)#打印类的描述信息
	print(Foo().__module__)#打印类从哪里导入的
	print(Foo().__class__)#打印类信息
	f=Foo()
	print(f(1,2,3))#让一个实例对象可以被调用
	print(Foo.__dict__)#将类里面的所有方法和类变量打印出来
	print(f.__dict__)#打印实例里的实例变量
	f['age']=18
	print(f['age'])

if __name__ == "__main__":
	main()

创建类的另一种方式

def func(self):
    print('Hello World')
Foo=type('Foo',(object,),{'func':func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员
f=Foo()
f.func()

1.6 反射

通过字符串映射或修改程序运行时的状态、属性、方法。

def bulk(self):
    print("%s正在汪汪汪" %self.name)

class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self,food):
        print("%s正在吃%s"%(self.name,food))


d = Dog("小黑")
choice = input(">>:").strip()

if hasattr(d,choice):#判断属性是否在d这个对象里
	func=getattr(d,choice)#获取属性值,choice是属性名
	func('包子')#调用方法,相当于d.eat('包子')
else:
    setattr(d,choice,bulk) #往实例里动态添加一个动态属性,choice是属性名,bulk是属性值
	#setattr(d,choice,22) #往实例里添加一个静态属性。
    func = getattr(d, choice)
    func(d)#调用实例方法

1.7 异常处理

异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止。

常用异常:

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
FileNotFoundError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
#异常处理第一种方式
try:
	code
except Error1 as e:
	print(e)
except Error2 as e:
	print(e)
except Exception:
	print('未知错误')#不是前两个异常,出现了其他异常则执行这段代码
else:
	print('一切正常')#没有任何错误执行这个
finally:
	print('不管有没有错误都执行')
#异常处理第二种方式,多个异常统一处理
try:
	code
except (Error1,Error2) as e:
	print(e)
#异常处理第三种方式(不建议使用)
try:
	code
except Exception as e:
	print(e)
    
# 主动触发异常
try:
    raise TypeError('类型错误')#抛出一个异常
except Exception as e:
    print(e)

#8 自定义异常,需要主动触发
class CustomException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg

try:
    raise CustomException('类型错误')
except CustomException as e:
    print(e)

没有更多推荐了,返回首页