封装
封装指的是隐藏对象的属性和实现细节,仅对外提供一个公共的访问方式
好处:
(1)封装能分开类的属性,并将类的属性分成私有属性和公共属性,而私有属性仅供类本身调用使用(只能在
本类来访问),公共属性可供外部直接调用(公共用);
(2)可以彻底隐藏方法的内部细节实现(内部实现是如何的,不必要知道),仅提供公有的方法供外部访问,让
其他使用这个类的调用者不需要关心内部细节是如何实现的,而只要知道该如何调用就行;
(3)隐藏方法的内部细节实现的好处,可以让保留调用方法不变的同时,随意修改类的结构,而不影响其他
调用者运行结果。
python中封装的一些基本步骤:
1)在自定义类名后添加(object);
在python3中已经默认加在了object(即使没写object)
(2)对属性私有化,即在属性名前添加双下划线(),只允许本类访问;
(3)向外部提供 set 和 get 方法,便于外部通过这些方法来进行访问
需要注意的是,Python 中并没有像 C++/Java 语言中的 public、protected、private 等关键字来区分公有属性和私有属性。在 Python 语言中,是以属性命名方式来区分公有属性和私有属性的,若在属性名前加上双下划线(即),则表明该属性为私有属性(只能在本类中访问),否则为公有属性。
类似地,Python 中的方法也是在方法名前加上双下划线(即__),则表明该方法为私有方法(只能本类中才能访问),否则为公有方法。
例如,在 User 类中定义一个__name 私有属性。
# coding:utf-8
class User(object):
#私有化属性
def __init__(self):
self.__name=""
#在外部调用
user=User()
print(user.__name)
结果报错
私有化方法 User类show()私有方法
class User(object):
#私有化属性
def __show(self):
print("show()为私有方法")
#在外部调用
user=User()
print(user.__show())
当创建对象后,Python 解释器会默认调用**init()方法。其实,Python 中还有很多其他魔法
方法,比如当删除一个对象(del 对象名)时,Python 解释器也会默认调用一个方法,那就是del()方法**(也称为析构方法)
# coding:utf-8
class User(object):
#私有化属性
def __init__(self):
print("__init__被调用了")
def __del__(self):
print("删除了对象")
#创建对象
user=User()
print("删除前")
print(user)
del user
print("后边----")
print(user)
把引用给新的变量
# coding:utf-8
class User(object):
def __del__(self):
print("调用了__del__()")
# 创建对象
user1 = User()
# 引用指向了user2
user2 = user1
user3 = user2
del user1 ##user1引用指向user2,不会调用__del__(self)
print("引用指向其他对象后,user1不会被删除")
del user2 ##user2引用指向user3,不会调用__del__(self)
print("引用指向其他对象后,user2也不会被删除")
del user3 #没有其他引用后 调用__del__(self)
对于__del__()方法,需要注意以下几点:
(1)当创建一个对象后,直接调用 del 即可删除该对象;–把堆中的 self 删除了。
(2)当有 1 个变量保存了对象的引用时,此对象的引用计数则会加 1;
(3)当使用 del 删除变量指向的对象时,对象的引用计数不为 1(即此时无法删除原对象名),若持续删除变量指向的对象,则最终可以把对象删除。
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例和方法;或子类从父类继承方法,使得子类具有父类相同的行为。(父类的行为,需要让某个类具有相同的行为,让该类继承父类。)
class 父类名(object): ##(object)在 Python3 中可以略
...(省略)
class 子类名 1(父类名):
...(省略)
两类代码重复的时候,代码量大且臃肿,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错)这时需要使用到python的继承性
# coding:utf-8
#提取一个公共的类
class Animal(object):
#初始化
def __init__(self,name):
#属性
self.name=name
def eat(self):
print("吃东西")
def sleep(self):
print("喜欢在白天睡觉")
#猫 老鼠
class Cat(Animal):
pass
class Mouse(Animal):
pass
#创建cat对象
cat=Cat("小白")
cat.eat()
cat.sleep()
print("------------")
mouse=Mouse("米老鼠")
mouse.eat()
需要注意,当子类继承了父类后,具备以下特点;
1在定义子类时,小括号中就是父类的名字
2.子类能默认继承父类的__init__()方法
3.子类拥有父类非私有属性及非私有方法
4.子类可以拥有自己的属性和方法,子类可以对父类扩展
5.python的继承既支持单继承,也支持多继承(单继承就是一个子类继承一个父类,多继承就是一个子类继承多个父类)
多继承语法:
class 子类名(父类1,父类2,…)
…
# coding:utf-8
#父类1
class Lion(object):
def running(self):
print("擅长奔跑...")
#父类2
class Tiger(object):
def walk(self):
print("走走")
#子类狮虎兽
class Liger(Lion,Tiger):
pass
#创建对象
liger=Liger()
#奔跑
liger.running()
#行走
liger.walk()
当两个类里有相同属性时
# coding:utf-8
#父类1
class Lion(object):
def running(self):
print("擅长奔跑...")
#父类2
class Tiger(object):
def running(self):
print("跑跑")
#子类狮虎兽
class Liger(Lion,Tiger):
pass
#创建对象
liger=Liger()
#奔跑
liger.running()
print(Liger.__mro__) #查看先执行哪个
先执行的第一个父类里,先输出谁就执行谁的方法
1.重写父类的方法
语法格式:在子类中写一个与父类名称一样、参数一致的方法即可。
def 父类方法名(参数列表):
…
# coding:utf-8
#父类1
class Animal(object):
def __init__(self,name):
self.name=name
def eat(self):
print("喜欢吃...")
#猫
class Cat(Animal):
#重写父类方法
def eat(self):
print(self.name+"喜欢吃鱼")
class Dog(Animal):
# 重写父类方法
def eat(self):
print(self.name + "喜欢啃骨头")
cat=Cat("汤姆")
cat.eat()
dog=Dog("旺财")
dog.eat()
2.调用父类的方法
上述案例重写父类方法后,可以满足子类的基本需求,但此时若仍想要保留父类的 eat()行为,我们发现仅通过上述方式好像完成不了这个需求了,那么此时就需要考虑通过 super 关键字调用父类方法了,super 关键字语法格式如下:
super().方法 #Python2 super(子类名, self).方法
# coding:utf-8
#父类1
class Animal(object):
def __init__(self,name):
self.name=name
def eat(self):
print("吃..")
class Dog(Animal):
# 调用父类的eat()
def eat(self):
# super().eat() python3
super(Dog,self).eat() #python2
print(self.name + "喜欢啃骨头...")
dog=Dog("旺财")
dog.eat()
多态
多态是指不同类的对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式。这里的发送消息就是指方法的调用。
# coding:utf-8
class Person:
# 属性
def __init__(self, name):
self.name = name
# 行为
def start_car(self, traffic):
print(self.name + "正在启动..")
traffic.start()
# 停车
def stop_car(self, traffic):
print(self.name + "正在停止..")
traffic.stop()
# 单独提取一个父类
class Traffic:
# 初始化属性
def __init__(self, brand):
self.brand = brand
# 行为 开启
def start(self):
print(self.brand + "已经启动")
# 行为 停止
def stop(self):
print(self.brand + "已经停下来了")
# 子类 小轿车
class Car(Traffic):
pass
# 子类 自行车
class Bike(Traffic):
pass
# 创建对象
person = Person("小明")
car = Car("小轿车")
person.start_car(car)
person.stop_car(car)
bike= Bike("自行车")
person.start_car(bike)
person.stop_car(bike)
面向对象的六大原则
当一旦确定了类,就不应该再对其功能发生修改。这是面向对象设计中,最重要最核心的原则。
对象属性调用时, self.对象属性名或对象名.对象属性名
访问类属性语法格式:类名.类属性名
静态方法
在class类中使用,在函数前加@staticmethod,表示是静态函数,并不需要这个类被实例化就可以使用
静态方法需要通过装饰器@staticmethod来标识其为静态方法,且静态方法不需要多定义参数,如cls
访问静态方法的语法格式:类名.静态方法名
# coding:utf-8
class MyMethod(object):
#静态方法
@staticmethod
def print_info():
print("天气变冷了")
#调用
my=MyMethod() #可以不用创建对象实例 直接用类名.方法名
MyMethod.print_info()
类方法@classmethod
@classmethod
def run(cls):
print("类方法run()")
class User(object):
def start(self):
print("------start()---------")
u2=User()
u2.start()
#添加方法 类名.方法名=静态方法名或类方法名
User.run=run
#可以不用实例化 直接类名.方法
User.run()
#对象
u2.run()
一般来说,如果有用到实例对象的就用普通的方法,没有用到的话建议用静态方法。
设计模式
设计模式(Design Pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的,它适用于任何计算机语言。
工厂模式(Factory Pattern)是设计模式中非常常用的一个模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,通常在创建对象时不会暴露子类对象的逻辑方法,并且是通过使用一个共同的父类来指向新创建的对象。
注意,对于工厂模式的实际处理方式通常需要专门定义一个类(工厂:__Factory)来负责创建其他类的实例,而被创建的实例一般都具有共同的父类。此外,还需要注意的是,工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类都继承自一个父类)的实例。
# coding:utf-8
class AnimalDoll(object):
def __init__(self,name):
self.name=name
def shout(self):
print(self.name+"发出声音")
#子类
class DogDoll(AnimalDoll):
pass
class MonkeyDoll(AnimalDoll):
pass
class PandaDoll(AnimalDoll):
#重写
def shout(self):
print(self.name+"发出熊猫叫声")
#工厂类
class DollFactory:
#静态方法 生产
@staticmethod
def produce(flag):
if flag=="Dog":
dog=DogDoll("狗")
return dog
elif flag=="Monkey":
monkey=MonkeyDoll("猴子")
return monkey
elif flag=="panda":
panda=PandaDoll("熊猫")
return panda
else:
dog=DogDoll("小狗")
return dog
dog_doll=DollFactory.produce("Dog")
dog_doll.shout()
monkey_doll = DollFactory.produce("Monkey")
monkey_doll.shout()
单例模式
只允许创建对象时获得一个对象
class Apple(object):
def __new__(cls, *args, **kwargs):
print("先被调用")
return object.__new__(cls)
#初始化
def __init__(self):
print("调用了init方法")
#创建对象
apple=Apple()
单例模式(Singleton Pattern)是设计模式中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类自己负责创建自己的对象,同时确保只有单个对象被创建。
单例模式的特点:
(1)单例类只能有一个实例;
(2)单例类必须自己创建自己的唯一实例;
(3)单例类必须给所有其他对象提供这个唯一实例对象。
class Instance(object):
#初始化
__instance=None
def __new__(cls, *args, **kwargs):
if cls.__instance==None:
#创建对象
cls.__instance=object.__new__(cls)
return cls.__instance
def __init__(self):
self.name=""
#封装
def set_name(self,name):
self.name=name
def get_name(self):
return self.name
#给对象1设置name值
instance1=Instance()
#给对象2设置name值
instance2=Instance()
instance1.set_name("haha")
print(instance2.get_name())
上述代码中验证了只创建了一个唯一实例