面向对象三大特征:封装、继承、多态
1.继承
面向对象编程 (OOP) 语言的一个主要功能就是“继承”,所谓继承就是使现有的类无需编码便可以拥有原有类的方法和属性。
被继承的类可以称之为父类、基类、超类。继承的类可以称之为子类、派生类。派生和继承是一体两面,从父类向子类看就是派生,从子类向父类看就是继承。子类和父类的关系可以用“is a”类表示,即子类是父类的一种,是一个更具体、更加强大的父类。python支持单继承和多继承。
继承的优点:
-
可以简化代码,减少冗余度
-
提高了代码的可维护性
-
提高了代码的安全性
1.1 单继承
所谓的单继承就是一个子类只有一个父类。子类会继承父类所有的属性和方法。
-
私有成员在子类中无法直接使用
-
子类对象无法直接使用继承自父类的私有成员
-
子类方法和父类方法重名,通过子类对象调用的是子类方法
#语法:
class 子类名(父类名):
pass
注意:object是Python中所有类的父类【一般情况下,如果一个类没有指明的父类,默认它的父类为object】
class Animal:
def __init__(self,name,age):
self.name = name
self.__age =age
....
class Dog(Animal):
def __init__(self,name,age,gender):
#调用父类构造方法的好处,简化了子类构造方法代码,实现了代码复用
#1. super(当前类名,self).__init__(实参列表) #实参不要带self
# super(Dog,self).__init__(name,age)
# 2. super().__init__(实参列表)#实参不要带self
# super().__init__(name, age)
#3. 父类名.__init__(self,其它参数)
Animal.__init__(self,name,age)
self.gender = gender
....
方法的改写
class Animal:
def __sleep(self):
print('睡饱饱')
def eat(self):
print('吃饭饭')
def sleeping(self):
self.__sleep()
....
class Dog(Animal):
#改写继承自父类的方法
def eat(self):
# Animal.eat(self)
super().eat()
print('香香的大骨头')
#添加新方法
def bark(self):
print('别跑,爷咬不死你')
# print(self.age)
dog = Dog('泰迪',5,'公')
dog.eat() #优先调用子类方法
dog.sleeping() #子类没有,则调用父类方法,一直找到object都没有,则报错
-
方法添加
1.2 多继承(理解、了解)
class 子类类名(父类1,父类2....):
子类类体
2.类成员
类成员包括:类属性和类方法,不同于成员属性和成员方法属于对象,类属性和类方法属于类,可以不实例化对象,直接通过类名调用,这些类成员为所有对象共有,一般用于对象间通信。
-
在程序运行期间类属性始终存在
-
class Person:
#类属性
name = '无名氏'
gender = '男'
__age = 0 #私有类属性
def __init__(self,name,age):
self.name = name #实例属性或成员属性
self.__age = age
#实例化对象
zhang = Person('张三',20)
#类属性调用方式
#调用方式:类名.属性名 对象.属性名
print(Person.name) #类属性可以不实例化对象调用
print(zhang.gender)
print(Person.__age) # 私有类属性不能通过类名直接调用
#访问的优先级 成员属性高于类属性
#如果成员属性名和类属性名冲突,优先访问成员属性,成员属性屏蔽类属性
#应该尽量避免成员属性和类属性重名
print(zhang.name) #张三
#删除对象的属性
del zhang.name
print(zhang.name) #无名氏 访问的是类属性
-
类方法属于类,为所有对象共有,可以通过类名或对象调用
-
类方法可以用来访问类属性
-
静态方法属于类的作用域内的全局函数
-
类方法和静态方法的区别,类方法第一个参数是类对象,由系统传入,静态方法没有
-
class Date:
def init(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod #类方法
def date_from_string(cls,date_string):
'''
:功能:根据传入字符串创建日期对象
:param cls 类对象,和类名作用一样
:param date_string: 日期字符串,格式必须是yyyy-mm-dd
:return: 日期对象
'''
year,month,day = tuple(map(int,date_string.split('-')))
return cls(year,month,day)
@staticmethod
def is_valid_date(date_string):
year,month,day = tuple(map(int,date_string.split('-')))
return year >= 0 and 1 < month <= 12 and 0< day <=31
d1 = Date.date_from_string('2018-05-29')
print(d1.year,d1.month,d1.day)
print(Date.is_valid_date('2018-5-29'))
实例的属性和方法都可以动态绑定,也就是可以在程序运行期间可以给程序增加功能,这对于那些静态语言来说无异于天方夜谭,但对python来说一切皆有可能
-
给对象动态添加的属性只属于这个对象,其它对象没有该属性
-
使用__ slots__限制属性的动态绑定:
class Cat:
__slots__ = ('gender','name','age','kind') #这个类的对象这能有这些属性
cat = Cat()
#1.动态绑定属性
cat.name = 'tom'
cat.gender = '公' #动态添加的属性
#cat.weight = 8 #不能添加这个属性,语法错误
定义一个函数,第一个参数要是self
def walk(self):
print(self.name)
cat.walk = walk
cat.walk(cat) #怪胎
#2.给对象绑定方法
from types import MethodType #引入types模块中的MethodType
cat.walk = MethodType(walk,cat) #给cat对象绑定walk方法
cat.walk()
#3.给类绑定实例方法 ,所有对象都可以使用
Cat.walk = walk
cat1 = Cat()
cat1.name = 'jerry'
cat1.walk()
__init__
和
-
__new__
是类方法;__ init__ 用于初始化对象,没有返回值 -
__new__
默认参数是cls,系统传递的是类名,__init__
默认参数是self,系统传递的是当前对象 -
class Dog:
def __new__(cls, *args, **kwargs):
print('new方法在执行')
// return super().__new__(cls,*args, **kwargs) #必须通过父类的__new__创建对象
return object.__new__(cls,*args, **kwargs)
def __init__(self,name,age):
self.name = name
self.__age = age
print('init方法在执行')
4.2 算数运算符重载
class MyTime:
def init(self,hour,minute,second):
self.hour = hour
self.minute = minute
self.second = second
def __add__(self, other):
if not isinstance(other,self.class):
raise TypeError('Not a MyTime')
second = self.second + other.second
minute = self.minute + other.minute + second // 60
hour = (self.hour + other.hour + minute // 60) % 24
return self.__class__(hour,minute % 60,second % 60)
#+=
def __iadd__(self, other):
self = self.__add__(other)
def __str__(self):
return "{}:{}:{}".format(self.hour,self.minute,self.second)
t1 = MyTime(5,34,45)
t2 = MyTime(8,45,34)
res = t1 + t2 #t1.__add__(t2)
print(res)
t1 += MyTime(3,20,10)
print(t1)
4.3 迭代器
class Fib:
def __init__(self):
self.x = 0
self.y = 1
def __iter__(self):
return self #返回当前对象
def __next__(self):
self.x ,self.y = self.y, self.x + self.y #迭代公式
if self.x > 1000:
raise StopIteration()
return self.x
4.4 __call__
如果一个类实现了__call__(slef, [,*args [,**kwargs]])
class Demo:
def __call__(self, *args, **kwargs):
print("我是函数,不过是假冒的")
d1 = Demo()
d1()
类装饰器
class Decrator:
def __call__(self, func):
def inner():
func()
print("*"*50)
return inner
@Decrator()
def test():
print("我是你们的小可爱")
2.1、设计模式概述
-
概念:对特定问题的一种解决方案,和平台、语言无关
-
作用
-
更好的理解面向对象
-
让你的代码更加优雅
-
使你的代码更加容易扩展和复用
-
面试时候的重点
-
设计模式的一些基本原则
-
高内聚,低耦合
-
单一职责
-
开闭原则(对修改封闭、对扩展开放)
2.2 单例
所谓单例也就是一个类只生成一个对象,无论你实例化多少对象,都是同一个对象
-
应用场景:数据库操作类,文件操作类等,可以减少资源的占用
2.3 实现
-
使用
__new__
class Singleton:
__instance = None # 保存实例的引用
def __new__(cls, *args, **kwargs):
if cls.instance is None: # 如果实例没有实例化
cls.__instance = object.__new__(cls,*args,**kwargs) #实例化对象,将引用存到__instance
return cls.__instance #返回对象
s1 = Singleton()
s2 = Singleton()
print(id(s1),id(s2))
if s1 is s2:
print('单例')