python(面向对象三大特征、设计模式)

目录

    • 一、python中方法的重载
    • 二、方法的动态性
    • 三、面向对象的三大特征
      • 1、实现封装(隐藏)(私有属性和私有方法)
      • 2、继承
        • 2.1重写
        • 2.2mro()查看类的继承层次结构
        • 2.3object 类根
        • 2.4dir()查看对象属性
        • 2.5重写__str__方法
        • 2.6多重继承
        • 2.7mro()
        • 2.8super()获得父类的定义
      • 3、多态
      • 四、特殊方法和运算符重载
      • 五、特殊属性
      • 六、对象的浅拷贝和深拷贝
      • 七、组合
      • 八、设计模式_工厂模式实现
      • 九、设计模式_单例模式

一、python中方法的重载

在其他语言中可以定义多个重名的方法,只要保证方法签名唯一即可,方法签名包含三个部分:方法名、参数数量、参数类型
python中方法的参数没有类型(调用时确定参数的类型),参数的数量也可以由可变参数控制。因此,python中是没有方法的重载的,定义一个方法即可有多种调用方式,相当于实现了其他语言中的方法的重载。
如果在类体中定义了多个重名的方法,只有最后一个方法有效。

class Student
	def say_hi

二、方法的动态性

python是动态语言,可以动态的为类添加方法,或者动态的修改类的已有的方法。

#测试方法的动态性
class Person:
	def work(self):
		print('努力上班')

def play_game(a):
	print('{0}在玩游戏'.format(a))
def study(b)
	print('好好上学!')
p=Person()
p.work()
p.play_game() #报错,因为person class中没有play_game
#但是我们可以直接添加
Person.game=play_game
p.game() #-->翻译器翻译:Person.game(p)
# 也可以将原有方法修改
Person.work=study
p.work() #这里返回的结果不是原来的努力上班了,而是好好上学
class Person:
    def work(self):
        print('努力上班')
    def play(self):
        print('{0}在玩'.format(self))
p=Person()
p.play() #-->翻译器翻译:Person.play(p)

三、面向对象的三大特征

1、实现封装(隐藏)(私有属性和私有方法)

python对于类的成员没有严格的访问控制吸纳之,这与面向对象的其它语言有差别。
隐藏对象的属性和实现细节,只对外提供必要的方法。
通过前面学习的私有属性私有方法的方式实现封装,但是python最求简介没有严格的语法级别的‘访问控制符’,更多依靠程序员的自觉实现。

私有属性和私有方法,如下要点:
通常约定,两个下划线开头的属性是私有的,其他为公共的
类内部可以访问私有属性(方法)
类外部不能直接访问私有属性(方法)
类外部可以通过‘_类名__私有属性(方法)名’(下划线类名两下划线私有属性名)访问私有属性(方法)

测试私有属性&私有方法(本质相同方法就是属性)

class Employee
	def __init__(self,name,age):
		self.name = name #公开的
		self.age = age
e = Employee('vivi',18) #外部

print(e.name)
print(e.age)

print('*****************************')

# 把属性和方法私有化
class Employee
	def __init__(self,name,age):
		self.name = name #公开的
		self.__age = age #将属性私有化

	def__work(self): #私有方法
		print('好好学习,天天向上')
		print('年龄:{0}'.format(self.__age)) #类内部可以自己调用自己的私有属性
e = Employee('vivi',18) #外部

print(e.name)
print(e.__age) #类外部调用私有属性会报错
print(_Employee.__age) #可以访问了

@property装饰器
可以将一个方法的调用方式变成“属性调用”。给属性增加对应的get和set方法。

class Employee:
    def __init__(self,name,salary1):
    	self.__name=name
    	self.__salary=salary1
    
    def get_salary(self):
    	return self.__salary
    def set_salary(self,salary2):
    	if 1000<salary2<50000:
    		self.__salary=salary2
    	else:
    		print('输入错误')

e=Employee('vivi',10000) #传参给salary1
print(e.get_salary)#此时self.__salary=salary1,这时候get_salary相当于属性直接通过.get_salary来调用,得到的结果是10000,对比之前方法的调用print(e.get_salary()) 
e.set_salary=20000) #传参给salary2,通过逻辑后, self.__salary=salary2	
print(e.get_salary()) #得到的结果是20000

class Employeedef __init__(self,name,salary1):
    	self.__name=name
    	self.__salary=salary1
    
    @property
    def get_salary(self):
    	return self.__salary
    @get_salary.setter #是上面这个方法的setter,如果没有这句话则print(e.get_salary)的值不会改变
	def set_salary(self,salary2):
    	if 1000<salary2<50000:
    		self.__salary=salary2
    	else:
    		print('输入错误')
