学习笔记,仅供参考,有错必纠
文章目录
- 类对象的特殊方法之`__del__()`
- 类对象的特殊方法之`__getattr__()`
- 类对象的特殊方法之`__getitem__()`
- 类对象的特殊方法之`__call__()`
- 类对象的特殊属性之`__doc__`
python 学习高级篇
# 支持多行输出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默认为'last'
类对象的特殊方法之__del__()
系统会自动销毁不再需要的对象以释放内存。因此,当对象被销毁时通常不需要手动地执行清理工作。但是,当使用我们自己创建的资源时,可能需要执行一些额外的清理工作,例如,如果创建了一个自定义的类对象来打开一个文件并写入一些数据,可能需要在实例对象被销毁之前关闭该文件。为了执行这些额外的清理工作,可以在自定义的类对象中实现特殊方法__del__()
当内存中的对象被销毁(垃圾回收)之前,会自动调用其对应的特殊方法__del__()
,当对象的引用计数为0时,对象并不会立刻被销毁(垃圾回收),何时进行垃圾回收是不确定的。因此特殊方法__del__()
何时会被调用也是不确定的。
class MyClass(object):
def __del__(self):
print("特殊方法__del__被调用")
mc = MyClass()
del mc
特殊方法__del__被调用
类对象的特殊方法之__getattr__()
当访问实例对象的属性或方法时,如果指定的属性或方法不存在,就会抛出AttributeError
class MyClass(object):
pass
mc = MyClass()
# print(mc.data)
# mc.do_sth()
class SomeClass(object):
def __getattr__(self, name):
if name == "data":
return 18
elif name == "do_sth":
return print
raise AttributeError("'SomeClass' object has no attribute '%s'" % name)
sc = SomeClass()
print(sc.data)
sc.do_sth(1, 2, 3)
print(sc.score)
18
1 2 3
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-8800c5726d47> in <module>()
19 print(sc.data)
20 sc.do_sth(1, 2, 3)
---> 21 print(sc.score)
<ipython-input-2-8800c5726d47> in __getattr__(self, name)
14 elif name == "do_sth":
15 return print
---> 16 raise AttributeError("'SomeClass' object has no attribute '%s'" % name)
17
18 sc = SomeClass()
AttributeError: 'SomeClass' object has no attribute 'score'
类对象的特殊方法之__getitem__()
对于自定义类对象的实例对象,在默认情况下,是不能像列表和字典那样使用中括号语法来操作数据的.
# 报错示例
class MyClass(object):
pass
mc = MyClass()
print(mc[3])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-408294622327> in <module>()
4
5 mc = MyClass()
----> 6 print(mc[3])
TypeError: 'MyClass' object does not support indexing
class MyDict(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]
md = MyDict()
md["one"] = 18
md["two"] = 32
print(md.data)
print(md["two"])
del md["two"]
print(md.data)
{'one': 18, 'two': 32}
32
{'one': 18}
类对象的特殊方法之__call__()
如果在类对象中实现了特殊方法__call__()
,那么就可以像调用函数一样直接调用这个类对象的实例对象,从而会自动调用特殊方法__call__()
class MyClass(object):
def __call__(self, *args, **kwargs):
print(args, kwargs)
mc = MyClass()
mc()
mc(1, 2, x = 3, y = 4)
() {}
(1, 2) {'x': 3, 'y': 4}
内置函数callable用于判断指定对象是否是可调用的。
除了函数对象是可调用的之外,对于实现了特殊方法__call__()
的类对象,其实例对象也是可调用的.
print(callable(print))
def do_sth():
pass
print(callable(do_sth))
print(callable(MyClass()))
True
True
True
类对象的特殊属性之__doc__
调用内置函数dir得到的类对象的所有属性中,有一个特殊属性叫__doc__
,用于表示类对象的文档字符串。
什么是类对象的文档字符串(docstring)
与函数的文档字符串类似,位于类对象的第一行的字符串被称为类对象的文档字符串,通常用三个引号表示。
类对象的文档字符串是对类对象的功能的简要描述。
在PyCharm,类对象的文档字符串用灰色显示。
之所以称为”文档”字符串,是因为可以使用工具根据文档字符串自动地生成文档。
应该养成编写文档字符串的习惯,以提高程序的可读性。
class MyClass(object):
"""这是类对象的文档字符串"""
pass
print(list.__doc__)
print(MyClass.__doc__)
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
这是类对象的文档字符串
访问类对象的文档字符串
通过类对象的特殊属性__doc__
可以访问类对象的文档字符串。
调用内置函数help()得到的帮助信息中会包含类对象的文档字符串。
print(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)
None
类对象的特殊属性之__slots__
Python是动态语言,所以,在创建对象之后,可以对其动态地绑定属性和方法。如果想要对实例对象动态绑定的属性和方法的名称进行限制,可以在其对应的类对象中
定义特殊属性__slots__
,并给__slots__
赋值一个所有元素都为字符串的列表或元组,这样,对实例对象动态绑定的属性和方法的名称就只能来自于__slots__
中的元素。
class MyClass(object):
__slots__ = ("attr1", "do_sth1")
mc = MyClass()
mc.attr1 = 18
print(mc.attr1)
mc.attr2 = 56
18
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-00d2b782091c> in <module>()
6 mc.attr1 = 18
7 print(mc.attr1)
----> 8 mc.attr2 = 56
AttributeError: 'MyClass' object has no attribute 'attr2'
def do_sth1(self):
print("do_sth1被调用了")
from types import MethodType
mc.do_sth1 = MethodType(do_sth1, mc)
mc.do_sth1()
def do_sth2(self):
print("do_sth2被调用了")
mc.do_sth2 = MethodType(do_sth2, mc)
do_sth1被调用了
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-17-1f6069f24f7c> in <module>()
9 print("do_sth2被调用了")
10
---> 11 mc.do_sth2 = MethodType(do_sth2, mc)
AttributeError: 'MyClass' object has no attribute 'do_sth2'
print(MyClass().__dict__)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-18-28c05d22bcd8> in <module>()
----> 1 print(MyClass().__dict__)
AttributeError: 'MyClass' object has no attribute '__dict__'
class MyChildClass1(MyClass):
pass
mcc1 = MyChildClass1()
mcc1.attr3 = 56
print(mcc1.attr3)
class MyChildClass2(MyClass):
__slots__ = ("attr2", "do_sth2")
mcc2 = MyChildClass2()
mcc2.attr1 = 18
mcc2.attr2 = 18
mcc2.do_sth1 = 18
mcc2.do_sth2 = 18
mcc2.attr3 = 18
56
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-20-b395fc2cfc5f> in <module>()
16 mcc2.do_sth1 = 18
17 mcc2.do_sth2 = 18
---> 18 mcc2.attr3 = 18
AttributeError: 'MyChildClass2' object has no attribute 'attr3'