文章目录
- 一、特殊方法
- 1. super().__ init__ ()
- 1.1 super()
- 1.2 super(). __ init __()
- 1.3 super() 在 python2、3中的区别
- 二、魔法方法
- 1. \__init__()
- 2. \__del__()
- 三、特殊成员
- 1. \__doc__()、 \__module__、\__class__
- 2. \__call__()
- 3. \__dict__()
- 4. \__str__()
- 5. \__len__()
- 6. \__iter__()
- 7. \__getitem__()、\__setitem__、\__delitem__
- 7.1 \__getitem__()
- 7.2 \__setitem__()
- 7.3 \__delitem__()
- 8. \__add__()
一、特殊方法
1. super().__ init__ ()
1.1 super()
super()即当子类和父类有相同方法时,来调用父类(基类)的方法
1.2 super(). __ init __()
如果子类B和父类A,都写了init方法,
那么A的init方法就会被B覆盖。想调用A的init方法需要用super去调用。
当然,在B内部,除了用super调用父类的方法,也可以用父类名调用,例:
class B(A):
def __init__(self):
A.__init__(self)
print("B init")
1.3 super() 在 python2、3中的区别
Python3.x 和 Python2.x 的一个区别: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
例:
python3 直接写成 : super().init()
python2 必须写成 :super(本类名,self).init()
Python3.x 实例:
class A:
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super().add(x)
b = B()
b.add(2) # 3
Python2.x 实例:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class A(object): # Python2.x 记得继承 object
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super(B, self).add(x)
b = B()
b.add(2) # 3
二、魔法方法
Python 中有大量类似__init__这种以双下划线开头和结尾的特殊成员及“魔法方法”,
它们有着非常重要的地位和作用,也是 Python 语言独具特色的语法之一!
1. _init_()
其他语言上叫构造函数,在类实例化对象的时候自动执行,功能是初始化工作。
2. _del_()
析构函数:与init相对应,用来销毁实例化对象,释放其空间。
class Cat:
def __init__(self, name):
self.name = name
print('我是一只猫,我叫%s' % self.name)
def __del__(self):
print('我被系统回收了')
cat = Cat('crystal')
print(cat)
del cat
print(cat) # print(cat)时报错
# >> 我是一只猫,我叫crystal
# >> 我被系统回收了
比如当类销毁时,需要关闭资源,可以将这部分写在__del__内。
三、特殊成员
1. _doc_()、 _module_、_class_
_doc_(): 表示类的文档,即描述信息:
_module_:当前对象所在的模块
_class_:当前对象所属的类
class Cat:
"""
这是一只猫的类
"""
def __init__(self, name):
pass
from ep07.DemoClass import Cat
cat = Cat('crystal')
print(cat.__doc__) # >> 这是一只猫的类
print(cat.__module__) # >> ep07.DemoClass
print(cat.__class__) # >> <class 'ep07.DemoClass.Cat'>
2. _call_()
是指调用:任何函数都是可以以函数名带括号来调用。
def func(a, b):
print(a+b)
func(1, 2)
那cat(1,2)是否被调用呢?结果是以下报错:
class Cat:
def __init__(self, name):
self.name = name
print('我是一只猫,我叫%s' % self.name)
def __del__(self):
print('我被系统回收了')
def __call__(self, *args, **kwargs):
print(args[0]+args[1])
cat(1,2) # >> 3
再运行cat(1,2)会输出3。cat对象就会具备像函数一样被调用的能力。
判断一个方法是否可以使用print(callable(cat))
3. _dict_()
特殊成员,展示了这个对象的成员属性。
当直接输出print(cat._dict_)时:会输出{‘name’:’crystal’}。name是实例化时赋值的
class Cat:
def __init__(self, name):
self.name = name
self.__privatename = name
print('我是一只猫,我叫%s' % self.name)
print(cat.__dict__) # >> {'name': 'crystal', '_Cat__privatename': 'crystal'}
self.__privatename是私有属性,不可以直接通过print(cat.__privatename)来访问私有属性。
可以通过print(cat._Cat__privatename),但编译器输出警告,既然保护肯定有用,不建议访问。
4. _str_()
print(str(cat)) # >> <ep07.DemoClass.Cat obiect at 0x00029C72070>
print(cat) # >> <ep07.DemoClass.Cat obiect at 0x00029C72070>
转不转字符串都是一样的输出结果。
对于实物来说打印出这些信息很不直观。更希望是打印出具体的内容,如:
print('我是 %s ' % cat.name) # >> 我是crystal
如果每次都这么输出会很麻烦。则使用到__str__:
所有类都会默认带有__str__方法。
此时在print就输出不同结果:
print(str(cat)) # >> 我是crystal
print(cat) # >> 我是crystal
5. _len_()
如果直接print(len(cat))会报错。需要加上以下代码:
class Cat:
def __init__(self, name, tail_length=10):
self.name = name
self.__privatename = name
self.taillen = tail_length
print('我是一只猫,我叫%s' % self.name)
def __del__(self):
print('我被系统回收了')
def __call__(self, *args, **kwargs):
print("cat:", args[0]+args[1])
def __str__(self):
return '我是 %s ' % cat.name
def __len__(self):
return self.taillen
print(len(cat)) # >> 10
6. _iter_()
l = [1, 2, 3]
for i in l:
print(i)
以上指列表可以被迭代iterable
但是以下会报错:
for i in cat:
print(i)
那怎么让cat可以被迭代呢?简单举个例子:
def __iter__(self):
return iter([1, 2, 3])
for i in cat:
print("cat:", i)
# 输出:
>> cat 1
>> cat 2
>> cat 3
7. _getitem_()、_setitem_、_delitem_
_getitem_()、_setitem_、_delitem_ 这三个方法就是让类对象具有像字典一样的能力:取值、赋值、删除。
之前学过对字典的访问、修改和删除等操作:
7.1 _getitem_()
dic = {'name': 'sniper', 'age': 40, 'dep': 'cccb'}
print(dic['name']) # >> sniper
dic['name'] = 'crystal'
print(dic['name']) # >> crystal
del dic['age']
print(dic) # >> {'name': 'crystal', 'age': 40, 'dep': 'cccb'}
那能否用print(cat[‘name’])方式来访问呢?
结果是报错:
TypeError:'Cat' object is not subscriptable
如果想让cat有被访问的能力,怎么做?
def __getitem__(self, key):
if key == 'name':
return self.name
else:
return None
print(cat[‘name’]) # >> crystal
7.2 _setitem_()
当需要修改时会报错:
print(cat[‘name’])
cat['name'- = 'sniper'
print(cat[‘name’])
7.3 _delitem_()
def __getitem__(self, key):
if key == 'name':
return self.name
else:
return None
def __setitem__(self, key):
if key == 'name':
self.name = value
def __delitem__(self, key):
if key == 'name':
del self.name
print(cat['name']) # >> crystal
cat['name'] = 'sniper'
print(cat['name']) # >> sniper
del cat['name']
print(cat['name']) # 报错:AttributeError: 'Cat' object has no attribute 'name'
del之后再查name就会报错。
8. _add_()
__add__() +
__sub__() -
__mul__() *
__div__() /
__mod__() %
__pow__() **
# 以下叫运算符:
x = 1
y = 2
print(x+y)
# 当我们想:
cat1 = Cat('crystal')
cat2 = Cat('Sniper', 15)
print(cat1 + cat2) # >> 报错