e=Employee('vivi',10000) #传参给salary1
print(e.get_salary)#此时self.__salary=salary1,这时候get_salary相当于属性直接通过.get_salary来调用,得到的结果是10000,对比之前方法的调用print(e.get_salary()) 
e.set_salary=20000  #传参给salary2,通过逻辑后, self.__salary=salary2	
print(e.get_salary ) #得到的结果是20000

2、继承

继承可以让子类拥有父类的特性,提高代码的重用性,是实现代码复用的重要手段。
设计上是一种增量进化,原有父类设计不变的情况下,可以增加新的功能,或者改进已有的算法。
如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,大大降低了工作的难度。已有的类我们称为父类或基类,新的类称为子类或派生类。

python继承多重继承,一个子类可以继承多个父类,语法格式:
class 子类类名(父类1[,父类2…]):
 类体
如果在类定义中没有指定父类,那么默认是object类,也就是说,object是所有类的父类,里面定义了一些所有类的共有实现,比如:__new __()
定义子类时,必须在其构造函数中调用父类的构造函数,语法如下:
父类名.__init __(self,参数列表)

class Person:
	def __init__(self,name,age,gender):
	self.name = name #实例属性
	self.age = age
	self.__gender = gender #私有属性
	
	def say_age(self): #在Person中创建一个实例方法
		print('你的年龄是')

class Student(Person): #继承Person
	def __init__(self,name,age,score)
		Person__init__(self,name,age) #显示的调用父类的初始化方法,不然解释器虽不会报错但是不会去调用
		self.score = score

s=student(vivi,19,100) #创建子类方法
s.say_age #子类中没有的方法,调用父类里面的,返回结果‘你的年龄是’
print(s.name) #拥有了父类的属性,返回值为‘vivi’
print(s.gender) #私有属性可以拥有不能直接用
print(s._Person__gender)# 调用私有属性

2.1重写

class Person:
	def __init__(self,name,age,gender):
	self.name = name #实例属性
	self.age = age
	self.__gender = gender #私有属性
	
	def say_gender(self): #在Person中创建一个实例方法
		print('你的性别是:',self.__gender) #同一个类中可以调用私有属性
	def say_name(self):
		print('你的姓名是{0}'.format(self.name))
		
class Student(Person): #继承Person
	def __init__(self,name,age,score)
		Person__init__(self,name,age) #显示的调用父类的初始化方法,不然解释器虽不会报错但是不会去调用
		self.score = score
	def say_name(self):
		print('报告,我的名字是{0}'.format(self.name))

s=Student('vivi',18,100)
s.say_gender()
s.say_name() #第一遍没有重写的时候返回的是你的名字是:vivi
s.say_name() #第二遍重写,返回的是报告,我的名字是:vivi

2.2mro()查看类的继承层次结构

通过类的方法mro(),或者类的属性__mro__可以输出这个类的继承层次结构

class A:pass
class B(A):pass
class C(B):pass

print(C.mro())

返回结果:
[,,,]

2.3object 类根

由上图可以看出,object类是所有类的父类,因此所有类都有object类的属性和方法所以有必要研究一下object类的结构

2.4dir()查看对象属性

# 定义一个类
class Person
	def __init__(self,name,age):
		self.name = name
		self.age = age
	def say_name(self):
		print('你的名字是:',self.name)

obj = object() #调用所有父类的父类,注意小写o
s = Person('vivi',18)
print(dir(obj))
print(dir(s))

python(面向对象三大特征、设计模式)_第1张图片
我们可以看出

  1. Person 对象增加了六个属性:
    dict module weakref age name say_age
  2. object 的所有属性,Person 类作为object 的子类,显然包含了所有的属性。
  3. 我们打印age、name、say_age,发现say_age 虽然是方法,实际上也是属性。只不过,这个属性的类型是“method”而已。
    age
    name
    say_age

2.5重写__str__方法

object中的__str__方法用于返回一个对于对象的描述,对应与内置函数str()经常用于print()方法,帮助我们查看对象的信息,并且__str__可以重写。

calss Person:
	def __init__(self,name):
		self.name = name
p = Person('vivi')
print(p) #这时默认返回的是__str__,也就是Person这个对象的说明<__main__Person object at 0x0042D410>
# 改写__str__
	def __str__(self):
		print('你好',self.name)
