1.类指针:子类找父类,实例找类都是通过自身携带的类指针去寻找。
类指针.png
2.Python3中所有的类都继承于Object类,可以省略不写,Python2不写继承Object类的话就是经典类。新式类和经典类的区别就是继承顺序。
① 经典类中是深度优先 :A->B->C->D->E->F
② 新式类中是广度优先(继承顺序按照C3算法,了解有这个算法即可):A-B-C-E-F-D
③ 在Python中可以利用mro()函数查看类的继承顺序
3.Python中是有多继承的,Java中只有单继承
4.多态:
① 在python中所有类都是多态的
② 在Java中,如果一个函数或者类,需要传入不同的类型B和C,那么B和C必须继承同一个类A,那么我们可以说传入的类型都为A,B和C是类型A表现出来的不同类型。
5.super方法:
① 在单继承中,super就是调用父类的方法
class User:
def __init__(self,name):
self.name = name
class VIPUser(User):
def __init__(self,name,level,strat_date,end_date):
# User.__init__(self,name)
super().__init__(name) # 推荐用法
# super(VIPUser,self).__init__(name)
self.level = level
self.strat_date = strat_date
self.end_date = end_date
② 在多继承中就是,按照mro的顺序寻找下个类中的同名方法
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
super(D,self).func()
print('D')
# 分析:D().func(),先搞清mro的顺序D->B->C->A->obj
# A-C-B-A-C-B-D
6.封装:
① 在类的静态变量,实例变量,实例方法加上两个下划线,就会变成私有的
class User:
__Country = 'China' # 私有的静态变量
__Role = '法师' # 私有的静态变量
def func(self):
print(self.__Country) # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形
print(User._User__Country)
print(User._User__Role)
# __Country -->'_User__Country': 'China'
# __Role -->'_User__Role': '法师'
# User.__aaa = 'bbb' # 在类的外部根本不能定义私有的概念
② 私有的变量不能被子类使用
7.property,setter,deleter装饰器
① property装饰器,把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值。什么时候用@property装饰器呢?举个例子,在一个圆形类中,有属性半径r,有函数area,这个函数返回的是面积。其实这个面积和半径一样,可以看做这个圆形类中的一个属性,那么这个时候就可以用@property装饰器。
from math import pi
class Circle:
def __init__(self,r):
self.r = r
# @property # 把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值
def area(self):
return pi * self.r**2
c1 = Circle(5)
print(c1.r)
print(c1.area)
② setter deleter装饰器
class Goods:
discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
# @后面的名字必须和函数名字相同
@price.setter
def price(self,new_value):
if isinstance(new_value,int):
self.__price = new_value
@price.deleter
def price(self):
del self.__price
apple = Goods('apple',5)
print(apple.price)
apple.price = 'ashkaksk' # 调用了@price.setter装饰的方法
del apple.price # 并不能真的删除什么,只是调用对应的被@price.deleter装饰的方法而已
print(apple.price)
8.反射
概念:用字符串数据类型的名字 来操作这个名字对应的函数\实例变量\绑定方法\各种方法
常见的反射:
① 反射对象的 实例变量/绑定方法
② 反射类的 静态变量/其他方法
③ 模块中的 所有变量(被导入模块和本模块)
# 反射
import sys
# getattr, hasattr
class Person:
Role = "法师"
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def sing():
return "我唱歌"
xm = Person(name="xiaoming", age=18)
# 访问对象xm的实例方法
name1 = xm.name
name2 = getattr(xm, "name") # 通过字符串的方法去访问
role = getattr(Person, "Role") # 通过字符串访问类的静态属性
s = getattr(Person, "sing") # 通过字符串访问类的静态方法
print(name1, name2, role, s())
def pig():
print('小p')
# 反射本模块的中的函数,如果是反射其他模块的,只需把第一个参数换成模块名
getattr(sys.modules['__main__'], "pig")()
9.两个装饰器 @classmethod 和 @staticmethod
① @classmethod :把一个对象绑定的方法 修改成一个 类方法
# 可以通过类名.方法名的方式调用,也可以实例.方法名的方式调用
# 什么时候用:我的理解是在在方法内部需要用到类名的时候
# 下面例子通过已知分数查看学生的level属性,在handle_score函数中直接返回了Students的对象,用到了类名,所以这时候用@classmethod
class Students:
def __init__(self, name, age, level):
self.name = name
self.age = age
self.level = level
@classmethod
def handle_score(cls, name, age, score):
if score >= 60:
return cls(name, age, "及格")
else:
return cls(name, age, "不及格")
stu = Students.handle_score("小明", 18, 60)
print(stu.level)
② @staticmethod:被装饰的方法会成为一个静态方法,这种常常是因为为了代码结构的完整性,将用不到self和cls的函数写在类中。
10.Python中的一些魔法方法
# __call__
# 一个对象如果是callable的,那么这个对象一定有__call__属性
class A:
def __call__(self, *args, **kwargs):
print('!!!-------')
A()() # 调用A的实例中的 __call__ 方法,输出:!!!-------
# __len__
# 如果想通过len(obj)的方式去获取一个实例中参数的个数,那么这个类中一定要实现__len__方法
class Cls:
def __init__(self,name):
self.name = name
self.students = []
def len(self):
return len(self.students)
def __len__(self):
return len(self.students)
py22 = Cls('py22')
py22.students.append('杜相玺')
py22.students.append('庄博')
py22.students.append('大壮')
print(py22.len()) # 执行类中__len__方法
print(len(py22)) #执行类中__len__方法
#__new__
#负责创建类的实例,并且先于__init__方法执行(通常情况下是使用 super(类名, cls).new(cls,参数1,参数2 …) 这样的方式)
# __new__创建的实例,就是init中self的空间地址,也是类的实例对应的空间地址。
#__new__的作用主要有两个,一个是补充init无法实现的功能,另外一个是实现函数的单例模式
#单例模式
class Baby:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self,cloth,pants):
self.cloth = cloth
self.pants = pants
b1 = Baby('红毛衣','绿皮裤')
print(b1.cloth)
b2 = Baby('白衬衫','黑豹纹')
print(b1.cloth)
print(b2.cloth)
#__str__和__repr__ 方法
# 在打印一个对象的时候 调用__str__方法
# 在%s拼接一个对象的时候 调用__str__方法
# 在str(一个对象)的时候 调用__str__方法
# 如果找不到__str__,就调用__repr__方法
# __repr__不仅是__str__的替代品,还有自己的功能
# 用%r进行字符串拼接 或者用repr(对象)的时候总是调用这个对象的__repr__方法
class clas:
def __init__(self):
self.student = []
def append(self,name):
self.student.append(name)
def __repr__(self):
return str(self.student)
def __str__(self):
return 'aaa'
py22 = clas()
py22.append('大壮')
print(py22) # aaa
print(str(py22)) # aaa
print('我们py22班 %s'%py22) # 我们py22班 aaa
print('我们py22班 %r'%py22) # 我们py22班 [大壮]
print(repr(py22)) # 我们py22班 [大壮]
网友评论