python特殊成员和魔法方法

文章目录

  • 一、特殊方法
    • 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)  # >> 报错
  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值