print(p) #这里返回的就是改过的‘你好’

2.6多重继承

一个子类可以有多个直接父类,虽然具备了多个父类的特点,但是把被类的整体层次搞得十分复杂,尽量避免使用

2.7mro()

class A:
	def say(self):
		print('AAA')
class B:
	def say(self):
		print('BBB')
class C(A,B)
	pass
c = C()
print(C.mro()) #[, , , ]
class C(A,B)
print(C.mro())#[, , , ]

2.8super()获得父类的定义

class A:
	def say(self):
		print('A',self)
class B(A):
	def say(self):
		super().say() #获得父类对象的定义
		print('B',self)

B().say()

3、多态

同一方法调用可能会产生不同的行为。类似于张三休息是睡觉,李四休息是打游戏。。。
a.break\b.break\c.break
注意以下两点:
1、多态是方法的多态,属性没有多态
2、多态的存在有两个必要条件,继承和方法重写

class Person:
	def thewayofeat(self):
		print('吃饭')
class Chinese(Person):
	def thewayofeat(self):
		print('用筷子')
class English(Person):
	def thewayofeat(self):
		print('用刀叉')
class India(Person):
	def thewayofeat(self):
		print('用手')
def manEat(m):
	if isinstance(m,Person):
		m.thewayofeat() #多态
	else:
		print('输入错误')

manEat(chinese())

四、特殊方法和运算符重载

python的运算符实际上是通过调用对象的特殊方法实现的。比如:
python(面向对象三大特征、设计模式)_第2张图片
python(面向对象三大特征、设计模式)_第3张图片

class Person:
	def __init__(self,name):
		self.name = name
	def __add__(self, other):
		if isinstance(other,Person):
			return "{0}--{1}".format(self.name,other.name)
		else:
			return "不是同类对象,不能相加"
	def __mul__(self, other):
		if isinstance(other,int):
			return self.name*other
		else:
			 return "不是同类对象,不能相乘"
p1 = Person("高淇")
p2 = Person("高希希")
x = p1 + p2
print(x)
print(p1*3)

五、特殊属性

python(面向对象三大特征、设计模式)_第4张图片

六、对象的浅拷贝和深拷贝

变量的赋值:只是形成两个变量,实质还是指向同一个对象
浅拷贝:源对象拷贝,子对象不拷贝
深拷贝:源对象子对象都拷贝

七、组合

‘is----a’关系使用继承(狗是动物)
‘has----a’关系使用组合(手机有cpu)
都是实现了代码的复用

class MobilePhone:
	def __init__(self,cpu,screen):
		self.cpu = cpu
		self.screen = screen
class CPU:
	def calculate(self):
		print("计算")
class Screen:
	def show(self):
		print("显示好看的图片")

c = CPU()
s = Screen()
m = MobilePhone(c,s)
m.cpu.calculate() #通过组合,我们也能调用cpu 对象的方法。相当于手机对象间接拥有了“cpu 的方法”
m.screen.show()

八、设计模式_工厂模式实现

设计模式是面向对象语言特有内容,是面临某一类问题是的固定做法。
工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象惊醒统一的管理和控制

class CarFactory:
	def create_car(self,brand)
		if brand == '奔驰'
		    return Benz()
		elif brand == '宝马'
			return BMW()
		elif brand == '比亚迪'
			return BYD()
		elseprint('没有这个品牌')
class Benz:
	pass
class BYD:
	pass
class BMW:
	pass
factory = CarFactory()
c1 = factory.creat_car('奔驰')

九、设计模式_单例模式

单例模式的核心作用是确保一个类只有一个实例,比关切提供一个访问该实例的全局访问点。
单例模式只生成一个实例对象,减少了对系统资源的开销。当一个对象的产生需要比较多的资源,可以产生一个单例对象,永久驻留在内存中,从而极大地降低开销。

class Single:
	__obj = None
	__init_flag = Ture #防止初始化两次
	def __new__(cls,*args,**kwargs)
		if cls.__obj ==None:
			cls.__obj = object.__new__(cls)
		return cls.__obj
	def __init__(self,name):
		if MySingleton.__init_flag:
			print("init....")
			self.name = name
			MySingleton.__init_flag = False #阻止第二次初始化
a = MySingleton("aa")
print(a)
b = MySingleton("bb")
print(b)		

返回结果:
init…
<main.MySingleton object at 0x01E15610>
<main.MySingleton object at 0x01E15610>

你可能感兴趣的:(python(面向对象三大特征、设计模式))