文章目录
__new__()
当创建实例对象时,python解释器的主要处理过程分为两步:
- 调用特殊方法__new__()创建实例对象
会查找该类对象中是否实现了__new__()方法,如果没有,则去父类中查找,直到类对象object - 调用特殊方法__init__()对创建的实例对象进行初始化
new()的返回实例对象会做为实参传递给__init__()的第一个参数self
class Parent(object):
def __new__(cls,*args,**kwargs):
print("父类的__new__()被调用,其形参cls对应实参的id:",id(cls))
obj = super().__new__(cls)
print("创建实例对象的id",id(obj))
return obj
class Child(Parent):
def __init__(self):
print("子类的__init__()被调用,其形参self对应实参的id:",id(self))
child = Child()
运行结果:
父类的__new__()被调用,其形参cls对应实参的id: 2599626482024
创建实例对象的id 2599651694744
子类的__init__()被调用,其形参self对应实参的id: 2599651694744
__getitem__(),__setitem__(),__delitem__()
如果想让自定义类对象的实例对象可以像列表和字典那样,使用中括号语法来操作数据,需要在类对象中实现一下特殊方法:
- __getitem__(self,key)
当执行object[key]时,会自动调用该方法 - __setitem__(self,key)
当执行object[key] = value时,会自动调用该方法 - __setitem__(self,key)
当执行 del object[key]时,会自动调用该方法
class MyClass(object):
def __init__(self):
self.data = {}
def __getitem__(self,key):
return self.data[key]
def __setitem__(self,key,value):
self.data[key] = value
def __delitem__(self,key):
del self.data[key]
mc = MyClass()
mc["one"] = 18
mc["two"] = 28
mc["three"] = 38
print(mc["one"])
del mc["three"]
print(mc.data)
运行结果:
18
{'one': 18, 'two': 28}
__call__()
如果在类对象中实现了特殊方法__call__(),那么就可以像调用函数一样直接调用这个类对象的实例对象,从而会自动调用特殊方法__call__()
class MyClass(object):
def __call__(cls,*args,**kwargs):
print(args,kwargs)
mc = MyClass()
mc()
mc(1,2,3,one = 1,two = 2,three = 3)
运行结果:
() {}
(1, 2, 3) {'one': 1, 'two': 2, 'three': 3}
__doc__与__dict__
类对象有一个特殊的属性__doc__,用于表示类对象的文档字符串,而文档字符串是位于类对象的第一行的字符串,通常用三个引号表示,是对类对象的功能的简要概述。
通过类对象的特殊属性__doc__可以访问类对象的文档字符串。
通过内置函数help()得到的帮助信息中会包含类对象的文档字符串。
class MyClass(object):
"""这是类对象的文档字符串
"""
pass
print(MyClass.__doc__)
help(MyClass)
运行结果:
这是类对象的文档字符串
Help on class MyClass in module __main__:
class MyClass(builtins.object)
| 这是类对象的文档字符串
|
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
对于指定的类对象和实例对象,可以访问特殊属性__dict__获得该类对象或者实例对象所绑定的所有属性和方法的字典。其中,字典中的键为属性名或者方法名。
class MyClass(object):
age = 18
name = "beryl"
def __init__(self):
self.ip = 12344
def func(self):
pass
@classmethod
def func1(cls):
pass
@staticmethod
def func2():
pass
MyClass.__dict__
mc = MyClass()
print(mc.__dict__)
运行结果:
mappingproxy({'__module__': '__main__',
'age': 18,
'name': 'beryl',
'__init__': <function __main__.MyClass.__init__(self)>,
'func': <function __main__.MyClass.func(self)>,
'func1': <classmethod at 0x2f207edf550>,
'func2': <staticmethod at 0x2f207edf5c0>,
'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'__doc__': None})
{'ip': 12344}
特殊属性之__slots__
如果想要对实例对象动态绑定的属性和方法的名称进行限制,可以在其对应的类对象中定义特殊方法__slots__,并且给__slots__赋值一个所有元素都为字符串的列表或元组,这样,对实例对象动态绑定的属性和方法的名称就都只能来自于__slots__中的元素。
class MyClass(object):
__slots__ = ("age","func1")
mc = MyClass()
mc.age = 18
def func1(self):
print("func1被调用")
from types import MethodType
mc.func1 = MethodType(func1,mc)
print(mc.age)
mc.func1()
运行结果:
18
func1被调用
def func2(self):
print("func2被调用")
from types import MethodType
mc.func2 = MethodType(func2,mc)
运行结果:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-18-df2af94662ca> in <module>()
2 print("func2被调用")
3 from types import MethodType
----> 4 mc.func2 = MethodType(func2,mc)
AttributeError: 'MyClass' object has no attribute 'func2'
特殊方法之__len__()
如果想让内置函数len()的实参可以是自定义类对象的实例对象,必须在自定义类对象中实现特殊方法__len__()。这样在调用内置函数len()时,在其内部会自动调用实参所对应类对象的特殊方法__len__()。
class MyClass(object):
def __len__(self):
return 18
print(len(MyClass()))
运行结果:
18