这篇博客记录一些我以前记得不扎实的或没接触过的知识点。
class A():
name = "aaa"
age = 10
def __init__(self):
self.name = "zzz"
self.age = 20
def say(self):
print("self.name:", self.name) #打印的是实例对象的成员
print("__class__.name:", __class__.name) # 打印的是类对象的成员
def func():
print("~hahaha!")
class B():
name = "bbb"
age = 30
a = A()
b = B()
a.__dict__ # 检查对象的所有成员,赋值之前指向 A,啥都没有
A.__dict__ # 检查类的所有成员
a.func() # 错了
A.func() # 对了
# “鸭子模型”
# self 指的是实例对象,访问非绑定对象需要实例对象调用,如果使用类对象调用需要传入实例对象
a.say() # 对了
A.say() # 错了
A.say(a) # 对了
A.say(A) # 对了
A.say(B) # 对了
A.say(b) # 对了
1.使用默认内置变量(.__dict__ )检查类和对象的所有成员:
2.类定义之后会自动生成一个与类名同名的类实例:
对象实例在未赋值的情况下指向类实例。
3.鉴别两个变量是否为同一个变量 id():print(id(a) == id(b))
4.关于self参数:
类成员函数第一个参数 self 表示当前对象本身,可以换成任意名称,self 并不是一个关键字。
5.绑定类方法与非绑定类方法:
绑定类方法就是没有 self(或其它名字) 参数的类方法,调用时候需要使用:
class_name.func_name()
6.访问类成员:
__class__.xxx # 类成员
self.xxx # 实例成员
7.封装:
class A():
name = 'aaa' # 公有成员
__age = 18 # 私有成员
a = A()
print(a.name) # 对了
print(a.__age) # 错了
print(A.__dict__) # 使用这个查一下就发现,Python中并不是真的私有,而是换了个名字“_A__age”
print(a._A__age) # 对了
8.继承(is a):
每一个类都有一个父类object。
父类与子类一般为集合与子集的关系(不一定都是,灵活使用)。
子类不能访问父类私有成员。
父类成员并没有复制到子类,而是引用访问。
子类中与父类中同名的成员,优先使用子类中的成员。
扩充父类方法,可以直接调用父类方法。
查找顺序:
- 优先查找自己的变量,没有的话查找父类;
- 构造函数如果本类没定义,自动查找父类构造函数,需要注意的是,一旦查找到最近的构造函数,如果参数不匹配则会报错;
- super 是内建类,不是关键字,起功能是获取MRO(method resolution order)元组中第一个类,往往是父类。但是 super 和父类没什么关系;
- super 也可以扩充构造函数
单继承、多继承:
一般不推荐多继承,有些语言不允许多继承。
多继承有顺序。
菱形继承、钻石继承问题:实际上就是多继承产生的继承顺序问题,MRO是一张表,可以解决这个继承顺序问题。
Python 的MRO使用C3算法:子类永远在父类前面;多个父类按定义是写的顺序。
# 每一个类都有一个 object 基类
class Person():
name = "NoName"
age = 0
def sleep(self):
print("Sleepping...")
def work(self):
print("make money")
class Teacher(Person):
def make_test(self):
print("test")
# 扩充父类方法
def work(self):
Person.work(self)
# 下面这行是另一种方法
# super 是一个内建类,不是关键字
super().work()
self.make_test()
# 查看 MRO,继承元组
print(Teacher.__mro__)
9.多态:同一个对象,不同情况下有不同的状态出现
多态性:一种调用方式,不同的执行效果;
多态:同一事物多种形态;
Mixin 设计模式:Python 中与发布支持Mixin,Python中主要使用多继承方式对类进行扩展。
10.检测是否为子类 issubclass()
11.检测是否为实例 isinstance()
12.成员操作
检测成员:hasattr();
获取:getattr();
设置:setattr();
删除:delattr();
获取成员列表:dir()
class A():
name = "aaa"
class B(A):
pass
class C():
pass
a = A()
print(issubclass(B, A)) # 检测子类
print(isinstance(a, A)) # 检测实例
print(isinstance(A, A)) # 结果:False
print(hasattr(a, "name")) # 检测成员
13.内建:
__dict__
__doc__
__name__
__bases__
...
14.魔术方法:不需要认为调用,特定时刻自动触发
操作:
__init__():构造函数
__new__():对象实例化方法一般情况下不需要使用
__call__():对象当函数使用时触发
__str__():对象当 str 时调用
__repr__():和上一个差不多
描述符:
__get__()
__set__()
__delete__()
属性操作:
__getattr__()
__setattr__()
运算重载:
...
class A():
def __new__(self):
pass
def __init__(self):
pass
def __call__(self):
pass
def __str__(self):
pass
15.三种方法
实例方法:实例化之后才能用
静态方法:不需要实例化,类直接使用
类方法:不需要实例化,类直接使用
class Person():
# 实例方法
def eat(self):
print(self)
print("Eatting...")
# 类方法
@classmethod
def play(cls)
print(cls)
print("Playing...")
# 静态方法
@staticmethod
def say():
print("Saying...")
p = Person()
p.eat()
Person.play()
p.play()
Person.say()
p.say()