1、什么是类和实例并说明他们之间的关系
-
类
类是一个抽象的概念,一个群体, 拥有共同特征,有类的一些行为;人类 -
实例
实例是类的一个具象化体现,类中的一个具体的个体,xx实例属于xx类; -
类与实例的关系:
封装
1、实例化
实例是由类这个抽象的概念实例化而生成的实际个体;
class Person:
pass
t = Person()
print(t,type(t))
<__main__.Person object at 0x000001C3685DA470> <class '__main__.Person'>
2、类属性、实例属性:
实例中有实例属性,类中由类的属性,相关属性都存在__dict__属性字典中;
实例中调用属性时,首先查看自身的__dict__,没有则去找类的__dict__
class Person:
age = 27
def __init__(self,name):
self.name = name
t = Person('tom')
print(t.name)
print(t.age)
3、类方法
类中有类方法,实际是一个函数,这个函数中可以实现相应功能;类方法也是属性的一种;
类方法绑定:类的实例,调用该类中使用类属性定义的的方法时,会出现绑定,将当前实例绑定在了方法上;因为该类的属性方法参数是self,代表实例本身;
class Person:
def showname(self,name): #在调用时self代表实例本身;
self.name = name #self.name即为实例属性;
return self.name
t = Person()
t.showname('tom')
初始化方法:在实例化的瞬间会自动完成,将实例赋予一些初始化的配置;
实例构造首先需要构建实例,然后在进行初始化方法,对实例本身配置;
class Person:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def showperson(self):
return self.name, self.age, self.gender
t = Person('zzh', 27, 'man')
print(t.showperson())
4、特殊属性:
类有类的特殊属性,实例有实例的特殊属性;
__dict__ #字典,存放的是属性,key为竖向,value为相应的值
__name__ #名字
__class__ #类型
__doc__ #文档属性
5、通过实例去访问属性:
1、首先找自身实例的__dict__,如果自身没有,则取找类的,如果类也没有则抛异常;
2、指定实例名去访问某一个属性,instance.__dict__[key],只能找实例里头的属性;
3、instance.__class__ 返回的是它的类;
instance__class__.__dict__ 返回的是类的属性
type(instance) 返回的是实例的类
4、可通过实例去找类,但是无法通过类去找实例;
实例存在,类必须存在;
类存在,实例并不是必须存在的,且一个类可以实例化多个实例;
继承
继承的规则:
1、在子类中,可以由自己的属性、方法,也可以继承自父类;
2、关于访问控制:私有的是不能被子类访问的;
本质是修改了名称放在了类的__dict__,只有当前类可以调;
公共的和保护的子类是可以访问的;
3、当父类中有一个方法,子类如果需要使用可以:
#直接使用父类的方法
#重新定义,覆盖父类的方法(重写、覆盖)
#不完全重新定义,在父类的基础上做一些增强(使用super方法去访问父类的类属性)
class Animal:
def __init__(self, name):
self._name = name
def jump(self):
raise NotImplementedError
class Dog(Animal):
def __init__(self):
super().__init__('Dog')
def jump(self):
return "{} jump ".format(self._name)
class Chicken(Animal):
def __init__(self):
super().__init__('Chicken')
def jump(self):
return "{} jump jump jump".format(self._name)
d = Dog()
print(d.jump())
c = Chicken()
print(c.jump())
多态
同一套接口(方法)在不同的类型(子类)上,表现的方式不一样就叫多态
多态的前提,有继承,有子类,子类当中有覆盖;
class Family:
def __init__(self, name):
self.name = name
class Zzh(Family):
def showname(self):
print(self.name)
class Km(Family):
def showname(self):
print(self.name)
class Zhy(Family):
def showname(self):
print(self.name)
f = Zzh('zzh')
m = Km('km')
s = Zhy('zhy')
print(f.showname())
print(m.showname())
print(s.showname())
2、类的实例方法、类方法和静态分别如何定义举例说明,并总结它们的应用场景
-
类的实例方法决定了怎么去定义这个实例,即后续如何调用这个方法(实例调用,还是直接使用类调用)
第一种:普通方法,可以通过实例化调用,使用类直接调用时需要手动传入实例(类方法绑定)
class A:
def showme(self):
return "{}'method".format(self)
#实例调用
t = A() #有类方法绑定,需要传入self,self代表实例本身
print(t.showme())
#类调用
print(A.showme(t)) #需要手动传入self
适用场景:指通过实例化传入参数保存下来,然后调用这个方法;
需求:需要对一个目录进行相关操作(复制,剪切),首先需要写入源路径、目标路径,然后执行相关动作;
import os
from pathlib import Path
from shutil import copytree,rmtree
class DirMethod:
def __init__(self,src:str,dest:str):
self.src = Path(src)
self.dest = Path(dest) / str(self.src.name)
def cp(self):
if not self.dest.exists():
copytree(self.src,self.dest)
else:
if not self.dest.is_file():
rmtree(self.dest)
copytree(self.src, self.dest)
else:
os.renames(str(self.dest),str(self.dest) + '.bak')
copytree(self.src, self.dest)
def shear(self):
if not self.dest.exists():
copytree(self.src,self.dest)
rmtree(self.src)
else:
if not self.dest.is_file():
rmtree(self.dest)
copytree(self.src, self.dest)
rmtree(self.src)
else:
os.renames(str(self.dest), str(self.dest) + '.bak')
copytree(self.src, self.dest)
rmtree(self.src)
t = DirMethod('E:\py_test','F:')
t.cp()
t.shear()
第二种:类方法装饰器,可通过实例化调用,也可以通过类直接调用;
class A1:
@classmethod
def showme(cls):
return "{}'s method".format(cls)
#实例调用
t = A1()
print(t.showme())
#类调用
print(A1.showme())
使用场景:可以直接通过类去调用方法,也可以通过实例去调用类方法;
需求:时间单位的转换,即可以使用实例化调用方法,也可以直接使用类调用方法;
class Timeconversion:
def __init__(self,time,unit = 's'):
self._s = None
self._m = None
self._h = None
if unit == 's':
self._s = time
elif unit == 'm':
self._m = time
self._s = self.min2sec(self._m)
else:
self._h = time
self._s = self.hours2sec(self._h)
@property
def h(self):
if self._h is None:
self._h = self.sec2hours(self._s)
return "{}Hours".format(self._h)
else:
return "{}Hours".format(self.sec2hours(self._s))
@property
def m(self):
if self._m is None:
self._m = self.sec2min(self._s)
return "{}Minutes".format(self._m)
else:
return "{}Minutes".format(self.sec2min(cls._s))
@property
def s(self):
return "{}Seconds".format(self._s)
@classmethod
def sec2min(cls,sec):
cls.sec = sec
if cls.sec >= 60:
return "{}Minutes".format(cls.sec / 60)
else:
return "{}Seconds".format(cls.sec)
@classmethod
def min2sec(cls,min):
cls.min = min
return "{}Seconds".format(cls.min * 60)
@classmethod
def min2hours(cls,min):
cls.min = min
if cls.min >= 60:
return "{}Hours".format(cls.min / 60)
else:
return "{}Minutes".format(cls.min)
@classmethod
def hours2min(cls,hours):
cls.hours = hours
return "{}Minutes".format(cls.hours * 60)
@classmethod
def sec2hours(cls,sec):
cls.sec = sec
if cls.sec >= 3600:
return "{}Hours".format(cls.sec / 3600)
@classmethod
def hours2sec(cls,hours):
cls.hours = hours
return "{}Seconds".format(cls.hours * 3600)
print(Timeconversion.sec2min(60))
t = Timeconversion(3600,'s')
print(t.s)
第三种:静态方法,与实例、类无关,只是这个方法是属于这个类的;
class A2:
@staticmethod
def showme():
return "static method"
#实例调用:
t = A2()
print(t.showme())
#类调用:
print(A2.showme())
使用场景:方法之间没有任何联系,方法与类也没有关系,只是说这个方法属于这个类;
需求:实现两个数字进行加减乘除的运算;
class Calculator:
@staticmethod
def add(x,y):
return x + y
@staticmethod
def sub(x,y):
return x - y
@staticmethod
def ride(x,y):
return x * y
@staticmethod
def excepts(x,y):
return x / y
t = Calculator()
print(t.add(1,2))
Calculator.add(1,2)
3、MRO是什么,描述其查找顺序
MRO,是方法解析顺序;返回的是一个继承关系;
查找顺序:
实例的__dict__ → 类__dict__ →如果有继承→ 父类 dict
class Person:
__a = 100
_b = 200
c = 300
def show(self):
print(self.__a)
print(self._b)
print(self.c)
class Zhangzhonghao(Person):
__a = 10000
_b = 2000
c = 3000
a = Zhangzhonghao()
print(a.show())
执行流程:
1、实例化,将变量a赋值给一个实例;
2、实例调用show方法,自身实例的__dict__中没有该方法,找类的,也没有,继续找父类的;
3、找到父类的show方法,执行:
- 打印self__a,为私有属性,自身实例__dict__没有,找类的__dict__没有,继续找父类的__dict__,self__a 等价于 _Person__a,所以只能使用父类的_Person__a;
- self._b和self.c,由于在自身类中__dict__中能够找到,所以优先使用自身类中的属性;
4、Mixin是什么,描述其应用场景
mixin类是对一个子类的功能补充,将一个方法抽取出来,然后通过多继承补充到其他的子类中;类似于装饰器;(一个子类缺了啥功能就补啥功能,组合的方式)
class Doc:
def __init__(self, content):
self.content = content
class Word(Doc):
pass
class Pdf(Doc):
pass
class PrintableMixin
def show(self):
print("** {} **".format(self.content))
class PrintableWord(PrintableMixin,Word):
pass
print(PrintableWord.__bases__)
print(PrintableWord.mro())
pw = PrintableWord('666666')
print(pw.show())
继承关系如图所示:
PrintableWord----->PrintableMixin---->word类---->Doc类---->object