0%

类介绍

经典类 新式类
python2 默认 需要显式继承object
python3 不支持 默认
__new__ 不支持 支持
type() <type 'instance'> class类
__class__ class类 class类
__slots__ 不支持 支持
__getattribute__ 不支持 支持
相同父类构造函数 重复执行多次 只执行一次
基类搜索顺序 深度优先 广度优先

类方法

一个类在使用时,需要先实例化,再初始化

__new__

该方法是一个实例化方法(静态方法,因为所有新式类都继承object类,而object类中该方法设置为静态方法)
一个对象实例化时调用的第一个方法;

  • 返回创建的实例

  • 当有父类时先执行父类的new

  • 不常用,但当继承一个不可改变的类型比如tuple 或 string时,一般返回实例化对象,最后会调用__init__,除非重写

  • 如果返回的不是该类的实例化对象,则不执行__init__方法

1
2
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)

__init__

初始化方法,构造函数被调用时任何参数都传递给他;

无返回值

def __init__(self, *args, **kwargs):pass

__call__

让类的实例对象可以象函数一样调用

无返回值

def __call__(self, *args, **kwargs):pass

__del__

相当于析构函数
当一个对象在删除的时候进行清理工作,但当解释器退出时,如对象还在,不保证执行

无返回值

def __del__(self):pass

__repr__

当对象要输出时,用来整理其属性及方法为可输出的格式

无返回值

def __repr__(self):pass

__str__

可读性更好的obj==eval(repr(obj))的

无返回值

def __str__(self):pass

__dict__

好像是python3之后就没了

无返回值

def __dict__(self):pass

__setattr__

添加属性,并赋值

无返回值

def __setattr__(self, key, value):pass

__super__

super(B, self)首先找到B的父类A,然后把B的对象self转换为A的对象(通过某种方式),然后“被转换”的A对象调用自己的__init__;

无返回值
def __super__(self):pass

__getattr__

只有当__getattribute__抛出AttributeError时才调用

无返回值

def __setattr__(self, name):pass

__getattribute__

这个方法很重要,会用于属性访问、super、类继承等

访问某个属性时,无条件默认调用,找不到时会抛出AttributeError提示找不到这个属性;

为了避免无限递归,应该把获取属性的方法指向其父类,即super().__getattribute__(self, name)

def __getattribute__(self, name):pass

类属性

不论所属类是否实例化都会执行,使用时作为类的静态变量

__slots__

用于限定属性,即外部能访问的属性
__slots__ = ['var', ...]

__doc__

帮助信息

__name__

类型名称

__module__

所在模块

__class__

类型

__bases__

所继承的基类

__dict__

存储所有类型成员
key是属性名,value为属性值

实例的__dict__只存储与该实例相关的实例属性,即实例属性
类的__dict__存储所有实例变量共享的变量和函数,并不包含父类的属性
类的__dict__是一个只读,对象的__dict__是一个一般的;

1
2
3
4
5
6
7
8
9
10
11
12
 class C():
cls_name = '123'
def __init__(self, name):
self.name = name
pass
c = C('c')
print(c.__dict__)
print(C.__dict__)
"""输出
{'name': 'c'}
{'__module__': '__main__', 'cls_name': '123', '__init__': <function C.__init__ at 0x10e1ba950>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
"""

对象属性访问顺序

通过__getattribute__访问

  1. 实例属性
  2. 类属性
  3. 父类属性
  4. __getattr__()

在每个层级访问时数据描述符优先于dict,而dict查找优先于非数据描述符;
这里请参考python 描述符

私有变量

  • 以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量

  • 私有变量会在代码生成之前被转换为长格式(变为公有),转换机制为:

在变量前端插入类名,再在前端加入一个下划线字符。这就是所谓的私有变量轧压(Private name mangling)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Person():
def __init__(self):
self._age = 1
self.__age = 2
pass
def age(self):
print(self._age)
print(self.__age)
def _name(self):
print('_name')
def __name(self):
print('__name')

p = Person()
p._name()
p.age()
print(p.__dict__)
# p.__name() # AttributeError: 'Person' object has no attribute '__name'
# print(p.__age) # AttributeError: 'Person' object has no attribute '__age'
"""Out
_name
1
2
{'_age': 1, '_Person__age': 2}
"""